I'm using custom generated tiles on web map (displayed using openlayers). Tiles are generated by maperetive and it's great. However my map is rotated -3/4Pi (openlayers has this feature) and many labels are rendered upside down. I belive maperitive has no feature to render labels relative to arbitrary angle. May be there are other options to fix this?
I was able to solve the problem altering dll's of Maperitive (v2.4.1) using dnSpy.
Placement of labels is done by Karta.MapLabeling.Igor2LineFeatureLabelPlacementAlgorithm.EvaluatePosition()
method (from Karta.dll). Below is the altered method. I added + 225f
in three places. 225(deg) is equvalent of -3/4*Pi(radians). The added value should be positive.
public static LabelPositionEvaluation EvaluatePosition(IPolylineAnalysis polylineAnalysis, float position, float? lengthAround)
{
if (lengthAround != null)
{
float? num = lengthAround;
if (num.GetValueOrDefault() <= 0f && num != null)
{
throw new ArgumentOutOfRangeException("lengthAround");
}
}
LabelPositionEvaluation labelPositionEvaluation = new LabelPositionEvaluation(position);
float polylineLength = polylineAnalysis.PolylineLength;
float num2 = (lengthAround != null) ? (position * polylineLength - lengthAround.Value) : 0f;
float num3 = (lengthAround != null) ? (position * polylineLength + lengthAround.Value) : (polylineLength * 0.9999f);
labelPositionEvaluation.Fits = (num2 >= 0f && num3 <= polylineLength);
if (!labelPositionEvaluation.Fits)
{
return labelPositionEvaluation;
}
IPolylineWalker polylineWalker = polylineAnalysis.CreateWalker();
polylineWalker.MoveTo(num2);
int currentSegment = polylineWalker.CurrentSegment;
float num4 = (polylineAnalysis.SegmentLengths[polylineWalker.CurrentSegment] - polylineWalker.CurrentOffsetWithinSegment) * polylineWalker.CurrentAngle;
polylineWalker.MoveTo(num3);
int currentSegment2 = polylineWalker.CurrentSegment;
if (currentSegment2 == currentSegment)
{
num4 = ((lengthAround != null) ? (polylineWalker.CurrentAngle * lengthAround.Value * 2f) : (polylineWalker.CurrentAngle * polylineLength));
}
else
{
num4 += polylineWalker.CurrentOffsetWithinSegment * polylineWalker.CurrentAngle;
}
float num5 = 0f;
for (int i = currentSegment; i < currentSegment2; i++)
{
float num6 = (float)GeometryUtils.DifferenceBetweenAngles((double)polylineAnalysis.SegmentAngles[i], (double)polylineAnalysis.SegmentAngles[i + 1], 360.0);
if (num6 > num5)
{
num5 = num6;
}
if (i > currentSegment)
{
num4 += polylineAnalysis.SegmentLengths[i] * polylineAnalysis.SegmentAngles[i];
}
}
labelPositionEvaluation.AverageAngle = (float)GeometryUtils.NormalizeAngle((double)((lengthAround != null) ? (num4 / (lengthAround.Value * 2f) + 225f) : (num4 / polylineLength + 225f)), 360.0);
labelPositionEvaluation.MaxCornerAngle = num5;
float angleForPosition = (float)GeometryUtils.NormalizeAngle((double)(polylineAnalysis.GetAngleForPosition(labelPositionEvaluation.Position) + 225f), 360.0);
labelPositionEvaluation.ForwardDirection = (angleForPosition < 90f || angleForPosition > 270f);
return labelPositionEvaluation;
}