//---------------------------------PRIVATES-------------------------------------// /** * Sets an end as vertex (starting point if none end were defined, ending point otherwise) * * @param vertex the vertex that is an segment end * @return false if all the ends were already defined, true otherwise */ private bool SetVertex(Vertex vertex) { //none end were defined - define starting point as VERTEX if (index == 0) { startVertex = vertex; startType = VERTEX; StartDist = line.ComputePointToPointDistance(vertex.GetPosition()); startPos = startVertex.GetPosition(); index++; return(true); } //starting point were defined - define ending point as VERTEX if (index == 1) { endVertex = vertex; endType = VERTEX; endDist = line.ComputePointToPointDistance(vertex.GetPosition()); endPos = endVertex.GetPosition(); index++; //defining middle based on the starting point //VERTEX-VERTEX-VERTEX if (startVertex.Equals(endVertex)) { middleType = VERTEX; } //VERTEX-EDGE-VERTEX else if (startType == VERTEX) { middleType = EDGE; } //the ending point distance should be smaller than starting point distance if (StartDist > endDist) { SwapEnds(); } return(true); } else { return(false); } }
//---------------------------------PRIVATES-------------------------------------// /** * Sets an end as vertex (starting point if none end were defined, ending point otherwise) * * @param vertex the vertex that is an segment end * @return false if all the ends were already defined, true otherwise */ private bool SetVertex(Vertex vertex) { //none end were defined - define starting point as VERTEX if (NumEndsSet == 0) { StartVertex = vertex; StartType = VERTEX; StartDistance = line.ComputePointToPointDistance(vertex.Position); StartPosition = StartVertex.Position; NumEndsSet++; return(true); } //starting point were defined - define ending point as VERTEX if (NumEndsSet == 1) { EndVertex = vertex; EndType = VERTEX; EndDistance = line.ComputePointToPointDistance(vertex.Position); EndPosition = EndVertex.Position; NumEndsSet++; //defining middle based on the starting point //VERTEX-VERTEX-VERTEX if (StartVertex.Equals(EndVertex)) { IntermediateType = VERTEX; } //VERTEX-EDGE-VERTEX else if (StartType == VERTEX) { IntermediateType = EDGE; } //the ending point distance should be smaller than starting point distance if (StartDistance > EndDistance) { SwapEnds(); } return(true); } else { return(false); } }
//---------------------------------PRIVATES-------------------------------------// /** * Sets an end as vertex (starting point if none end were defined, ending point otherwise) * * @param vertex the vertex that is an segment end * @return false if all the ends were already defined, true otherwise */ private bool SetVertex(Vertex vertex) { //none end were defined - define starting point as VERTEX if (_Index == 0) { _StartVertex = vertex; _StartType = VERTEX; StartDist = Line.ComputePointToPointDistance(vertex.Position); _StartPos = _StartVertex.Position; _Index++; return(true); } //starting point were defined - define ending point as VERTEX if (_Index == 1) { _EndVertex = vertex; _EndType = VERTEX; _EndDist = Line.ComputePointToPointDistance(vertex.Position); _EndPos = _EndVertex.Position; _Index++; //defining middle based on the starting point //VERTEX-VERTEX-VERTEX if (_StartVertex.Equals(_EndVertex)) { _MiddleType = VERTEX; } //VERTEX-EDGE-VERTEX else if (_StartType == VERTEX) { _MiddleType = EDGE; } //the ending point distance should be smaller than starting point distance if (StartDist > _EndDist) { SwapEnds(); } return(true); } else { return(false); } }
/// <summary> /// Classifies the face based on the ray trace technique /// </summary> /// <param name="obj">object3d used to compute the face status</param> public void RayTraceClassify(Object3D obj) { //creating a ray starting at the face baricenter going to the normal direction Line ray = new Line(GetNormal(), center); bool success; double distance; Vector3 intersectionPoint; Face closestFace = null; double closestDistance; do { success = true; closestDistance = Double.MaxValue; //for each face from the other solid... for (int faceIndex = 0; faceIndex < obj.GetNumFaces(); faceIndex++) { Face face = obj.GetFace(faceIndex); intersectionPoint = ray.ComputePlaneIntersection(face.GetPlane()); //if ray intersects the plane... if (intersectionPoint.x != double.PositiveInfinity) { double dotProduct = Vector3.Dot(face.GetNormal(), ray.Direction); distance = ray.ComputePointToPointDistance(intersectionPoint); //if ray lies in plane... if (Math.Abs(distance) < EqualityTolerance && Math.Abs(dotProduct) < EqualityTolerance) { //disturb the ray in order to not lie into another plane ray.PerturbDirection(); success = false; break; } //if ray starts in plane... if (Math.Abs(distance) < EqualityTolerance && Math.Abs(dotProduct) > EqualityTolerance) { //if ray intersects the face... if (face.ContainsPoint(intersectionPoint)) { //faces coincide closestFace = face; closestDistance = 0; break; } } //if ray intersects plane... else if (Math.Abs(dotProduct) > EqualityTolerance && distance > EqualityTolerance) { if (distance < closestDistance) { //if ray intersects the face; if (face.ContainsPoint(intersectionPoint)) { //this face is the closest face until now closestDistance = distance; closestFace = face; } } } } } } while (success == false); if (closestFace == null) { //none face found: outside face status = Status.OUTSIDE; } else //face found: test dot product { double dotProduct = Vector3.Dot(closestFace.GetNormal(), ray.Direction); //distance = 0: coplanar faces if (Math.Abs(closestDistance) < EqualityTolerance) { if (dotProduct > EqualityTolerance) { status = Status.SAME; } else if (dotProduct < -EqualityTolerance) { status = Status.OPPOSITE; } } else if (dotProduct > EqualityTolerance) { //dot product > 0 (same direction): inside face status = Status.INSIDE; } else if (dotProduct < -EqualityTolerance) { //dot product < 0 (opposite direction): outside face status = Status.OUTSIDE; } } }
/// <summary> /// 为表面分类,基于光线追踪技术 /// </summary> /// <param name="obj">计算面状态的 3D 物件</param> public void RayTraceClassify(Object3D obj) { Line ray = new Line(PlaneNormal, Center); // 射线从面的几何中心发出,方向为法线方向 Face closet = default; bool foundCloset = false; double closestDistance; bool success; do { success = true; closestDistance = double.MaxValue; for (int faceIndex = 0; faceIndex < obj.GetNumFaces(); faceIndex++) { Face face = obj.GetFace(faceIndex); var intersectionPoint = ray.ComputePlaneIntersection(face.Plane); // 对三角面所在的平面采样 if (intersectionPoint.x < float.PositiveInfinity) // 射线被平面拦截 { var distance = ray.ComputePointToPointDistance(intersectionPoint); var dot = Vector3Double.Dot(face.PlaneNormal, ray.Direction); bool parallel = Math.Abs(dot) < epsilon; // 射线与平面平行 //if ray lies in plane... if (Math.Abs(distance) < epsilon) // 交点是射线起点 { if (parallel) { // 略微抖动光线方向以免采样到另一平面 ray.PerturbDirection(); success = false; break; } else if (face.ContainsPoint(intersectionPoint)) { // 面重合 closet = face; foundCloset = true; closestDistance = 0; break; } } else if (!parallel && distance > epsilon) // 射线产生交点 { if (distance < closestDistance && face.ContainsPoint(intersectionPoint)) { closestDistance = distance; closet = face; // 当前的面时最近的平面 foundCloset = true; } } } } } while (!success); if (!foundCloset) { Status = Status.OUTSIDE; } // 没有找到面,自己是外部面 else // 由离自己最近的面,检查方向 { var dot = Vector3Double.Dot(closet.PlaneNormal, ray.Direction); if (Math.Abs(closestDistance) < epsilon) // 距离为零,这个面和自己重合 { if (dot > epsilon) { Status = Status.SAME; } else if (dot < -epsilon) { Status = Status.OPPOSITE; } } else if (dot > epsilon) { Status = Status.INSIDE; } // 不重合,同向,在参数物件内部 else if (dot < -epsilon) { Status = Status.OUTSIDE; } // 不重合,反向,在参数物件外部 } }