As I mentioned, my tollerance is actually very high, I don't need 100% correlation,
my application doesn't require such high precision. I'm not sure which methods in
the Revit API are the most suitable to convert the object's geometry to
(x,y,z) points array.
The collections can be all the Column instances in the models represented by x,y,z points array, which can be run against each other.
@RPTHOMAS108 what do you think about the below implimentation?
Element element = myElement;
//use the GetGeometryObjectFromReference method to get a GeometryObject for the element
GeometryObject geomObject = element.GetGeometryObjectFromReference(new Options());
// Create a list to store the points
List<XYZ> points = new List<XYZ>();
// If the GeometryObject is a Solid, use the Faces property to get a list of faces
if (geomObject is Solid solid)
{
FaceArray faces = solid.Faces;
// Iterate over the faces and get the vertices for each face
foreach (Face face in faces)
{
// Use the Tessellate method to get a list of tessellated points
Mesh mesh = face.Triangulate();
// Iterate over the tessellated points and add them to the list
foreach (XYZ point in mesh.Vertices)
{
points.Add(point);
}
}
}
// If the GeometryObject is a curve, use the Tessellate method to get a list of tessellated points
else if (geomObject is Curve curve)
{
// Use the Tessellate method to get a list of tessellated points
IList<XYZ> tessellatedPoints = curve.Tessellate();
// Iterate over the tessellated points and add them to the list
foreach (XYZ point in tessellatedPoints)
{
points.Add(point);
}
}
// If the GeometryObject is a surface, use the Triangulate method to get a list of triangles
else if (geomObject is Surface surface)
{
// Use the Triangulate method to get a list of triangles
IList<Polygon> triangles = surface.Triangulate();
// Iterate over the triangles and add the vertices to the list
foreach (Polygon triangle in triangles)
{
points.AddRange(triangle.ToList());
}
}
public static double ComputeCollectionCoerrealtion(List<List<(int x, int y, int z)>> collection1, List<List<(int x, int y, int z)>> collection2)
{
double totalVolumeCorrelation = 0;
for (int i = 0; i < collection1.Count; i++)
{
for (int j = 0; j < collection2.Count; j++)
{
double volumeCorrelation = ComputeVolumeCorrelation(collection1[i], collection2[j]);
totalVolumeCorrelation += volumeCorrelation;
}
}
// Compute the percentage of volume correlation between the two collections
int numObjectPairs = collection1.Count * collection2.Count;
double percentVolumeCorrelation = totalVolumeCorrelation / numObjectPairs * 100;
return percentVolumeCorrelation;
}
public static double ComputeVolumeCorrelation(List<(int x, int y, int z)> object1, List<(int x, int y, int z)> object2)
{
// Create 3D arrays to store the voxel data for the two objects
bool[,,] object1Voxels = CreateObjectVoxels(object1);
bool[,,] object2Voxels = CreateObjectVoxels(object2);
// Iterate over the points in each object and set the corresponding voxels to True
foreach ((int x, int y, int z) in object1)
{
object1Voxels[x, y, z] = true;
}
foreach ((int x, int y, int z) in object2)
{
object2Voxels[x, y, z] = true;
}
// Compute the intersection volume of the two objects
int intersectionVolume = 0;
for (int x = 0; x < object1Voxels.GetLength(0); x++)
{
for (int y = 0; y < object1Voxels.GetLength(1); y++)
{
for (int z = 0; z < object1Voxels.GetLength(2); z++)
{
if (object1Voxels[x, y, z] && object2Voxels[x, y, z])
{
intersectionVolume++;
}
}
}
}
// Compute the volumes of the two objects
int object1Volume = 0;
for (int x = 0; x < object1Voxels.GetLength(0); x++)
{
for (int y = 0; y < object1Voxels.GetLength(1); y++)
{
for (int z = 0; z < object1Voxels.GetLength(2); z++)
{
if (object1Voxels[x, y, z])
{
object1Volume++;
}
}
}
}
int object2Volume = 0;
for (int x = 0; x < object2Voxels.GetLength(0); x++)
{
for (int y = 0; y < object2Voxels.GetLength(1); y++)
{
for (int z = 0; z < object2Voxels.GetLength(2); z++)
{
if (object2Voxels[x, y, z])
{
object2Volume++;
}
}
}
}
// Compute the volume correlation
double volumeCorrelation = (double)intersectionVolume / Math.Min(object1Volume, object2Volume);
return volumeCorrelation;
}
public static bool[,,] CreateObjectVoxels(List<(int x, int y, int z)> points)
{
// Find the minimum and maximum x, y, and z coordinates of the points in the object
int minX = int.MaxValue;
int minY = int.MaxValue;
int minZ = int.MaxValue;
int maxX = int.MinValue;
int maxY = int.MinValue;
int maxZ = int.MinValue;
foreach ((int x, int y, int z) in points)
{
minX = Math.Min(minX, x);
minY = Math.Min(minY, y);
minZ = Math.Min(minZ, z);
maxX = Math.Max(maxX, x);
maxY = Math.Max(maxY, y);
maxZ = Math.Max(maxZ, z);
}
// Calculate the dimensions of the 3D array needed to represent the object
int width = maxX - minX + 1;
int height = maxY - minY + 1;
int depth = maxZ - minZ + 1;
// Create the 3D array and initialize all elements to False
bool[,,] voxels = new bool[width, height, depth];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
for (int z = 0; z < depth; z++)
{
voxels[x, y, z] = false;
}
}
}
// Set the elements corresponding to the points in the object to True
foreach ((int x, int y, int z) in points)
{
voxels[x - minX, y - minY, z - minZ] = true;
}
return voxels;
}