コード例 #1
0
 public Side GetSide(UniversalLine otherLine)
 {
     if (VisuallyClosed || otherLine.VisuallyClosed)
     {
         return(GetSideClosedCase(otherLine));
     }
     else
     {
         return(GetSideOpenedCase(otherLine));
     }
 }
コード例 #2
0
        private Side GetSideClosedCase(UniversalLine other)
        {
            Point3d getPointMaxY(UniversalLine line) =>
            line.Segments
            .Select(segment => segment.EndPoint)
            .Aggregate(line.StartPoint, (p1, p2) => p1.Y > p2.Y ? p1 : p2);

            Side GetTurnDirectionAt(UniversalLine line, Point3d point)
            {
                Point3d previous = default(Point3d), next = default(Point3d);
                bool    hasNext = false, hasPrevious = false;

                foreach (var segment in Segments)
                {
                    if (point == segment.StartPoint)
                    {
                        next    = segment.EndPoint;
                        hasNext = true;
                        if (hasPrevious)
                        {
                            break;
                        }
                    }
                    if (point == segment.EndPoint)
                    {
                        previous    = segment.StartPoint;
                        hasPrevious = true;
                        if (hasNext)
                        {
                            break;
                        }
                    }
                }

                if (!hasNext || !hasPrevious)
                {
                    throw new InvalidOperationException("Bottom line is strange");
                }

                return(previous.GetVectorTo(point).GetSide(point.GetVectorTo(next)));
            }

            var pointMaxY     = getPointMaxY(this);
            var isOutside     = pointMaxY.Y > getPointMaxY(other).Y;
            var turnDirection = GetTurnDirectionAt(this, pointMaxY);

            return(isOutside ? turnDirection : (Side)(-(int)turnDirection));
        }
コード例 #3
0
        private Side GetSideOpenedCase(UniversalLine otherLine)
        {
            bool codirectional(UniversalLine line, UniversalLine other)
            {
                using (var connectedFronts = new Line(line.StartPoint, other.StartPoint))
                    using (var connectedEnds = new Line(line.EndPoint, other.EndPoint))
                    {
                        return(!connectedFronts.Intersects(connectedEnds, 0) &&
                               !line.Intersects(connectedFronts, 1) &&
                               !other.Intersects(connectedFronts, 1) &&
                               !line.Intersects(connectedEnds, 1) &&
                               !other.Intersects(connectedEnds, 1));
                    }
            }

            var thisSegment  = Segments.First();
            var otherSegment = codirectional(this, otherLine)
                ? otherLine.Segments.First()
                : otherLine.Segments.Last();

            if (thisSegment.StartPoint == otherSegment.StartPoint)
            {
                return(thisSegment.GetFirstDerivative(0).GetSide(otherSegment.GetFirstDerivative(0)));
            }
            else if (thisSegment.StartPoint == otherSegment.EndPoint)
            {
                return(thisSegment.GetFirstDerivative(0).GetSide(otherSegment.GetFirstDerivative(1)));
            }

            var tangent = thisSegment.GetFirstDerivative(thisSegment.EvaluatePoint(0));
            var normal  = new Vector3d(tangent.Y, -tangent.X, 0);

            using (var normalLine = new Line(thisSegment.StartPoint, thisSegment.StartPoint + normal))
                using (var otherLineSegment = new Line(otherSegment.StartPoint, otherSegment.EndPoint))
                    using (var intersection = new Point3dCollection())
                    {
                        normalLine.IntersectWith(otherLineSegment, Intersect.ExtendBoth, intersection, IntPtr.Zero, IntPtr.Zero);
                        if (intersection.Count == 0)
                        {
                            throw new InvalidOperationException("Top line does not intersect bottom's normal");
                        }
                        return(tangent.GetSide(thisSegment.StartPoint.GetVectorTo(intersection[0])));
                    }
        }
コード例 #4
0
        public bool TryAddSegment(UniversalLine line)
        {
            var allowance = Segments.LastOrDefault()?.Length * 0.1 ?? 0.0;

            if (!Lines.Any())
            {
                Lines.Add(line);
            }

            else if (VisuallyClosed || line.VisuallyClosed && Lines.Any())
            {
                return(false);
            }

            else if (AlmostEqual(line.EndPoint, StartPoint, allowance))
            {
                Lines.Insert(0, line);
            }
            else if (AlmostEqual(line.StartPoint, EndPoint, allowance))
            {
                Lines.Add(line);
            }
            else if (AlmostEqual(line.StartPoint, StartPoint, allowance))
            {
                line.Reverse();
                Lines.Insert(0, line);
            }
            else if (AlmostEqual(line.EndPoint, EndPoint, allowance))
            {
                line.Reverse();
                Lines.Add(line);
            }
            else
            {
                return(false);
            }

            return(true);
        }