public IGraphic Extend(double distance, double segmentLength, JointType jointType, IEnumerable <Segment> segments = null) { var start = Start; var end = End; var vec = GraphicHelper.GetVector(end - start) * distance; IGraphic graphic = new GraphicLine(start + vec, end + vec); if (segments != null) { graphic = new GraphicCompositeCurve(graphic.Spilt(segments, segmentLength), false); } return(graphic); }
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); }