public void FindIntersectionTest(Vector2 l1_p1, Vector2 l1_p2, Vector2 l2_p1, Vector2 l2_p2,
                                         int expectedIntersectionType, IntersectionResult expectedIntersectionResult)
        {
            int intersectionType = UnityVectorExtensions.FindIntersection(l1_p1, l1_p2, l2_p1, l2_p2,
                                                                          out Vector2 intersection);

            Assert.That(intersectionType, Is.EqualTo(expectedIntersectionType));
            switch (expectedIntersectionResult)
            {
            case IntersectionResult.Zero:
                Assert.That(intersection, Is.EqualTo(Vector2.zero).Using(Vector2EqualityComparer.Instance));
                break;

            case IntersectionResult.Infinity:
                Assert.That(float.IsInfinity(intersection.x), Is.True);
                Assert.That(float.IsInfinity(intersection.y), Is.True);
                break;

            case IntersectionResult.l1_p1:
                Assert.That(intersection, Is.EqualTo(l1_p1).Using(Vector2EqualityComparer.Instance));
                break;

            case IntersectionResult.l1_p2:
                Assert.That(intersection, Is.EqualTo(l1_p2).Using(Vector2EqualityComparer.Instance));
                break;

            case IntersectionResult.l2_p1:
                Assert.That(intersection, Is.EqualTo(l2_p1).Using(Vector2EqualityComparer.Instance));
                break;

            case IntersectionResult.l2_p2:
                Assert.That(intersection, Is.EqualTo(l2_p2).Using(Vector2EqualityComparer.Instance));
                break;
            }
        }
Beispiel #2
0
 protected override void OnPolygonComplete(Polygon2f input)
 {
     polygon = input;
     polygon.BuildIndices();
     polygon.BuildHoleIndices();
     result = null;
 }
        // If N0 and N1 are parallel, either the planes are parallel and separated
        // or the same plane.  In both cases, 'false' is returned.  Otherwise,
        // the intersection line is
        //   L(t) = t*Cross(N0,N1)/|Cross(N0,N1)| + c0*N0 + c1*N1
        // for some coefficients c0 and c1 and for t any real number (the line
        // parameter).  Taking dot products with the normals,
        //   d0 = Dot(N0,L) = c0*Dot(N0,N0) + c1*Dot(N0,N1) = c0 + c1*d
        //   d1 = Dot(N1,L) = c0*Dot(N0,N1) + c1*Dot(N1,N1) = c0*d + c1
        // where d = Dot(N0,N1).  These are two equations in two unknowns.  The
        // solution is
        //   c0 = (d0 - d*d1)/det
        //   c1 = (d1 - d*d0)/det
        // where det = 1 - d^2.
        public bool Find()
        {
            if (Result != IntersectionResult.NotComputed)
            {
                return(Result != IntersectionResult.NoIntersection);
            }

            double dot = plane0.Normal.Dot(plane1.Normal);

            if (Math.Abs(dot) >= 1 - MathUtil.ZeroTolerance)
            {
                double cDiff = dot >= 0 ? Plane0.Constant - Plane1.Constant : Plane0.Constant + Plane1.Constant;

                if (Math.Abs(cDiff) < MathUtil.ZeroTolerance)
                {
                    Type   = IntersectionType.Plane;
                    Result = IntersectionResult.NoIntersection;
                    Plane  = new Plane3d(plane0.Normal, plane0.Constant);
                }

                Type   = IntersectionType.Empty;
                Result = IntersectionResult.NoIntersection;
                return(false);
            }

            double invDet = 1 / (1 - dot * dot);
            double c0     = (plane0.Constant - dot * plane1.Constant) * invDet;
            double c1     = (plane1.Constant - dot * plane0.Constant) * invDet;

            Quantity = 1;
            Type     = IntersectionType.Line;
            Line     = new Line3d(c0 * plane0.Normal + c1 * plane1.Normal, plane0.Normal.UnitCross(plane1.Normal));
            return(true);
        }
Beispiel #4
0
        //求出轴网和基准线的相交点,以点的位置比例和轴网建立字典
        public IDictionary <double, Grid> GetInterGridDict(IList <Element> girdsElements, Line baseCurve)
        {
            IDictionary <double, Grid> dictParaGrid = new Dictionary <double, Grid>(); //创建字典,double为相交点在基准线上的比例位置, Grid为相交轴线

            foreach (Element ele in girdsElements)                                     //求出各个轴网与所画直线的关系
            {
                Grid   grid_tmep          = ele as Grid;
                Line   grid_curve         = grid_tmep.Curve as Line;
                XYZ    direction          = grid_curve.Direction;
                XYZ    middleXyz          = (grid_curve.GetEndPoint(0) + grid_curve.GetEndPoint(1)) / 2;//求出线段的中点
                double d                  = 10000;
                XYZ    startPoint         = middleXyz + direction * d;
                XYZ    endPoint           = middleXyz - direction * d;
                Line   grid_curve_newLine = Line.CreateBound(startPoint, endPoint);
                IntersectionResultArray results;
                SetComparisonResult     result = baseCurve.Intersect(grid_curve_newLine, out results);
                if (result == SetComparisonResult.Overlap)    //判断基准线是否与轴网相交
                {
                    if (results != null && results.Size == 1) //判断交点的数量是否为1
                    {
                        double             intersectPara;
                        IntersectionResult iResult    = results.get_Item(0);             //发现无法直接获取相交点在基准线上的二维比例位置
                        XYZ intersectXYZ              = iResult.XYZPoint;                //得到基准线和轴网的交点
                        IntersectionResult projectXyz = baseCurve.Project(intersectXYZ); //获得交点在基准线上的投影点
                        intersectPara = projectXyz.Parameter;                            //将投影点转化为在基准线上的一维距离比例位置
                        dictParaGrid.Add(intersectPara, grid_tmep);
                    }
                }
            }
            return(dictParaGrid);
        }
Beispiel #5
0
        public void DoorRenumbering(Curve curve)
        {
            List <LocationPoint> points = new List <LocationPoint>();

            Dictionary <Element, double> sort = new Dictionary <Element, double>();

            foreach (Element element in elements)
            {
                FamilyInstance door = element as FamilyInstance;

                XYZ point = door.GetTransform().Origin;

                if (point == null)
                {
                    continue;
                }

                IntersectionResult closestPoint = curve.Project(point);

                sort.Add(element, curve.ComputeNormalizedParameter(closestPoint.Parameter));
            }

            List <Element> sorted = sort.OrderBy(x => x.Value).Select(x => x.Key).ToList();

            using (Transaction t = new Transaction(doc, "Rename Mark Values"))
            {
                t.Start();
                foreach (Element el in sorted)
                {
                    el.LookupParameter("Mark").Set(String.Format("{0}{1}{2}", prefix, increment.ToString(format), suffix));
                    increment++;
                }
                t.Commit();
            }
        }
