Mesh: improve MeshGeomFacet::IntersectWithFacet
This commit is contained in:
@@ -1036,6 +1036,15 @@ void MeshGeomFacet::SubSample (float fStep, std::vector<Base::Vector3f> &rclPoin
|
||||
rclPoints.insert(rclPoints.end(), clPoints.begin(), clPoints.end());
|
||||
}
|
||||
|
||||
bool MeshGeomFacet::IsCoplanar(const MeshGeomFacet &facet) const
|
||||
{
|
||||
const float eps = 1e-06f;
|
||||
const float unit = 0.9995f;
|
||||
float mult = fabs(this->GetNormal() * facet.GetNormal());
|
||||
float dist = fabs(DistancePlaneToPoint(facet._aclPoints[0]));
|
||||
return (mult >= unit) && (dist <= eps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fast Triangle-Triangle Intersection Test by Tomas Moeller
|
||||
* http://www.acm.org/jgt/papers/Moller97/tritri.html
|
||||
@@ -1068,6 +1077,39 @@ int MeshGeomFacet::IntersectWithFacet (const MeshGeomFacet& rclFacet,
|
||||
Base::Vector3f& rclPt0,
|
||||
Base::Vector3f& rclPt1) const
|
||||
{
|
||||
// Note: tri_tri_intersect_with_isection() does not return line of
|
||||
// intersection when triangles are coplanar. See tritritest.h:18 and 658.
|
||||
if (IsCoplanar(rclFacet)) {
|
||||
// Since tri_tri_intersect_with_isection may return garbage values try to get
|
||||
// sensible values with edge/edge intersections
|
||||
std::vector<Base::Vector3f> intersections;
|
||||
for (short i=0; i<3; i++) {
|
||||
MeshGeomEdge edge1 = GetEdge(i);
|
||||
for (short j=0; j<3; j++) {
|
||||
MeshGeomEdge edge2 = rclFacet.GetEdge(j);
|
||||
Base::Vector3f point;
|
||||
if (edge1.IntersectWithEdge(edge2, point)) {
|
||||
intersections.push_back(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If triangles overlap there can be more than two intersection points
|
||||
// In that case use any two of them.
|
||||
if (intersections.size() >= 2) {
|
||||
rclPt0 = intersections[0];
|
||||
rclPt1 = intersections[1];
|
||||
return 2;
|
||||
}
|
||||
else if (intersections.size() == 1) {
|
||||
rclPt0 = intersections[0];
|
||||
rclPt1 = intersections[0];
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float V[3][3], U[3][3];
|
||||
int coplanar = 0;
|
||||
float isectpt1[3], isectpt2[3];
|
||||
@@ -1089,45 +1131,17 @@ int MeshGeomFacet::IntersectWithFacet (const MeshGeomFacet& rclFacet,
|
||||
rclPt0.x = isectpt1[0]; rclPt0.y = isectpt1[1]; rclPt0.z = isectpt1[2];
|
||||
rclPt1.x = isectpt2[0]; rclPt1.y = isectpt2[1]; rclPt1.z = isectpt2[2];
|
||||
|
||||
// Note: tri_tri_intersect_with_isection() does not return line of
|
||||
// intersection when triangles are coplanar. See tritritest.h:18 and 658.
|
||||
if (coplanar) {
|
||||
// Since tri_tri_intersect_with_isection may return garbage values try to get
|
||||
// sensible values with edge/edge intersections
|
||||
std::vector<Base::Vector3f> intersections;
|
||||
for (short i=0; i<3; i++) {
|
||||
MeshGeomEdge edge1 = GetEdge(i);
|
||||
for (short j=0; j<3; j++) {
|
||||
MeshGeomEdge edge2 = rclFacet.GetEdge(j);
|
||||
Base::Vector3f point;
|
||||
if (edge1.IntersectWithEdge(edge2, point)) {
|
||||
intersections.push_back(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If triangles overlap there can be more than two intersection points
|
||||
// In that case use any two of them.
|
||||
if (intersections.size() >= 2) {
|
||||
rclPt0 = intersections[0];
|
||||
rclPt1 = intersections[1];
|
||||
}
|
||||
else if (intersections.size() == 1) {
|
||||
rclPt0 = intersections[0];
|
||||
rclPt1 = intersections[0];
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
// With extremely acute-angled triangles it may happen that the algorithm
|
||||
// claims an intersection but the intersection points are far outside the
|
||||
// model. So, a plausibility check is to verify that the intersection points
|
||||
// are inside the bounding boxes of both triangles.
|
||||
Base::BoundBox3f box1 = this->GetBoundBox();
|
||||
box1.Enlarge(0.001f);
|
||||
if (!box1.IsInBox(rclPt0) || !box1.IsInBox(rclPt1))
|
||||
return 0;
|
||||
|
||||
Base::BoundBox3f box2 = rclFacet.GetBoundBox();
|
||||
box2.Enlarge(0.001f);
|
||||
if (!box2.IsInBox(rclPt0) || !box2.IsInBox(rclPt1))
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -546,6 +546,10 @@ public:
|
||||
/** Apply a transformation on the triangle.
|
||||
*/
|
||||
void Transform(const Base::Matrix4D&);
|
||||
/**
|
||||
* Checks if the two triangles are coplanar.
|
||||
*/
|
||||
bool IsCoplanar(const MeshGeomFacet &facet) const;
|
||||
|
||||
protected:
|
||||
Base::Vector3f _clNormal; /**< Normal of the facet. */
|
||||
|
||||
@@ -226,6 +226,59 @@ class MeshGeoTestCases(unittest.TestCase):
|
||||
res=f1.intersect(f2)
|
||||
self.assertTrue(len(res) == 0)
|
||||
|
||||
def testIntersectionOfTransformedMesh(self):
|
||||
self.planarMesh.append( [0.0,10.0,10.0] )
|
||||
self.planarMesh.append( [10.0,0.0,10.0] )
|
||||
self.planarMesh.append( [10.0,10.0,10.0] )
|
||||
self.planarMesh.append( [6.0,8.0,10.0] )
|
||||
self.planarMesh.append( [16.0,8.0,10.0] )
|
||||
self.planarMesh.append( [6.0,18.0,10.0] )
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
|
||||
mat = Base.Matrix()
|
||||
mat.rotateX(1.0)
|
||||
mat.rotateY(1.0)
|
||||
mat.rotateZ(1.0)
|
||||
planarMeshObject.transformGeometry(mat)
|
||||
|
||||
f1 = planarMeshObject.Facets[0]
|
||||
f2 = planarMeshObject.Facets[1]
|
||||
res=f1.intersect(f2)
|
||||
self.assertEqual(len(res), 2)
|
||||
|
||||
def testIntersectionOfParallelTriangles(self):
|
||||
self.planarMesh.append( [0.0,10.0,10.0] )
|
||||
self.planarMesh.append( [10.0,0.0,10.0] )
|
||||
self.planarMesh.append( [10.0,10.0,10.0] )
|
||||
self.planarMesh.append( [6.0,8.0,10.1] )
|
||||
self.planarMesh.append( [16.0,8.0,10.1] )
|
||||
self.planarMesh.append( [6.0,18.0,10.1] )
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
|
||||
mat = Base.Matrix()
|
||||
mat.rotateX(1.0)
|
||||
mat.rotateY(1.0)
|
||||
mat.rotateZ(1.0)
|
||||
planarMeshObject.transformGeometry(mat)
|
||||
|
||||
f1 = planarMeshObject.Facets[0]
|
||||
f2 = planarMeshObject.Facets[1]
|
||||
res=f1.intersect(f2)
|
||||
self.assertTrue(len(res) == 0)
|
||||
|
||||
def testIntersectionOnEdge(self):
|
||||
self.planarMesh.append( [5.0, -1.9371663331985474, 0.49737977981567383] )
|
||||
self.planarMesh.append( [4.0, -1.9371663331985474, 0.49737977981567383] )
|
||||
self.planarMesh.append( [5.0, -1.9842294454574585, 0.25066646933555603] )
|
||||
self.planarMesh.append( [4.6488823890686035, -1.7827962636947632, 0.4577442705631256] )
|
||||
self.planarMesh.append( [4.524135112762451, -2.0620131492614746, 0.5294350385665894] )
|
||||
self.planarMesh.append( [4.6488823890686035, -1.8261089324951172, 0.23069120943546295] )
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
f1 = planarMeshObject.Facets[0]
|
||||
f2 = planarMeshObject.Facets[1]
|
||||
res = f1.intersect(f2)
|
||||
self.assertEqual(len(res), 2)
|
||||
|
||||
def testIntersectionCoplanar(self):
|
||||
self.planarMesh.append( [0.,10.,10.] )
|
||||
self.planarMesh.append( [10.,0.,10.] )
|
||||
|
||||
Reference in New Issue
Block a user