Beispiel #1
0
        internal static IEnumerable <GeoLine> GetLines(IEnumerable <Point> points, double distance, bool isClosed)
        {
            var firstLine = default(GeoLine?);
            var lastPoint = default(Point);
            var isFirst   = true;

            foreach (var point in points)
            {
                if (isFirst)
                {
                    isFirst = false;
                }
                else
                {
                    var start = lastPoint;
                    var end   = point;
                    var vec   = GetVector(end - start) * distance;
                    start += vec;
                    end   += vec;
                    var line = new GeoLine(start, end);
                    if (isClosed && firstLine == null)
                    {
                        firstLine = line;
                    }
                    yield return(line);
                }
                lastPoint = point;
            }
            if (firstLine.HasValue)
            {
                yield return(firstLine.Value);
            }
        }
Beispiel #2
0
        public Point?Cross(GeoLine line)
        {
            var crossPoint = default(Point?);

            var d = A * line.B - B * line.A;

            if (!Utilities.IsZero(d))
            {
                var p = new Point();
                p.X        = (line.C * B - C * line.B) / d;
                p.Y        = -(line.C * A - C * line.A) / d;
                crossPoint = p;
            }

            return(crossPoint);
        }
Beispiel #3
0
 public double AngleTo(GeoLine line)
 {
     return(Vector.AngleBetween(_direction, line._direction));
 }
