DavAndLar
(DavAndLar)
June 27, 2024, 8:05am
1
Dear forum,
After some debugging I have come to realise that computing the centroid of a brep using
AreaMassProperties.Compute
takes a lot of time, even though I only set firstMoment to true
.
I am wondering if there is an alternative way to AreaMassProperties for getting the centroid of a brep? The Brep is very spatial, thus using the bounding box is not an option.
Thanks,
david
As Plan B : Try converting the Brep(s) to Mesh(es) and then use something like this:
public Point3d MeshCentroid(Mesh M){
M.Faces.ConvertQuadsToTriangles();
double meshVolume = 0;
Point3d temp = new Point3d (0, 0, 0);
var MTV = M.TopologyVertices;
var MF = M.Faces;
for(int i = 0; i < MF.Count;i++){
int[] adjV = MTV.IndicesFromFace(i);
Point3d[] V = new Point3d[adjV.Length];
for(int j = 0; j < adjV.Length;j++) V[j] = MTV[adjV[j]];
Point3d center = (V[0] + V[1] + V[2]) / 4;
double volume = DotProduct((Vector3d) V[0], CrossProduct((Vector3d) V[1], (Vector3d) V[2])) / 6;
meshVolume += volume;
temp += center * volume;
}
return temp / meshVolume;
}
public double DotProduct(Vector3d v1, Vector3d v2){
double dot = (v1.X * v2.X) + (v1.Y * v2.Y) + (v1.Z * v2.Z);
return dot;
}
public Vector3d CrossProduct(Vector3d V1, Vector3d V2){
Vector3d cross = new Vector3d (
(V1.Y * V2.Z - V1.Z * V2.Y),
(V1.Z * V2.X - V1.X * V2.Z),
(V1.X * V2.Y - V1.Y * V2.X));
return cross;
}
dale
(Dale Fugier)
June 27, 2024, 6:53pm
3
Hi @DavAndLar ,
Use the à la carte version of AreaMassProperties.Compute . Specify true
for area
and firstMoments
, false
for the other moments.
– Dale
DavAndLar
(DavAndLar)
June 28, 2024, 6:44am
4
Hi @dale , that’s what I’m doing atm. However, I found that it was even ok specify false
for area
. But still, it takes a while to compute, that’s why I was looking for an alternative.
best,
david
I tried your code @PeterFotiadis and it returns a Null Point
. Any idea of why that is?
-david
DavAndLar:
Any idea of why that is?
Quite strange (given a valid and manifold Mesh as a result from converting a valid and manifold Brep). Anyway post (in R5 format) the input Brep (or Breps).
Atm I’m just trying out the code on a planar rectangle, i.e. no fancy Brep to be shared.
This is how I’ve implemented the code:
private void RunScript(Brep x, ref object a)
{
Mesh[] myMesh = Rhino.Geometry.Mesh.CreateFromBrep(x);
a = MeshCentroid(myMesh[0]);
}
public Point3d MeshCentroid(Mesh M){
M.Faces.ConvertQuadsToTriangles();
double meshVolume = 0;
Point3d temp = new Point3d (0, 0, 0);
var MTV = M.TopologyVertices;
var MF = M.Faces;
for(int i = 0; i < MF.Count;i++){
int[] adjV = MTV.IndicesFromFace(i);
Point3d[] V = new Point3d[adjV.Length];
for(int j = 0; j < adjV.Length;j++) V[j] = MTV[adjV[j]];
Point3d center = (V[0] + V[1] + V[2]) / 4;
double volume = DotProduct((Vector3d) V[0], CrossProduct((Vector3d) V[1], (Vector3d) V[2])) / 6;
meshVolume += volume;
temp += center * volume;
}
return temp / meshVolume;
}
public double DotProduct(Vector3d v1, Vector3d v2){
double dot = (v1.X * v2.X) + (v1.Y * v2.Y) + (v1.Z * v2.Z);
return dot;
}
public Vector3d CrossProduct(Vector3d V1, Vector3d V2){
Vector3d cross = new Vector3d (
(V1.Y * V2.Z - V1.Z * V2.Y),
(V1.Z * V2.X - V1.X * V2.Z),
(V1.X * V2.Y - V1.Y * V2.X));
return cross;
}
Code provided works on closed Meshes (i.e. where Volume has meaning). Spot the meshVolume - as double - used.