Beispiel #6
0
    /// <summary>
    /// 两射线求交点
    /// </summary>
    /// <param name="rayOrigin1"></param>
    /// <param name="rayDirection1"></param>
    /// <param name="rayOrigin2"></param>
    /// <param name="rayDirection2"></param>
    /// <returns></returns>
    public static IntersectionResult RayToRayIntersection(Vector2 rayOrigin1, Vector2 rayDirection1, Vector2 rayOrigin2, Vector2 rayDirection2)
    {
        IntersectionResult result = new IntersectionResult();

        rayDirection1 = rayDirection1.normalized;
        rayDirection2 = rayDirection2.normalized;

        float r, s, d;

        if (rayDirection1 != rayDirection2)
        {
            d = Cross(rayDirection1, rayDirection2);
            if (d != 0)
            {
                Vector2 rayOrigin2ToRayOrigin1 = rayOrigin1 - rayOrigin2;
                r = Cross(rayDirection2, rayOrigin2ToRayOrigin1) / d;
                s = Cross(rayDirection1, rayOrigin2ToRayOrigin1) / d;
                if (r >= 0)
                {
                    if (s >= 0)
                    {
                        Vector2 intersectionPoint = rayOrigin1 + rayDirection1 * r;
                        result.AddIntersectionPoint(intersectionPoint);
                    }
                }
            }
        }
        return(result);
    }
Beispiel #7
0
        public bool Find()
        {
            if (Result != IntersectionResult.NotComputed)
            {
                return(Result == IntersectionResult.Intersects);
            }

            // [RMS] if either line direction is not a normalized vector,
            //   results are garbage, so fail query
            if (segment.Direction.IsNormalized == false)
            {
                Type   = IntersectionType.Empty;
                Result = IntersectionResult.InvalidQuery;
                return(false);
            }

            SegmentParam0 = -segment.Extent;
            SegmentParam1 = segment.Extent;
            DoClipping(ref SegmentParam0, ref SegmentParam1, segment.Center, segment.Direction, box,
                       solid, ref Quantity, ref Point0, ref Point1, ref Type);

            Result = (Type != IntersectionType.Empty) ?
                     IntersectionResult.Intersects : IntersectionResult.NoIntersection;
            return(Result == IntersectionResult.Intersects);
        }
Beispiel #8
0
        private void GetIntersectionPoints()
        {
            IntersectionResultArray iresArray1;
            SetComparisonResult     result1 = Line1.Intersect(Line3, out iresArray1);
            IntersectionResult      ires1   = iresArray1.get_Item(0);

            Point1 = ires1.XYZPoint;

            IntersectionResultArray iresArray2;
            SetComparisonResult     result2 = Line1.Intersect(Line4, out iresArray2);
            IntersectionResult      ires2   = iresArray2.get_Item(0);

            Point2 = ires2.XYZPoint;

            IntersectionResultArray iresArray3;
            SetComparisonResult     result3 = Line2.Intersect(Line3, out iresArray3);
            IntersectionResult      ires3   = iresArray3.get_Item(0);

            Point3 = ires3.XYZPoint;

            IntersectionResultArray iresArray4;
            SetComparisonResult     result4 = Line2.Intersect(Line4, out iresArray4);
            IntersectionResult      ires4   = iresArray4.get_Item(0);

            Point4 = ires4.XYZPoint;
        }
