Ejemplo n.º 1
0
        /// <summary>
        /// 构造直线,为两平面的交线
        /// </summary>
        public Line(Face face1, Face face2)
        {
            Vector3Double normalFace1 = face1.PlaneNormal;
            Vector3Double normalFace2 = face2.PlaneNormal;

            Direction = Vector3Double.Cross(normalFace1, normalFace2);

            if (!(Direction.magnitude < EqualityTolerance))  // 两平面不平行
            {
                //getting a line point, zero is set to a coordinate whose direction
                // 获取线上一点,方向坐标设为零点
                //component isn't zero (line intersecting its origin plan)
                // 成员不为零(线与第一个平面相交)
                var d1 = -Vector3Double.Dot(normalFace1, face1.v1.Position);
                var d2 = -Vector3Double.Dot(normalFace2, face2.v1.Position);
                if (Math.Abs(Direction.x) > EqualityTolerance)
                {
                    startPoint = new Vector3Double
                    {
                        x = 0,
                        y = (d2 * normalFace1.z - d1 * normalFace2.z) / Direction.x,
                        z = (d1 * normalFace2.y - d2 * normalFace1.y) / Direction.x
                    };
                }
                else if (Math.Abs(Direction.y) > EqualityTolerance)
                {
                    startPoint = new Vector3Double
                    {
                        x = (d1 * normalFace2.z - d2 * normalFace1.z) / Direction.y,
                        y = 0,
                        z = (d2 * normalFace1.x - d1 * normalFace2.x) / Direction.y
                    };
                }
                else
                {
                    startPoint = new Vector3Double
                    {
                        x = (d2 * normalFace1.y - d1 * normalFace2.y) / Direction.z,
                        y = (d1 * normalFace2.x - d2 * normalFace1.x) / Direction.z,
                        z = 0
                    };
                }
            }
            else
            {
                startPoint = default;
            }
            Direction.Normalize();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Compute the point resulting from the intersection with a plane
        /// </summary>
        /// <param name="normal">the plane normal</param>
        /// <param name="planePoint">a plane point.</param>
        /// <returns>intersection point.If they don't intersect, return null</returns>
        public Vector3Double ComputePlaneIntersection(Plane plane)
        {
            var distanceToStartFromOrigin = Vector3Double.Dot(plane.planeNormal, startPoint);

            var distanceFromPlane = distanceToStartFromOrigin - plane.distanceToPlaneFromOrigin;
            var denominator       = Vector3Double.Dot(plane.planeNormal, Direction);

            if (Math.Abs(denominator) < EqualityTolerance)  // 射线与平面垂直
            {
                return(Math.Abs(distanceFromPlane) < EqualityTolerance ? startPoint : Vector3Double.PositiveInfinity);
            }
            else // 射线被平面拦截
            {
                return(StartPoint + (Direction * -distanceFromPlane / denominator));
            }
        }
Ejemplo n.º 3
0
        /// <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;
                }                                                      // 不重合,反向,在参数物件外部
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// 计算从线到另一点的距离
        /// </summary>
        /// <param name="otherPoint">the point to compute the distance from the line point. The point is supposed to be on the same line.</param>
        /// <returns>如果射线起点到另一点的向量与射线方向相反,会得到负数的值</returns>
        public double ComputePointToPointDistance(Vector3Double otherPoint)
        {
            var distance = (otherPoint - startPoint).magnitude;

            return((Vector3Double.Dot((otherPoint - startPoint).normalized, Direction) < 0) ? -distance : distance);
        }