Add methods to get intersections of mesh edges, project point on edge

This commit is contained in:
wmayer
2019-06-27 19:27:12 +02:00
parent 5fb22278e8
commit c5e400cd38
2 changed files with 110 additions and 0 deletions

View File

@@ -225,6 +225,100 @@ bool MeshGeomEdge::IntersectBoundingBox (const Base::BoundBox3f &rclBB) const
return intrsectbox.Test();
}
bool MeshGeomEdge::IntersectWithLine (const Base::Vector3f &rclPt,
const Base::Vector3f &rclDir,
Base::Vector3f &rclRes) const
{
const float eps = 1e-06f;
Base::Vector3f n = _aclPoints[1] - _aclPoints[0];
// check angle between edge and the line direction, FLOAT_MAX is
// returned for degenerated edges
float fAngle = rclDir.GetAngle(n);
if (fAngle == 0) {
// parallel lines
float distance = _aclPoints[0].DistanceToLine(rclPt, rclDir);
if (distance < eps) {
// lines are equal
rclRes = _aclPoints[0];
return true;
}
return false; // no intersection possible
}
// that's the normal of a helper plane and its base at _aclPoints
Base::Vector3f normal = n.Cross(rclDir);
// if the distance of rclPt to the plane is higher than eps then the
// two lines are warped and there is no intersection possible
if (fabs(rclPt.DistanceToPlane(_aclPoints[0], normal)) > eps)
return false;
// get a second helper plane and get the intersection with the line
Base::Vector3f normal2 = normal.Cross(n);
float s = ((_aclPoints[0] - rclPt) * normal2) / (rclDir * normal2);
rclRes = rclPt + s * rclDir;
float dist1 = Base::Distance(_aclPoints[0], _aclPoints[1]);
float dist2 = Base::Distance(_aclPoints[0], rclRes);
float dist3 = Base::Distance(_aclPoints[1], rclRes);
return dist2 + dist3 <= dist1 + eps;
}
void MeshGeomEdge::ProjectPointToLine (const Base::Vector3f &rclPoint,
Base::Vector3f &rclProj) const
{
Base::Vector3f pt1 = rclPoint - _aclPoints[0];
Base::Vector3f dir = _aclPoints[1] - _aclPoints[0];
Base::Vector3f vec;
vec.ProjectToLine(pt1, dir);
rclProj = rclPoint + vec;
}
void MeshGeomEdge::ClosestPointsToLine(const Base::Vector3f &linePt, const Base::Vector3f &lineDir,
Base::Vector3f& rclPnt1, Base::Vector3f& rclPnt2) const
{
const float eps = 1e-06f;
Base::Vector3f edgeDir = _aclPoints[1] - _aclPoints[0];
// check angle between edge and the line direction, FLOAT_MAX is
// returned for degenerated edges
float fAngle = lineDir.GetAngle(edgeDir);
if (fAngle == 0) {
// parallel lines
float distance = _aclPoints[0].DistanceToLine(linePt, lineDir);
if (distance < eps) {
// lines are equal
rclPnt1 = _aclPoints[0];
rclPnt2 = _aclPoints[0];
}
else {
rclPnt1 = _aclPoints[0];
MeshGeomEdge edge;
edge._aclPoints[0] = linePt;
edge._aclPoints[1] = linePt + lineDir;
edge.ProjectPointToLine(rclPnt1, rclPnt2);
}
}
else {
// that's the normal of a helper plane
Base::Vector3f normal = edgeDir.Cross(lineDir);
// get a second helper plane and get the intersection with the line
Base::Vector3f normal2 = normal.Cross(edgeDir);
float s = ((_aclPoints[0] - linePt) * normal2) / (lineDir * normal2);
rclPnt2 = linePt + s * lineDir;
// get a third helper plane and get the intersection with the line
Base::Vector3f normal3 = normal.Cross(lineDir);
float t = ((linePt - _aclPoints[0]) * normal3) / (edgeDir * normal3);
rclPnt1 = _aclPoints[0] + t * edgeDir;
}
}
// -----------------------------------------------------------------
MeshGeomFacet::MeshGeomFacet (void)

View File

@@ -164,6 +164,22 @@ public:
Base::BoundBox3f GetBoundBox () const;
/** Checks if the edge intersects with the given bounding box. */
bool IntersectBoundingBox (const Base::BoundBox3f &rclBB) const;
/** Calculates the intersection point of the line defined by the base \a rclPt and the direction \a rclDir
* with the edge. The intersection must be inside the edge. If there is no intersection false is returned.
*/
bool IntersectWithLine (const Base::Vector3f &rclPt, const Base::Vector3f &rclDir, Base::Vector3f &rclRes) const;
/**
* Calculates the projection of a point onto the line defined by the edge. The caller must check if
* the projection point is inside the edge.
*/
void ProjectPointToLine (const Base::Vector3f &rclPoint, Base::Vector3f &rclProj) const;
/**
* Get the closest points \a rclPnt1 and \a rclPnt2 of the line defined by this edge and the line
* defined by \a rclPt and \a rclDir.
* If the two points are identical then both lines intersect each other.
*/
void ClosestPointsToLine(const Base::Vector3f &linePt, const Base::Vector3f &lineDir,
Base::Vector3f& rclPnt1, Base::Vector3f& rclPnt2) const;
public:
Base::Vector3f _aclPoints[2]; /**< Corner points */