Beispiel #9
0
        /***************************************************/
        /****              Public methods               ****/
        /***************************************************/

        public static bool IsInside(this XYZ point, Solid solid, double tolerance)
        {
            if (solid == null || solid.Volume < tolerance)
            {
                return(false);
            }

            SolidCurveIntersectionOptions sco = new SolidCurveIntersectionOptions();

            sco.ResultType = SolidCurveIntersectionMode.CurveSegmentsInside;

            XYZ[] vectors = { XYZ.BasisX, XYZ.BasisY, XYZ.BasisZ };
            foreach (XYZ vector in vectors)
            {
                Line l = Line.CreateBound(point - vector, point + vector);
                SolidCurveIntersection sci = solid.IntersectWithCurve(l, sco);
                if (sci == null)
                {
                    continue;
                }

                for (int i = 0; i < sci.SegmentCount; i++)
                {
                    Curve c = sci.GetCurveSegment(i);
                    IntersectionResult ir = c.Project(point);
                    if (ir != null && ir.Distance <= tolerance)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        private XYZ GetPointIntersecWithWall(Wall wall, Line cuttingLine, out bool isOvelapWithAnotherWindown)
        {
            isOvelapWithAnotherWindown = false;
            List <Solid> solids = GetSolidFromWall(wall);

            foreach (Solid solid in solids)
            {
                if (solid.Faces != null && solid.Faces.Size > 0)
                {
                    foreach (Face face in solid.Faces)
                    {
                        SetComparisonResult result = face.Intersect(cuttingLine, out IntersectionResultArray intersectionResultArray);
                        if (result == SetComparisonResult.Overlap || result == SetComparisonResult.Subset)
                        {
                            if (intersectionResultArray != null)
                            {
                                for (int i = 0; i < intersectionResultArray.Size; i++)
                                {
                                    IntersectionResult intersectionResult = intersectionResultArray.get_Item(i);
                                    if (intersectionResult.XYZPoint != null)
                                    {
                                        return(intersectionResult.XYZPoint);
                                    }
                                }
                            }
                            else
                            {
                                isOvelapWithAnotherWindown = true;
                            }
                        }
                    }
                }
            }
            return(null);
        }
Beispiel #11
0
        public override IIntersectionResult Intersection(Vector3d direction, Vector3d position)
        {
            Vector3d spherePositionProjected = ProjectSpherePosition(direction, position);

            if (spherePositionProjected == null)
            {
                return(null);
            }

            Vector3d distance = (_position - position) - spherePositionProjected;

            if (distance.Length() > _radius)
            {
                return(null);
            }

            double c = System.Math.Sqrt(_radius * _radius - distance.Length() * distance.Length());

            double i1 = ((_position - position).Dot(direction) - c);
            double i2 = ((_position - position).Dot(direction) + c);

            IntersectionResult intersectionResult = new IntersectionResult();

            intersectionResult.Intersection         = position + direction * i1;
            intersectionResult.IntersectionDistance = (intersectionResult.Intersection - position).Length();
            intersectionResult.Object = this;

            return(intersectionResult);
        }
Beispiel #12
0
        private static PointData ConvertToPointData(Face revitFace, FMEPoint fmePoint)
        {
            PointData pointData = null;

            try
            {
                string[] coordinates = fmePoint.Coordinate.Split(',');
                XYZ      xyz         = null;
                if (coordinates.Length == 3)
                {
                    xyz = new XYZ(double.Parse(coordinates[0]), double.Parse(coordinates[1]), double.Parse(coordinates[2]));
                }

                UV uv = null;
                if (null != revitFace && null != xyz)
                {
                    IntersectionResult intersectionResult = revitFace.Project(xyz);
                    if (null != intersectionResult)
                    {
                        uv = intersectionResult.UVPoint;
                    }
                }

                pointData = new PointData(uv, xyz, fmePoint.PointValue);
            }
            catch (Exception ex)
            {
                string message = ex.Message;
            }
            return(pointData);
        }
        // Find-intersection query.  The point of intersection is
        // P = origin + t*direction.
        public bool Find()
        {
            var DdN = line.Direction.Dot(plane.Normal);
            var signedDistance = plane.DistanceTo(line.Origin);
            if (Math.Abs(DdN) > MathUtil.ZeroTolerance)
            {
                // The line is not parallel to the plane, so they must intersect.
                lineParameter = -signedDistance / DdN;
                Type = IntersectionType.Point;
                Result = IntersectionResult.Intersects;
                return true;
            }

            // The Line and plane are parallel.  Determine if they are numerically
            // close enough to be coincident.
            if (Math.Abs(signedDistance) <= MathUtil.ZeroTolerance)
            {
                // The line is coincident with the plane, so choose t = 0 for the
                // parameter.
                lineParameter = 0;
                Type = IntersectionType.Line;
                Result = IntersectionResult.Intersects;
                return true;
            }

            Type = IntersectionType.Empty;
            Result = IntersectionResult.NoIntersection;
            return false;
        }
Beispiel #14
0
        private static IList <double> CreateRoughParametricTessellation(Curve curve)
        {
            IList <XYZ> originalTessellation = curve.Tessellate();

            int numPoints         = originalTessellation.Count;
            int numTargetPoints   = Math.Min(numPoints, 12);
            int numInteriorPoints = numTargetPoints - 2;

            IList <double> roughTessellation = new List <double>(numTargetPoints);

            // Skip the first point as redundant.
            IntersectionResult result = null;

            for (int ii = 0; ii < numInteriorPoints; ii++)
            {
                XYZ initialPoint = originalTessellation[(int)(numPoints - 2) * (ii + 1) / numInteriorPoints];
                result = curve.Project(initialPoint);
                roughTessellation.Add(result.Parameter);
            }

            XYZ finalPoint = originalTessellation[numPoints - 1];

            result = curve.Project(finalPoint);
            roughTessellation.Add(result.Parameter);

            return(roughTessellation);
        }
Beispiel #15
0
        // Bullet pattern generation "borrowed" from user Felsir on gamedev.stackexchange
        // from the following post https://gamedev.stackexchange.com/questions/124688/how-to-create-shockwave-of-objects-in-other-shapes-than-circle
        private Vector2[] CreateBulletPattern(int segments, double offset, int numberofbullets)
        {
            List <Linesegment> polygon          = CreateRadialPolygon(segments, offset);
            List <Vector2>     bulletdirections = new List <Vector2>();

            double bulletangle = (2 * Math.PI) / numberofbullets;

            for (int i = 0; i < numberofbullets; i++)
            {
                foreach (Linesegment l in polygon)
                {
                    //do an intersection; if the line intersects add a bullet to the pattern.
                    IntersectionResult r = ProcessIntersection(l, Vector2.Zero, i * bulletangle);
                    if (r.intersection)
                    {
                        //check if the intersectionpoint already is in the result-
                        //this may be if the intersectionpoint is one of the endpoints of the line segment.
                        if (!bulletdirections.Contains(r.intersectionPoint))
                        {
                            bulletdirections.Add(r.intersectionPoint);
                        }
                    }
                }
            }
            return(bulletdirections.ToArray());
        }
        public bool Test()
        {
            double DdN = line.Direction.Dot(plane.Normal);

            if (Math.Abs(DdN) > MathUtil.ZeroTolerance)
            {
                // The line is not parallel to the plane, so they must intersect.
                // The line parameter is *not* set, since this is a test-intersection
                // query.
                Quantity = 1;
                Type     = IntersectionType.Point;
                return(true);
            }

            // The line and plane are parallel. Determine if they are numerically
            // close enough to be coincident.
            double signedDistance = plane.DistanceTo(line.Origin);

            if (Math.Abs(signedDistance) <= MathUtil.ZeroTolerance)
            {
                Quantity = 1;
                Type     = IntersectionType.Line;
                return(true);
            }

            Result = IntersectionResult.NoIntersection;
            Type   = IntersectionType.Empty;
            return(false);
        }
        public bool Find()
        {
            if (Result != IntersectionResult.NotComputed)
            {
                return(Result == IntersectionResult.Intersects);
            }

            // [RMS] if either line direction is not a normalized vector,
            //   results are garbage, so fail query
            if (ray.Direction.IsNormalized == false)
            {
                Type   = IntersectionType.Empty;
                Result = IntersectionResult.InvalidQuery;
                return(false);
            }

            RayParam0 = 0.0;
            RayParam1 = double.MaxValue;
            IntrLine3AxisAlignedBox3.DoClipping(ref RayParam0, ref RayParam1, ref ray.Origin, ref ray.Direction, ref box,
                                                true, ref Quantity, ref Point0, ref Point1, ref Type);

            Result = (Type != IntersectionType.Empty) ?
                     IntersectionResult.Intersects : IntersectionResult.NoIntersection;
            return(Result == IntersectionResult.Intersects);
        }
Beispiel #18
0
        private List <Line> GetSquare(Line infLine0, Line infLine1, Line infLine2, Line infLine3)
        {
            IntersectionResultArray iresArray1;
            SetComparisonResult     result1 = infLine0.Intersect(infLine2, out iresArray1);
            IntersectionResult      ires1   = iresArray1.get_Item(0);
            XYZ point1 = ires1.XYZPoint;

            IntersectionResultArray iresArray2;
            SetComparisonResult     result2 = infLine0.Intersect(infLine3, out iresArray2);
            IntersectionResult      ires2   = iresArray2.get_Item(0);
            XYZ point2 = ires2.XYZPoint;

            IntersectionResultArray iresArray3;
            SetComparisonResult     result3 = infLine1.Intersect(infLine2, out iresArray3);
            IntersectionResult      ires3   = iresArray3.get_Item(0);
            XYZ point3 = ires3.XYZPoint;

            IntersectionResultArray iresArray4;
            SetComparisonResult     result4 = infLine1.Intersect(infLine3, out iresArray4);
            IntersectionResult      ires4   = iresArray4.get_Item(0);
            XYZ point4 = ires4.XYZPoint;

            List <Line> retLines = new List <Line>();

            retLines.Add(Line.CreateBound(point1, point2));
            retLines.Add(Line.CreateBound(point2, point4));
            retLines.Add(Line.CreateBound(point4, point3));
            retLines.Add(Line.CreateBound(point3, point1));

            return(retLines);
        }
    /// <summary>
    ///  射线与线段的交点
    /// </summary>
    /// <param name="rayOrigin"></param>
    /// <param name="rayDirection"></param>
    /// <param name="lineStart"></param>
    /// <param name="lineEnd"></param>
    /// <returns></returns>
    public static IntersectionResult RayToLineSegmentIntersection(Vector2 rayOrigin, Vector2 rayDirection, Vector2 lineStart, Vector2 lineEnd)
    {
        IntersectionResult result = new IntersectionResult();
        Vector2            v1     = rayOrigin - lineStart;
        Vector2            v2     = lineEnd - lineStart;
        Vector2            v3     = new Vector2(-rayDirection.y, rayDirection.x);


        var dot = Vector2.Dot(v2, v3);

        if (Math.Abs(dot) < float.Epsilon)
        {
            return(result);
        }

        var t1 = Cross(v2, v1) / dot;
        var t2 = Vector2.Dot(v1, v3) / dot;

        if (t1 >= 0.0 && (t2 >= 0.0 && t2 <= 1.0))
        {
            result.AddIntersectionPoint(rayOrigin + t1 * rayDirection);
        }

        return(result);
    }
Beispiel #20
0
        /// <summary>
        /// Add a new vertice in order in the list of vertices of the polygon given the IntersectionResultArray.
        /// </summary>
        /// <param name="points"></param>
        /// <param name="resultArray"></param>
        /// <param name="curve"></param>
        private static CircularLinkedListNode <UV> AddPointsInList(CircularLinkedList <UV> points, IntersectionResultArray resultArray, Curve curve)
        {
            UV p0 = VectorManipulator.ProjectInPlaneXY(curve.GetEndPoint(0));
            CircularLinkedListNode <UV> newNode = null;
            CircularLinkedListNode <UV> node    = FindPoint(points, p0);

            IntersectionResultArrayIterator iterator = resultArray.ForwardIterator();

            iterator.Reset();
            while (iterator.MoveNext())
            {
                IntersectionResult result = iterator.Current as IntersectionResult;
                UV intersectionPoint      = VectorManipulator.ProjectInPlaneXY(result.XYZPoint);
                newNode = points.AddAfter(node, intersectionPoint);
            }
            if (newNode.Next.Value.IsAlmostEqualTo(newNode.Value))
            {
                points.Remove(newNode.Next.Value);
            }
            else if (newNode.Previous.Value.IsAlmostEqualTo(newNode.Value))
            {
                points.Remove(newNode.Previous.Value);
            }

            return(newNode);
        }
    private static void IncrementalRaycast(
        Vector3 start,
        Vector3 end,
        ProcessIntersection onIntersect,
        ShouldContinueRayCast shouldContinue
        )
    {
        RaycastHit hitInfo;
        Vector3    ray       = end - start;
        Vector3    dx        = ray.normalized;
        Vector3    remaining = end - start;

        dx.Scale(new Vector3(.01f, .01f, .01f));
        while (Physics.Raycast(start, dx, out hitInfo, remaining.magnitude, instance.collisionMask))
        {
            remaining -= (hitInfo.point - start);
            start      = (hitInfo.point + dx);

            //hit object must have an obstacle script
            if (hitInfo.collider.transform.GetComponent <Obstacle>() != null)
            {
                IntersectionResult result = new IntersectionResult(hitInfo);
                onIntersect(result);
                if (!shouldContinue(result))
                {
                    break;
                }
            }
        }
    }
    /// <summary>
    /// 射线与圆相交交点
    /// </summary>
    /// <param name="rayOrigin"></param>
    /// <param name="rayDirection"></param>
    /// <param name="circleCenter"></param>
    /// <param name="radius"></param>
    /// <returns></returns>
    public static IntersectionResult RayToCircleIntersection(Vector2 rayOrigin, Vector2 rayDirection, Vector2 circleCenter, float radius)
    {
        IntersectionResult result = new IntersectionResult();

        rayDirection = rayDirection.normalized;

        Vector2 rayOriginToCircleCenter       = circleCenter - rayOrigin;
        float   rayOriginToCircleCenterLength = rayOriginToCircleCenter.sqrMagnitude;

        float dot = Vector2.Dot(rayDirection, rayOriginToCircleCenter.normalized);

        Vector2 pointOnRayVerticalWithCircleCenter = rayOrigin + rayDirection * (dot * Mathf.Sqrt(rayOriginToCircleCenterLength));

        float squareDistanceToCenter = Vector2.Dot(pointOnRayVerticalWithCircleCenter - circleCenter, pointOnRayVerticalWithCircleCenter - circleCenter);

        if (squareDistanceToCenter > radius * radius)
        {
            return(result);
        }

        if (squareDistanceToCenter == radius * radius)
        {
            result.AddIntersectionPoint(pointOnRayVerticalWithCircleCenter);
            return(result);
        }

        float distanceToIntersection = 0f;
        float distanceToCenter       = 0f;

        if (squareDistanceToCenter == 0)
        {
            distanceToIntersection = radius;
        }
        else
        {
            distanceToCenter       = (float)Math.Sqrt(squareDistanceToCenter);
            distanceToIntersection = (float)Math.Sqrt(radius * radius - squareDistanceToCenter);
        }

        float lineSegmentLength = 1 / Mathf.Sqrt(rayOriginToCircleCenterLength);

        rayOriginToCircleCenter *= lineSegmentLength;
        rayOriginToCircleCenter *= distanceToIntersection;

        Vector2 solution1 = pointOnRayVerticalWithCircleCenter + rayOriginToCircleCenter;

        if (Vector2.Distance(solution1, rayOrigin) > 0)
        {
            result.AddIntersectionPoint(solution1);
        }
        Vector2 solution2 = pointOnRayVerticalWithCircleCenter - rayOriginToCircleCenter;

        if (Vector2.Distance(solution2, rayOrigin) > 0)
        {
            result.AddIntersectionPoint(solution2);
        }
        return(result);
    }
Beispiel #23
0
        public override void Evaluate(FSharpList <Value> args, Dictionary <PortData, Value> outPuts)
        {
            var xyz      = (XYZ)((Value.Container)args[0]).Item;
            var inputArg = ((Value.Container)args[1]).Item;

            XYZ    pt;
            UV     uv;
            double d;
            Edge   e;
            double et;

            var face = inputArg is Face ? (Face)inputArg : null;

            if (face == null && !(inputArg is Plane))
            {
                throw new Exception(" Project Point On Face needs Face or Plane as argument no. 1");
            }
            if (face == null)
            {
                var pln = (Plane)inputArg;
                uv = new UV(
                    pln.XVec.DotProduct(xyz - pln.Origin), pln.YVec.DotProduct(xyz - pln.Origin));
                pt = pln.Origin + uv[0] * pln.XVec + uv[1] * pln.YVec;
                d  = xyz.DistanceTo(pt);
                e  = null;
                et = 0.0;
            }
            else
            {
                IntersectionResult ir = face.Project(xyz);

                pt = ir.XYZPoint;
                uv = ir.UVPoint;
                d  = ir.Distance;
                e  = null;
                et = 0;

                try
                {
                    e = ir.EdgeObject;
                }
                catch { }

                try
                {
                    et = ir.EdgeParameter;
                }
                catch { }
            }

            pts.Add(pt);

            outPuts[_xyzPort]   = Value.NewContainer(xyz);
            outPuts[_uvPort]    = Value.NewContainer(uv);
            outPuts[_dPort]     = Value.NewNumber(d);
            outPuts[_edgePort]  = Value.NewContainer(e);
            outPuts[_edgeTPort] = Value.NewNumber(et);
        }
Beispiel #24
0
        private double?GetTrimParameter(IFCData trim, IFCCurve basisCurve, IFCTrimmingPreference trimPreference, bool secondAttempt)
        {
            bool preferParam = !(trimPreference == IFCTrimmingPreference.Cartesian);

            if (secondAttempt)
            {
                preferParam = !preferParam;
            }
            double vertexEps = MathUtil.VertexEps;

            IFCAggregate trimAggregate = trim.AsAggregate();

            foreach (IFCData trimParam in trimAggregate)
            {
                if (!preferParam && (trimParam.PrimitiveType == IFCDataPrimitiveType.Instance))
                {
                    IFCAnyHandle trimParamInstance = trimParam.AsInstance();
                    XYZ          trimParamPt       = IFCPoint.ProcessScaledLengthIFCCartesianPoint(trimParamInstance);
                    if (trimParamPt == null)
                    {
                        IFCImportFile.TheLog.LogWarning(basisCurve.Id, "Invalid trim point for basis curve.", false);
                        continue;
                    }

                    try
                    {
                        IntersectionResult result = basisCurve.Curve.Project(trimParamPt);
                        if (result.Distance < vertexEps)
                        {
                            return(result.Parameter);
                        }

                        IFCImportFile.TheLog.LogWarning(basisCurve.Id, "Cartesian value for trim point not on the basis curve.", false);
                    }
                    catch
                    {
                        IFCImportFile.TheLog.LogWarning(basisCurve.Id, "Cartesian value for trim point not on the basis curve.", false);
                    }
                }
                else if (preferParam && (trimParam.PrimitiveType == IFCDataPrimitiveType.Double))
                {
                    double trimParamDouble = trimParam.AsDouble();
                    if (basisCurve.Curve.IsCyclic)
                    {
                        trimParamDouble = IFCUnitUtil.ScaleAngle(trimParamDouble);
                    }
                    return(trimParamDouble);
                }
            }

            // Try again with opposite preference.
            if (!secondAttempt)
            {
                return(GetTrimParameter(trim, basisCurve, trimPreference, true));
            }

            return(null);
        }
Beispiel #25
0
        private Segment closeIfCollinear(Segment s1, int end1, Segment s2, int end2)
        {
            Line ln1 = s1.Curve as Line;
            Line ln2 = s2.Curve as Line;

            if (ln1 == null)
            {
                return(null);
            }
            if (ln2 == null)
            {
                return(null);
            }

            double ang = ln1.Direction.AngleTo(ln2.Direction);

            if ((ang < 0.01) || (ang > Math.PI * 0.9))
            {
                // it is collinear or close
            }
            else
            {
                return(null);
            }

            // midpoint has changed, so we need to refigure:
            XYZ p1a = ln1.GetEndPoint(0);
            XYZ p1b = ln1.GetEndPoint(1);
            XYZ p2a = ln2.GetEndPoint(0);
            XYZ p2b = ln2.GetEndPoint(1);

            // need to make the lines unbound
            ln1 = Line.CreateUnbound(ln1.Origin, ln1.Direction);
            ln2 = Line.CreateUnbound(ln2.Origin, ln2.Direction);



            XYZ s1MidPoint             = new XYZ((p1a.X + p1b.X) / 2.0, (p1a.Y + p1b.Y) / 2.0, (p1a.Z + p1b.Z) / 2.0);
            XYZ s2MidPoint             = new XYZ((p2a.X + p2b.X) / 2.0, (p2a.Y + p2b.Y) / 2.0, (p2a.Z + p2b.Z) / 2.0);
            IntersectionResult result1 = ln1.Project(s2MidPoint);
            IntersectionResult result2 = ln2.Project(s1MidPoint);

            if ((result1.Distance < 0.02) && (result2.Distance < 0.02))
            {
                // collinear or close:

                Line stitch = Line.CreateBound(s1.Curve.GetEndPoint(end1), s2.Curve.GetEndPoint(end2));

                Segment fix = new Segment()
                {
                    Curve = stitch, Draw = true, Length = stitch.Length
                };

                return(fix);
            }

            return(null);
        }
    /*
     * Might cause memory leaks if interrupted before NativeArrays are disposed
     */
    private static void ParallelIncrementalRaycast(
        List <ParallelIncrementalRaycastData> paths
        )
    {
        List <ParallelIncrementalRaycastData> remainingPaths =
            new List <ParallelIncrementalRaycastData>(paths);

        NativeArray <RaycastHit>     results  = default(NativeArray <RaycastHit>);
        NativeArray <RaycastCommand> commands = default(NativeArray <RaycastCommand>);

        do
        {
            results  = new NativeArray <RaycastHit>(remainingPaths.Count, Allocator.TempJob);
            commands = new NativeArray <RaycastCommand>(remainingPaths.Count, Allocator.TempJob);

            for (int i = 0; i < remainingPaths.Count; i++)
            {
                commands[i] = new RaycastCommand(
                    remainingPaths[i].start,
                    remainingPaths[i].dx,
                    remainingPaths[i].remaining.magnitude,
                    instance.collisionMask
                    );
            }

            JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
            handle.Complete();

            for (int i = 0; i < remainingPaths.Count; i++)
            {
                ParallelIncrementalRaycastData data = remainingPaths[i];
                RaycastHit batchedHit = results[i];
                data.hit = batchedHit;
                if (batchedHit.collider == null)
                {
                    continue;
                }


                data.remaining -= (batchedHit.point - data.start);
                data.start      = (batchedHit.point + data.dx);


                if (batchedHit.collider.transform.GetComponent <Obstacle>() != null)
                {
                    IntersectionResult result = new IntersectionResult(batchedHit);
                    data.onIntersect(result);
                }
            }

            remainingPaths.RemoveAll(
                path => !path.continueCondition(path.result) || path.hit.collider == null
                );
            results.Dispose();
            commands.Dispose();
        } while (remainingPaths.Count > 0);
    }
Beispiel #27
0
        /// <summary>
        /// Compute the distance between two planar faces.
        /// </summary>
        /// <param name="face1">Face 1</param>
        /// <param name="face2">Face 2</param>
        /// <returns>Distance of the two planar faces</returns>
        private static double GetDistance(PlanarFace face1, PlanarFace face2)
        {
            BoundingBoxUV      boxUV    = face2.GetBoundingBox();
            UV                 center   = (boxUV.Max + boxUV.Min) * 0.5;
            XYZ                centerPt = face2.Evaluate(center);
            IntersectionResult result   = face1.Project(centerPt);

            return(face1.Project(centerPt).Distance);
        }
Beispiel #28
0
        public void Update()
        {
            IntersectionResults.Clear();

            IntersectionResult previousResult = new IntersectionResult()
            {
                OutgoingRay = new Ray(IncidentRay)
            };

            double lastRefractiveIndex       = RefractiveIndices.AIR;
            Vector translationFromLensCenter = new Vector(0.0, 0.0);

            int maxIntersections = Elements.Count;

            for (int i = 0; i < maxIntersections; i++)
            {
                IntersectionResult result  = new IntersectionResult();
                OpticalElement     element = Elements[i];

                result.IncidentRay = new Ray(previousResult.OutgoingRay);

                Vector toLocal = element.TranslationToLocal();

                // compute intersection

                Point intersection         = null;
                Ray   rayIncidentToElement = result.IncidentRay.Translate(translationFromLensCenter + toLocal);
                result.Intersected = element.IntersectRay(rayIncidentToElement, out intersection);
                result.Normal      = Vector.FromPoint(intersection);
                intersection       = intersection - (translationFromLensCenter + toLocal);
                if (!result.Intersected)
                {
                    break;
                }
                result.Intersection = intersection;

                // compute refracted ray

                Vector outgoingDirection;
                if (Math.Abs(lastRefractiveIndex - element.NextRefractiveIndex) > double.Epsilon)
                {
                    outgoingDirection = result.IncidentRay.Direction.Length * Vector.refract(result.IncidentRay.Direction, result.Normal, lastRefractiveIndex, element.NextRefractiveIndex);
                }
                else
                {
                    // there's no border between different media and thus no refraction
                    outgoingDirection = result.IncidentRay.Direction;
                }
                result.OutgoingRay = new Ray(result.Intersection, outgoingDirection);
                result.Refracted   = true; // TODO: differ refraction and TIR
                IntersectionResults.Add(result);
                previousResult               = result;
                lastRefractiveIndex          = element.NextRefractiveIndex;
                translationFromLensCenter.X += element.DistanceToNext;
            }
        }
Beispiel #29
0
        public void Update()
        {
            IntersectionResults.Clear();

            IntersectionResult previousResult = new IntersectionResult()
            {
                OutgoingRay = new Ray(IncidentRay)
            };

            double lastRefractiveIndex = RefractiveIndices.AIR;
            Vector translationFromLensCenter = new Vector(0.0, 0.0);

            int maxIntersections = Elements.Count;
            for (int i = 0; i < maxIntersections; i++)
            {
                IntersectionResult result = new IntersectionResult();
                OpticalElement element = Elements[i];

                result.IncidentRay = new Ray(previousResult.OutgoingRay);

                Vector toLocal = element.TranslationToLocal();

                // compute intersection

                Point intersection = null;
                Ray rayIncidentToElement = result.IncidentRay.Translate(translationFromLensCenter + toLocal);
                result.Intersected = element.IntersectRay(rayIncidentToElement, out intersection);
                result.Normal = Vector.FromPoint(intersection);
                intersection = intersection - (translationFromLensCenter + toLocal);
                if (!result.Intersected)
                {
                    break;
                }
                result.Intersection = intersection;

                // compute refracted ray

                Vector outgoingDirection;
                if (Math.Abs(lastRefractiveIndex - element.NextRefractiveIndex) > double.Epsilon)
                {
                    outgoingDirection = result.IncidentRay.Direction.Length * Vector.refract(result.IncidentRay.Direction, result.Normal, lastRefractiveIndex, element.NextRefractiveIndex);
                }
                else
                {
                    // there's no border between different media and thus no refraction
                    outgoingDirection = result.IncidentRay.Direction;
                }
                result.OutgoingRay = new Ray(result.Intersection, outgoingDirection);
                result.Refracted = true; // TODO: differ refraction and TIR
                IntersectionResults.Add(result);
                previousResult = result;
                lastRefractiveIndex = element.NextRefractiveIndex;
                translationFromLensCenter.X += element.DistanceToNext;
            }
        }
        /// <summary>
        /// Place an instance of the given family symbol
        /// on a selected face of an existing 3D element.
        /// </summary>
        FamilyInstance PlaceFamilyInstanceOnFace(
            UIDocument uidoc,
            FamilySymbol symbol)
        {
            Document doc = uidoc.Document;

            Reference r = uidoc.Selection.PickObject(
                ObjectType.Face, "Please pick a point on "
                + " a face for family instance insertion");

            Element e = doc.GetElement(r.ElementId);

            GeometryObject obj
                = e.GetGeometryObjectFromReference(r);

            if (obj is PlanarFace)
            {
                PlanarFace planarFace = obj as PlanarFace;

                // Handle planar face case ...
            }
            else if (obj is CylindricalFace)
            {
                CylindricalFace cylindricalFace = obj
                                                  as CylindricalFace;

                // Handle cylindrical face case ...
            }

            // Better than specialised individual handlers
            // for each specific case, handle the general
            // case in a generic fashion.

            Debug.Assert(
                ElementReferenceType.REFERENCE_TYPE_SURFACE
                == r.ElementReferenceType,
                "expected PickObject with ObjectType.Face to "
                + "return a surface reference");

            Face face = obj as Face;
            UV   q    = r.UVPoint;

#if DEBUG
            XYZ p = r.GlobalPoint;
            IntersectionResult ir = face.Project(p);
            UV q2 = ir.UVPoint;
            Debug.Assert(q.IsAlmostEqualTo(q2),
                         "expected same UV point");
#endif // DEBUG

            Transform t = face.ComputeDerivatives(q);
            XYZ       v = t.BasisX; // or BasisY, or whatever...

            return(doc.Create.NewFamilyInstance(r, p, v, symbol));
        }
Beispiel #31
0
        private bool isAlreadyCreated(Segment seg, IList <Tuple <XYZ, ModelCurve> > already)
        {
            //double midTolerance = 0.5 / 12.0;
            double endTolerance       = 1.0 / 12.0;
            double endOffsetTolerance = 2.0 / 12.0;

            XYZ  mid     = seg.Curve.Evaluate(0.5, true);
            Line segLine = seg.Curve as Line;

            if (segLine == null)
            {
                return(false);
            }

            foreach (var item in already)
            {
                Curve crv = (item.Item2.GeometryCurve);
                if ((crv is Line) == false)
                {
                    continue;
                }

                Line ln = crv as Line;
                IntersectionResult res = ln.Project(mid);

                if (res.Distance <= endTolerance)
                {
                    // it is a close projection.

                    // check angle
                    double angle = ln.Direction.AngleTo(segLine.Direction);
                    if ((angle < 0.01) || (angle > Math.PI * 0.95))
                    {
                        // collinear
                    }
                    else
                    {
                        continue;
                    }
                    // now we need to look at how close the endpoints are
                    XYZ end1 = segLine.GetEndPoint(0);
                    XYZ end2 = segLine.GetEndPoint(1);

                    IntersectionResult res1 = ln.Project(end1);
                    IntersectionResult res2 = ln.Project(end2);

                    if ((res1.Distance <= endOffsetTolerance) && (res2.Distance < endOffsetTolerance))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Beispiel #32
0
    // intersction entre deux droite du plan
    public static IntersectionResult FindIntersection(StraightLine l0, StraightLine l1)
    {
        Vector2 delta = l1.point - l0.point;
        Vector3 crossVector = Vector3.Cross (l0.tangent, l1.tangent);

        IntersectionResult ir = new IntersectionResult ();

        if (!Utils.Approximately (crossVector.z, 0))
        {
            // unique intersection point
            ir.intersectionType = IntersectionType.UniqueIntersection;
            ir.intersectionCount = 1;

            Vector3 delta1CrossVector = Vector3.Cross (delta, l1.tangent);
            float l0Factor = delta1CrossVector.z / crossVector.z;

            Vector2 intersectedPoint = l0.point + l0Factor * l0.tangent;
            ir.intersectedPoints = new Vector2 [1];
            ir.intersectedPoints[0] = intersectedPoint;
        }
        else
        {
            Vector3 delta0CrossVector = Vector3.Cross (l0.tangent, delta);

            if (Utils.Approximately (delta0CrossVector.z, 0))
            {
            // infinitely many points
            ir.intersectionType = IntersectionType.InfinityIntersections;
            ir.intersectionCount = -1;
            }
            else
            {
                // lines are parallel, no intersection
                ir.intersectionType = IntersectionType.NoIntersection;
                ir.intersectionCount = 0;
            }
        }

        return ir;
    }
        /// <summary>
        /// Returns the intersection of the parallel with a line.
        /// </summary>
        /// <param name="refline">The reference line.</param>
        /// <param name="parpos">Search position that coincides with the parallel.</param>
        /// <param name="line">The line to intersect with.</param>
        /// <returns>The intersection (if any). In cases where the line intersects the
        /// parallel more than once, you get the intersection that is closest to the
        /// search position.</returns>
        internal static IPosition GetIntersect(LineFeature refline, IPosition parpos, LineFeature line)
        {
            // Make sure the intersection is undefined.
            IPosition result = null;

            // Return if the parallel point is undefined.
            if (parpos==null)
                return null;

            // If the reference line is a circular arc (or a section based on an arc), get the curve info.
            ArcFeature arc = refline.GetArcBase();
            if (arc != null)
            {
                Circle circle = arc.Circle;
                double radius = circle.Radius;
                IPointGeometry centre = circle.Center;
                bool iscw = arc.IsClockwise;

                // Construct a circle that passes through the search position
                double parrad = Geom.Distance(centre, parpos);

                // Intersect the circle with the line to intersect with.
                IntersectionResult xres = new IntersectionResult(line);
                uint nx = xres.Intersect(centre, parrad);
                if (nx==0)
                    return null;

                // If there is only one intersection, that's what we want.
                if (nx==1)
                    return xres.Intersections[0].P1;

                // Get the intersection that is closest to the search position.
                xres.GetClosest(parpos, out result, 0.0);
            }
            else
            {
                // Get the bearing from the start to the end of the reference line.
                IPosition spos = refline.StartPoint;
                IPosition epos = refline.EndPoint;
                double bearing = Geom.BearingInRadians(spos, epos);

                // Project the parallel line to positions that are a long way away (but make sure we
                // don't end up with negative numbers).
                Window searchWindow = new Window(line.Extent);
                searchWindow.Union(refline.Extent);
                searchWindow.Union(parpos);
                double dist = Geom.Distance(searchWindow.Min, searchWindow.Max);

                IPosition start = Geom.Polar(parpos, bearing+Constants.PI, dist);
                IPosition end = Geom.Polar(parpos, bearing, dist);

                // Intersect the line segment with the line to intersect with.
                IntersectionResult xres = new IntersectionResult(line);
                IPointGeometry sg = new PointGeometry(start);
                IPointGeometry eg = new PointGeometry(end);
                uint nx = xres.Intersect(sg, eg);
                if (nx==0)
                    return null;

                // If there is only one intersection, that's what we want.
                if (nx==1)
                    return xres.Intersections[0].P1;

                // Get the intersection that is closest to the search position
                xres.GetClosest(parpos, out result, 0.0);
            }

            return result;
        }
Beispiel #34
0
        /// <summary>
        /// Intersects this direction with a line.
        /// </summary>
        /// <param name="line">The line to intersect with.</param>
        /// <param name="closeTo">The point that the intersection should be closest to.
        /// Specify null if you don't care. In that case, if there are multiple intersections,
        /// you get the intersection that is closest to one of 3 points: the start of the
        /// direction line, the start of the line, or the end of the line.</param>
        /// <param name="xsect">The position of the intersection (if any). Null if not found.</param>
        /// <param name="closest">The default point that is closest to the intersection. Null if
        /// intersection wasn't found.</param>
        /// <returns>True if intersection was found.</returns>
        internal bool Intersect( LineFeature line
            , PointFeature closeTo
            , out IPosition xsect
            , out PointFeature closest)
        {
            // Initialize results
            xsect = null;
            closest = null;

            // Define the length of the direction line as the length
            // of a diagonal that crosses the map's extent.
            IWindow mapWin = SpatialController.Current.MapModel.Extent;
            Debug.Assert(mapWin!=null);

            // If the window is currently undefined (e.g. during deserialization),
            // just use a really big distance.
            // TODO: This is a hack, but hopefully it may be shortlived, because
            // new logic is in the works for handling updates.
            double dist = (mapWin.IsEmpty ? 100000.0 : Geom.Distance(mapWin.Min, mapWin.Max));

            // Define the position of the direction line. DON'T use the from-
            // point, because there may be an offset to the direction.
            IPosition fromPos = this.StartPosition;
            IPosition toPos = Geom.Polar(fromPos, this.Bearing.Radians, dist);

            // Construct a corresponding line segment.
            ITerminal start = new FloatingTerminal(fromPos);
            ITerminal end = new FloatingTerminal(toPos);
            SegmentGeometry seg = new SegmentGeometry(start, end);

            // Intersect the line segment with the other one.
            IntersectionResult xres = new IntersectionResult(line);
            uint nx = seg.Intersect(xres);
            if (nx==0)
                return false;

            // Determine which terminal point is the best. Start with the
            // ends of the intersected line.
            double mindsq = Double.MaxValue;

            if (xres.GetCloserPoint(line.StartPoint, ref mindsq, ref xsect))
                closest = line.StartPoint;

            if (xres.GetCloserPoint(line.EndPoint, ref mindsq, ref xsect))
                closest = line.EndPoint;

            // Check whether the direction from-point is any closer (the position may be
            // different from the start of the direction line, because the direction may
            // have an offset).

            if (xres.GetCloserPoint(this.From, ref mindsq, ref xsect))
                closest = this.From;

            // If a close-to point has been specified, that overrides
            // everything else (however, doing the above has the desired
            // effect of defining the best of the default points). In
            // this case, we allow an intersection that coincides with
            // the line being intersected.
            // -- actually, we don't, since GetClosest uses a > 0 test

            if (closeTo != null)
            {
                xres.GetClosest(closeTo, out xsect, 0.0);
                /*
                IPosition xCloseTo;
                xres.GetClosest(closeTo, out xCloseTo, 0.0);

                if (xCloseTo != null)
                    xsect = xCloseTo;
                 */
            }

            return (xsect!=null);
        }
        private void Stream(ArrayList data, IntersectionResult intrResult)
        {
            data.Add(new Snoop.Data.ClassSeparator(typeof(IntersectionResult)));

            data.Add(new Snoop.Data.Double("Distance", intrResult.Distance));
            data.Add(new Snoop.Data.Object("Edge object", intrResult.EdgeObject));
            data.Add(new Snoop.Data.Double("Edge parameter", intrResult.EdgeParameter));
            data.Add(new Snoop.Data.Double("Parameter", intrResult.Parameter));
            data.Add(new Snoop.Data.Uv("UV Point", intrResult.UVPoint));
            data.Add(new Snoop.Data.Xyz("XYZ Point", intrResult.XYZPoint));
        }
        /// <summary>
        /// Returns the intersection of the parallel with a line. A prior call to Calculate is required.
        /// </summary>
        /// <param name="line">The line to intersect with.</param>
        /// <param name="isEndParallel">Is the intersection biased towards the end of the parallel?</param>
        /// <returns>The intersection (if any). In cases where the line intersects the parallel
        /// more than once, you get an arbitrary intersection.</returns>
        internal IPosition GetIntersect(LineFeature line, bool isEndParallel)
        {
            // Make sure the intersection is undefined.
            IPosition result = null;

            // Return if the parallel points are undefined.
            if (m_Par1==null || m_Par2==null)
                return null;

            // If the reference line is a circular arc, get the curve info.
            ArcFeature arc = m_Line.GetArcBase();
            if (arc != null)
            {
                Circle circle = arc.Circle;
                double radius = circle.Radius;
                IPointGeometry centre = circle.Center;
                bool iscw = arc.IsClockwise;

                // Construct a circle that passes through
                // the parallel points (assumed to have the same distance
                // with respect to the centre of the circle).
                double parrad = Geom.Distance(centre, m_Par1);

                // Intersect the circle with the line to intersect with.
                IntersectionResult xres = new IntersectionResult(line);
                uint nx = xres.Intersect(centre, parrad);
                if (nx==0)
                    return null;

                // If there is only one intersection, that's what we want.
                if (nx==1)
                    return xres.Intersections[0].P1;

                // Get the intersection that is closest to the parallel point
                // that has the bias.
                if (isEndParallel)
                    xres.GetClosest(m_Par2, out result, 0.0);
                else
                    xres.GetClosest(m_Par1, out result, 0.0);
            }
            else
            {
                // Get the bearing from the start to the end of the parallel.
                double bearing = Geom.BearingInRadians(m_Par1, m_Par2);

                // Get the ground dimension of a line that crosses the
                // extent of the draw window.
                double dist = MaxDiagonal;

                // Project the parallel line to positions that are well
                // beyond the draw extent.
                IPosition start = Geom.Polar(m_Par1, bearing+Constants.PI, dist);
                IPosition end = Geom.Polar(m_Par2, bearing, dist);

                // Intersect the line segment with the line to intersect with.
                IntersectionResult xres = new IntersectionResult(line);
                IPointGeometry sg = PointGeometry.Create(start);
                IPointGeometry eg = PointGeometry.Create(end);
                uint nx = xres.Intersect(sg, eg);
                if (nx==0)
                    return null;

                // If there is only one intersection, that's what we want.
                if (nx==1)
                    return xres.Intersections[0].P1;

                // Get the intersection that is closest to the parallel point
                // that has the bias.
                if (isEndParallel)
                    xres.GetClosest(m_Par2, out result, 0.0);
                else
                    xres.GetClosest(m_Par1, out result, 0.0);
            }

            return result;
        }