private IntersectionInfo CalcApparentIntersection(CurveVertex source, CurveVertex target, Transaction transaction)
        {
            var sourceEntity = transaction.GetObject(source.Id, OpenMode.ForRead);
            var targetEntity = transaction.GetObject(target.Id, OpenMode.ForRead);

            // Source curve
            var desiredSourceExtend = CurveUtils.GetExtendType((Curve)sourceEntity, source.Point);
            var sourceLine          = sourceEntity as Line;
            var sourceArc           = sourceEntity as Arc;
            var sourcePolyline      = sourceEntity as Autodesk.AutoCAD.DatabaseServices.Polyline;
            var sourcePolyline2d    = sourceEntity as Polyline2d;

            if (sourcePolyline != null)
            {
                sourceLine = CurveUtils.CutOutLineFromPolyLine(sourcePolyline, source.Point);
            }
            else if (sourcePolyline2d != null)
            {
                sourceLine = CurveUtils.CutOutLineFromPolyline2d(sourcePolyline2d, source.Point, transaction);
            }

            // Target curve
            var desiredTargetExtend = CurveUtils.GetExtendType((Curve)targetEntity, target.Point);
            var targetLine          = targetEntity as Line;
            var targetArc           = targetEntity as Arc;
            var targetPolyline      = targetEntity as Autodesk.AutoCAD.DatabaseServices.Polyline;
            var targetPolyline2d    = targetEntity as Polyline2d;

            if (targetPolyline != null)
            {
                targetLine = CurveUtils.CutOutLineFromPolyLine(targetPolyline, target.Point);
            }
            else if (targetPolyline2d != null)
            {
                targetLine = CurveUtils.CutOutLineFromPolyline2d(targetPolyline2d, target.Point, transaction);
            }

            // Calculate intersection.
            var results = new List <IntersectionInfo>();

            if (sourceLine != null && targetLine != null)
            {
                // Line && Line
                var info = CurveIntersectUtils.InsersectLines(sourceLine, targetLine);
                if (info != null)
                {
                    info.SourceId = source.Id;
                    info.TargetId = target.Id;
                    results.Add(info);
                }
            }
            else if (sourceLine != null && targetArc != null)
            {
                // Line && Arc
                var infos = CurveIntersectUtils.IntersectLineArc(sourceLine, targetArc, coerceArcExtendType: desiredTargetExtend);
                foreach (var info in infos)
                {
                    info.SourceId = source.Id;
                    info.TargetId = target.Id;
                }
                results.AddRange(infos);
            }
            else if (sourceArc != null && targetLine != null)
            {
                // Arc && Line
                var infos = CurveIntersectUtils.IntersectLineArc(targetLine, sourceArc, coerceArcExtendType: desiredSourceExtend);
                foreach (var info in infos)
                {
                    // Exchange entend type.
                    var newInfo = new IntersectionInfo(source.Id, info.TargetExtendType, target.Id,
                                                       info.SourceExtendType, info.IntersectPoint);

                    results.Add(newInfo);
                }
            }
            else if (sourceArc != null && targetArc != null)
            {
                // Arc && Arc
                var infos = CurveIntersectUtils.IntersectArcs(sourceArc, desiredSourceExtend, targetArc,
                                                              desiredTargetExtend);
                foreach (var info in infos)
                {
                    info.SourceId = source.Id;
                    info.TargetId = target.Id;
                }

                results.AddRange(infos);
            }

            IntersectionInfo result = null;

            foreach (var info in results)
            {
                var valid = CheckIntersectionInfo(info, desiredSourceExtend, source.Point, desiredTargetExtend, target.Point, _tolerance);
                if (valid)
                {
                    result = info;
                    break;
                }
            }
            return(result);
        }
        private IntersectionInfo GetUnderShootIntersection(CurveVertex vertex, Transaction transaction, double tolerance)
        {
            var curve         = transaction.GetObject(vertex.Id, OpenMode.ForRead);
            var desiredExtend = CurveUtils.GetExtendType((Curve)curve, vertex.Point);

            var line       = curve as Line;
            var arc        = curve as Arc;
            var polyline   = curve as Polyline;
            var polyline2d = curve as Polyline2d;

            if (polyline != null)
            {
                line = CurveUtils.CutOutLineFromPolyLine(polyline, vertex.Point);
            }
            else if (polyline2d != null)
            {
                line = CurveUtils.CutOutLineFromPolyline2d(polyline2d, vertex.Point, transaction);
            }

            // Construct a polygon to get adjacent entities.
            Point3dCollection polygon = null;

            if (line != null)
            {
                var direction = line.EndPoint - line.StartPoint;
                if (desiredExtend == ExtendType.ExtendStart)
                {
                    direction = -1.0 * direction;
                }
                polygon = BuildSelectionPolygonForLine(vertex.Point, direction, tolerance);
            }
            else if (arc != null)
            {
                polygon = BuildSelectionPolygonForArc(vertex.Point, tolerance);
            }

            // Zoom window
            var minPt   = new Point3d(vertex.Point.X - tolerance, vertex.Point.Y - tolerance, 0.0);
            var maxPt   = new Point3d(vertex.Point.X + tolerance, vertex.Point.Y + tolerance, 0.0);
            var extents = new Extents3d(minPt, maxPt);

            Editor.ZoomToWin(extents, factor: 2.0);

            var selectionResult = Editor.SelectCrossingPolygon(polygon, SelectionFilterUtils.OnlySelectCurve());

            if (selectionResult.Status != PromptStatus.OK || selectionResult.Value == null)
            {
                return(null);
            }

            // Check each adjacent entity whether they are intersected.
            var intersectionInfos = new List <IntersectionInfo>();
            var adjacentIds       = selectionResult.Value.GetObjectIds();

            foreach (ObjectId objId in adjacentIds)
            {
                var targetCurve = transaction.GetObject(objId, OpenMode.ForRead) as Curve;
                if (targetCurve == null)
                {
                    continue;
                }

                // Calculate the intersection
                IntersectionInfo info = null;
                if (line != null)
                {
                    info = IntersectLineAndCurve(line, targetCurve, vertex.Point, desiredExtend);
                }
                else if (arc != null)
                {
                    info = IntersectArcAndCurve(arc, targetCurve, vertex.Point, desiredExtend);
                }

                if (info != null && info.SourceExtendType == desiredExtend)
                {
                    info.SourceId = vertex.Id;
                    info.TargetId = objId;

                    intersectionInfos.Add(info);
                }
            }

            // Get nearest point.
            if (intersectionInfos.Count <= 0)
            {
                return(null);
            }

            var nearest     = intersectionInfos[0];
            var nearsetDist = (intersectionInfos[0].IntersectPoint - vertex.Point).Length;

            for (int i = 1; i < intersectionInfos.Count; i++)
            {
                var dist = (intersectionInfos[i].IntersectPoint - vertex.Point).Length;
                if (dist < nearsetDist)
                {
                    nearsetDist = dist;
                    nearest     = intersectionInfos[i];
                }
            }

            if (nearsetDist.Larger(tolerance))
            {
                return(null);
            }

            return(nearest);
        }