Esempio n. 1
0
        void ProcessExpandingSearchOnSide(int index, List <KeyValuePair <double, Point> > curvePoints, ICurve curve,
                                          double side, double radius,
                                          double distanceFromCurve, Point wh, ref double coveredLength,
                                          PointSetList placedPoints,
                                          double labelLength)
        {
            foreach (int i in ExpandingSearch(index, 0, curvePoints.Count))
            {
                KeyValuePair <double, Point> p = curvePoints[i];
                Point der = curve.Derivative(p.Key);

                if (der.LengthSquared < ApproximateComparer.DistanceEpsilon)
                {
                    continue;
                }

                Point o        = der.Rotate(Math.PI / 2).Normalize() * side;
                Point labelPos = p.Value + (radius + distanceFromCurve) * o;
                if (!Conflict(labelPos, radius, wh))
                {
                    // found a valid candidate position
                    var ps = new PointSet
                    {
                        Key    = p.Key,
                        Center = labelPos,
                        Inner  = p.Value + distanceFromCurve * o,
                        Outer  = p.Value + (2.0 * radius + distanceFromCurve) * o
                    };
                    coveredLength = i <= index
                                        ? placedPoints.AddFirst(ps)
                                        : placedPoints.AddLast(ps);

                    Debug.Assert(Math.Abs(PointSetLength(placedPoints.Points) - coveredLength) < 0.01);
                    if (coveredLength >= labelLength)
                    {
                        break;
                    }
                }
                else
                {
                    // not going to work!
                    break;
                }
            }
        }
        void CaseOfCoveredLengthGreaterThanLabelLength(Label label, PointSetList placedPoints, double coveredLength,
                                                       double labelLength, Point wh)
        {
            var             innerPoints   = new List <Point>();
            var             outerPoints   = new List <Point>();
            List <PointSet> orderedPoints = placedPoints.Points.ToList();
            double          excess        = coveredLength - labelLength;

            if (excess > 0)
            {
                // move back the last point
                PointSet q      = orderedPoints[orderedPoints.Count - 1];
                PointSet p      = orderedPoints[orderedPoints.Count - 2];
                Point    v      = q.Center - p.Center;
                double   length = v.Length;
                if (excess > length)
                {
                    q      = orderedPoints[0];
                    p      = orderedPoints[1];
                    v      = q.Center - p.Center;
                    length = v.Length;
                }
                Debug.Assert(length > excess);
                Point w = v * ((length - excess) / length);
                Debug.Assert(Math.Abs((length - w.Length) - excess) < 0.01);
                q.Center = p.Center + w;
                q.Inner  = p.Inner + w;
                q.Outer  = p.Outer + w;
            }
            double cl = PointSetLength(orderedPoints);

            Debug.Assert(Math.Abs(cl - labelLength) < 0.01);
            GoOverOrderedPointsAndAddLabelObstacels(orderedPoints, innerPoints, outerPoints, wh);
            // placed all points in label so we are done
            label.InnerPoints = innerPoints;
            label.OuterPoints = outerPoints;
        }
        /// <summary>
        ///     places a label
        /// </summary>
        /// <param name="label"></param>
        /// <returns></returns>
        bool PlaceEdgeLabelOnCurve(Label label)
        {
            ValidateArg.IsNotNull(label, "label");
            // approximate label with a set of circles
            // generate list of candidate points for label ordered by priority
            // check candidate point for conflicts - if none then stop and keep placement
            var edge = (Edge)label.GeometryParent;

            label.InnerPoints = null;
            List <KeyValuePair <double, Point> > curvePoints = edgePoints[edge];
            const double distanceFromCurve = 3;
            double       radius            = label.Height / 2.0;
            var          wh          = new Point(radius, radius);
            double       labelLength = label.Width;

            foreach (int index in ExpandingSearch(StartIndex(label, curvePoints), 0, curvePoints.Count))
            {
                double[] sides;
                var      curve = GetSidesAndEdgeCurve(label, edge, curvePoints, index, out sides);

                foreach (double side in sides)
                {
                    var    placedPoints  = new PointSetList();
                    double coveredLength = 0;
                    ProcessExpandingSearchOnSide(index, curvePoints, curve, side, radius, distanceFromCurve, wh,
                                                 ref coveredLength, placedPoints, labelLength);

                    if (coveredLength >= labelLength)
                    {
                        CaseOfCoveredLengthGreaterThanLabelLength(label, placedPoints, coveredLength, labelLength, wh);
                        return(true);
                    }
                }
            }
            return(false);
        }