Beispiel #4
0
        internal static IGraphic Extend(IList <Point> points, double distance, JointType jointType, IEnumerable <Segment> segments, bool isClosed)
        {
            var tuples     = new List <Tuple <IGraphic, GeoLine?> >();
            var lastLine   = default(GeoLine?);
            var lastOrigin = default(GeoLine?);
            var index      = 0;

            foreach (var line in GetLines(points, distance, isClosed))
            {
                if (lastLine.HasValue)
                {
                    var beforeOrigin = lastOrigin.Value;
                    var before       = lastLine.Value;
                    var after        = line;
                    var angle        = before.AngleTo(after);
                    if (Utilities.IsZero(Math.Abs(angle)))
                    {
                        tuples.Add(new Tuple <IGraphic, GeoLine?>(new GraphicLine(before.P1, before.P2), beforeOrigin));
                    }
                    else
                    {
                        var flag = Utilities.IsClose(Math.Abs(angle), 180);
                        if (angle < 0 ^ distance > 0)
                        {
                            switch (jointType)
                            {
                            case JointType.Flat:
                            {
                                tuples.Add(new Tuple <IGraphic, GeoLine?>(new GraphicLine(before.P1, before.P2), beforeOrigin));
                                tuples.Add(new Tuple <IGraphic, GeoLine?>(new GraphicLine(before.P2, after.P1), null));
                            }
                            break;

                            case JointType.Sharp:
                            {
                                if (flag)
                                {
                                    return(null);
                                }
                                var cp = before.Cross(after);
                                if (!cp.HasValue)
                                {
                                    return(null);
                                }
                                tuples.Add(new Tuple <IGraphic, GeoLine?>(new GraphicLine(before.P1, cp.Value), beforeOrigin));
                                after = new GeoLine(cp.Value, after.P2);
                            }
                            break;

                            case JointType.Rounded:
                            {
                                tuples.Add(new Tuple <IGraphic, GeoLine?>(new GraphicLine(before.P1, before.P2), beforeOrigin));
                                var center     = points[index];
                                var radius     = Math.Abs(distance);
                                var startV     = before.P2 - center;
                                var endV       = after.P1 - center;
                                var startAngle = Vector.AngleBetween(new Vector(1, 0), startV);
                                var endAngle   = startAngle + Vector.AngleBetween(startV, endV);
                                if (endAngle > startAngle)
                                {
                                    tuples.Add(new Tuple <IGraphic, GeoLine?>(new GraphicArc(center, radius, startAngle, endAngle), null));
                                }
                                else
                                {
                                    tuples.Add(new Tuple <IGraphic, GeoLine?>(new GraphicArc(center, radius, endAngle, startAngle, true), null));
                                }
                            }
                            break;
                            }
                        }
                        else
                        {
                            if (flag)
                            {
                                return(null);
                            }
                            var cp = before.Cross(after);
                            if (cp.HasValue && before.IsOnLine(cp.Value) && after.IsOnLine(cp.Value))
                            {
                                before = new GeoLine(before.P1, cp.Value);
                                after  = new GeoLine(cp.Value, after.P2);
                                tuples.Add(new Tuple <IGraphic, GeoLine?>(new GraphicLine(before.P1, before.P2), beforeOrigin));
                            }
                            else
                            {
                                return(null);
                            }
                        }
                    }
                    lastLine = after;
                }
                else
                {
                    lastLine = line;
                }
                lastOrigin = line;
                index++;
            }
            if (lastLine.HasValue)
            {
                if (!isClosed)
                {
                    tuples.Add(new Tuple <IGraphic, GeoLine?>(new GraphicLine(lastLine.Value.P1, lastLine.Value.P2), lastOrigin));
                }
                else
                {
                    var tuple     = tuples[0];
                    var firstLine = (GraphicLine)tuple.Item1;
                    var p1        = lastLine.Value.P1;
                    var p2        = firstLine.P2;
                    var vec1      = p2 - firstLine.P1;
                    var vec2      = p2 - p1;
                    if (Utilities.IsSameDirection(vec1, vec2))
                    {
                        firstLine = new GraphicLine(p1, p2);
                        tuples[0] = new Tuple <IGraphic, GeoLine?>(firstLine, tuple.Item2);
                    }
                    else
                    {
                        return(null);
                    }
                }
            }

            if (tuples.Count > 0)
            {
                if (segments != null)
                {
                    var graphics = new List <IGraphic>();
                    foreach (var segment in segments)
                    {
                        var started       = false;
                        var subGraphics   = new List <IGraphic>();
                        var currentOffset = 0d;
                        var startOffset   = segment.StartOffset;
                        var endOffset     = segment.EndOffset;
                        foreach (var tuple in tuples)
                        {
                            var item = tuple.Item2;
                            if (item.HasValue)
                            {
                                var line   = item.Value;
                                var offset = currentOffset + line.Length;
                                if (currentOffset < endOffset && offset > startOffset)
                                {
                                    if (currentOffset >= startOffset && offset <= endOffset)
                                    {
                                        subGraphics.Add(tuple.Item1);
                                        started = true;
                                    }
                                    else
                                    {
                                        var brk     = false;
                                        var newLine = (GraphicLine)tuple.Item1;
                                        var sp      = newLine.Start;
                                        var ep      = newLine.End;
                                        if (startOffset > currentOffset)
                                        {
                                            var p = line.GetPoint(startOffset - currentOffset);
                                            if (newLine.IsOnLine(p))
                                            {
                                                sp      = p;
                                                started = true;
                                            }
                                            else
                                            {
                                                var vec1 = newLine.End - p;
                                                var vec2 = newLine.End - newLine.Start;
                                                started = Utilities.IsSameDirection(vec1, vec2);
                                            }
                                        }
                                        else
                                        {
                                            started = true;
                                        }

                                        if (endOffset < offset)
                                        {
                                            var p = line.GetPoint(endOffset - currentOffset);
                                            if (newLine.IsOnLine(p))
                                            {
                                                ep = p;
                                            }
                                            else
                                            {
                                                var vec1 = p - newLine.Start;
                                                var vec2 = newLine.End - newLine.Start;
                                                started = Utilities.IsSameDirection(vec1, vec2);
                                            }
                                            brk = true;
                                        }

                                        if (started)
                                        {
                                            subGraphics.Add(new GraphicLine(sp, ep));
                                        }
                                        if (brk)
                                        {
                                            break;
                                        }
                                    }
                                }
                                else if (currentOffset >= endOffset)
                                {
                                    if (subGraphics.Count > 0)
                                    {
                                        graphics.Add(new GraphicCompositeCurve(subGraphics, true));
                                    }
                                    break;
                                }
                                currentOffset = offset;
                            }
                            else if (started)
                            {
                                subGraphics.Add(tuple.Item1);
                            }
                        }
                        if (subGraphics.Count > 0)
                        {
                            graphics.Add(new GraphicCompositeCurve(subGraphics, true));
                        }
                    }
                    if (graphics.Count > 0)
                    {
                        return(new GraphicCompositeCurve(graphics, false));
                    }
                }
                else
                {
                    return(new GraphicCompositeCurve(tuples.Select(graphic => graphic.Item1), true));
                }
            }
            return(null);
        }