/// <override></override> public override RelativePosition CalculateRelativePosition(int x, int y) { // The RelativePosition of a PolyLine is defined as // A = ControlPointId of the first vertex of the nearest line segment (FirstVertex -> LastVertex) // B = Angle between the line segment (A / next vertex of A) and the point // C = Distance of the point from A in percentage of the line segment's length RelativePosition result = RelativePosition.Empty; Point p = Point.Empty; p.Offset(x, y); // Find the nearest line segment int pointIdx = -1; float angleFromA = float.NaN; float distanceFromA = float.NaN; float lowestAbsDistance = float.MaxValue; float lineWidth = LineStyle.LineWidth / 2f + 2; int cnt = vertices.Count - 1; for (int i = 0; i < cnt; ++i) { float dist = Geometry.DistancePointLine(p, vertices[i], vertices[i + 1], true); if (dist < lowestAbsDistance) { lowestAbsDistance = dist; pointIdx = i; if (dist > lineWidth) { angleFromA = ((360 + Geometry.RadiansToDegrees(Geometry.Angle(vertices[i], vertices[i + 1], p))) % 360); } else { angleFromA = 0; } distanceFromA = Geometry.DistancePointPoint(vertices[i], p); } } if (pointIdx >= 0) { result.A = GetControlPointId(pointIdx); result.B = Geometry.DegreesToTenthsOfDegree(angleFromA); float segmentLength = Geometry.DistancePointPoint(vertices[pointIdx], vertices[pointIdx + 1]); if (segmentLength == 0) { result.C = 0; } else { result.C = (int)Math.Round((distanceFromA / (segmentLength / 100)) * 10); } Debug.Assert(result.B >= 0 && result.B <= 3600, "Calculated angle is out of range."); } if (result == RelativePosition.Empty) { result.A = result.B = result.C = 0; } return(result); }
/// <override></override> public override Point CalculateAbsolutePosition(RelativePosition relativePosition) { // The RelativePosition of a PolyLine is defined as // A = ControlPointId of the first vertex of the nearest line segment (FirstVertex -> LastVertex) // B = Angle between the line segment (A / next vertex of A) and the point // C = Distance of the point from A in percentage of the line segment's length Point result = Point.Empty; int idx = GetControlPointIndex(relativePosition.A); float angle = Geometry.TenthsOfDegreeToDegrees(relativePosition.B); float distance = relativePosition.C / 1000f; if (distance != 0) { float segmentLength = Geometry.DistancePointPoint(vertices[idx], vertices[idx + 1]); Point p = Geometry.VectorLinearInterpolation(vertices[idx], vertices[idx + 1], (distance)); result = Geometry.RotatePoint(vertices[idx], angle, p); Debug.Assert(Geometry.IsValid(result)); } else { result = vertices[idx]; } return(result); }
/// <summary> /// Calculates the absolute position of a RelativePosition. /// </summary> public abstract Point CalculateAbsolutePosition(RelativePosition relativePosition);