/// <summary>
        /// this code should never work!
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        static void CreateEdgeCurveWithNoTrimming(Edge edge, Point a, Point b)
        {
            Point ab = b - a;

            ab = ab.Normalize();

            Point lineStart = a;
            Point lineEnd   = b;

            Arrowhead targetArrow = edge.EdgeGeometry.TargetArrowhead;

            if (targetArrow != null)
            {
                targetArrow.TipPosition = b;
                lineEnd = b - ab * targetArrow.Length;
            }
            Arrowhead sourceArrow = edge.EdgeGeometry.SourceArrowhead;

            if (sourceArrow != null)
            {
                sourceArrow.TipPosition = a;
                lineStart = a + ab * sourceArrow.Length;
            }
            edge.Curve = new LineSegment(lineStart, lineEnd);
        }
        public FrameworkElement CreateFrameworkElementForRailArrowhead(Rail rail, Arrowhead arrowhead, Point curveAttachmentPoint, byte edgeTransparency) {
            var streamGeometry = new StreamGeometry();

            using (StreamGeometryContext context = streamGeometry.Open()) {
                AddArrow(context, curveAttachmentPoint, arrowhead.TipPosition,
                         PathStrokeThickness);
                //arrowhead.BasePoint = curveAttachmentPoint;

            }

            var path=new Path
            {
                Data = streamGeometry,
                Tag = this
            };

            SetPathStrokeToRailPath(rail, path);
            return path;
        }
        internal Rail(Arrowhead arrowhead, Point curveAttachmentPoint, LgEdgeInfo topRankedEdgeInfoOfTheRail,
            int zoomLevel)
#if DEBUG
            : this()
#endif
        {
            TopRankedEdgeInfoOfTheRail = topRankedEdgeInfoOfTheRail;
            Geometry = arrowhead.Clone();
            CurveAttachmentPoint = curveAttachmentPoint;
            ZoomLevel = zoomLevel;
        }
 void CreateStatisticsForArrowhead(Arrowhead arrowhead) {
     TileStatistic tile = GetOrCreateTileStatistic(arrowhead.TipPosition);
     tile.rails++;
 }
        Rail ContinueReadingRail(LgEdgeInfo topRankedEdgoInfo, int zoomLevel, LgLevel level) {
            XmlRead();
            string pointString;
            if (TokenIs(GeometryToken.Arrowhead)) {
                Point arrowheadPosition = TryGetPointAttribute(GeometryToken.ArrowheadPosition);
                Point attachmentPoint = TryGetPointAttribute(GeometryToken.CurveAttachmentPoint);
                Arrowhead ah = new Arrowhead {
                    TipPosition = arrowheadPosition,
                    Length = (attachmentPoint - arrowheadPosition).Length
                };
                XmlRead();
                ReadEndElement();
                var rail = new Rail(ah, attachmentPoint, topRankedEdgoInfo, zoomLevel);
                var tuple = new SymmetricSegment(arrowheadPosition, attachmentPoint);
                level._railDictionary[tuple] = rail;
                return rail;
            }

            if (TokenIs(GeometryToken.LineSegment)) {
                pointString = GetAttribute(GeometryToken.Points);
                var linePoints = ParsePoints(pointString);
                Debug.Assert(linePoints.Length == 2);
                LineSegment ls = new LineSegment(linePoints[0], linePoints[1]);
                XmlRead();
                ReadEndElement();
                var rail = new Rail(ls, topRankedEdgoInfo, zoomLevel);
                var tuple = new SymmetricSegment(ls.Start, ls.End);
                level._railDictionary[tuple] = rail;
                level._railTree.Add(ls.BoundingBox, rail);
                return rail;
            }
            if (TokenIs(GeometryToken.CubicBezierSegment)) {
                pointString = GetAttribute(GeometryToken.Points);
                var controlPoints = ParsePoints(pointString);
                Debug.Assert(controlPoints.Length == 4);
                var bs = new CubicBezierSegment(controlPoints[0], controlPoints[1], controlPoints[2], controlPoints[3]);
                XmlRead();
                ReadEndElement();
                var rail = new Rail(bs, topRankedEdgoInfo, zoomLevel);
                var tuple = new SymmetricSegment(bs.Start, bs.End);
                level._railDictionary[tuple] = rail;
                return rail;
            }
            throw new Exception();
        }