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); }