public LineSymbol(IGraphicFactory graphicFactory, DisplayModel displayModel, string elementName, XmlReader reader, string relativePathPrefix) : base(graphicFactory, displayModel) { this.display = Display.IFSPACE; this.rotate = true; this.relativePathPrefix = relativePathPrefix; this.dyScaled = new Dictionary <sbyte?, float?>(); ExtractValues(elementName, reader); }
private void ExtractValues(string elementName, XmlReader reader) { for (int i = 0; i < reader.AttributeCount; ++i) { reader.MoveToAttribute(i); string name = reader.Name; string value = reader.Value; if (SRC.Equals(name)) { this.src = value; } else if (CAT.Equals(name)) { this.category = value; } else if (DISPLAY.Equals(name)) { this.display = Display.FromString(value); } else if (ID.Equals(name)) { this.id = value; } else if (PRIORITY.Equals(name)) { this.priority = int.Parse(value); } else if (SYMBOL_HEIGHT.Equals(name)) { this.height = XmlUtils.ParseNonNegativeInteger(name, value) * displayModel.ScaleFactor; } else if (SYMBOL_PERCENT.Equals(name)) { this.percent = XmlUtils.ParseNonNegativeInteger(name, value); } else if (SYMBOL_SCALING.Equals(name)) { this.scaling = FromValue(value); } else if (SYMBOL_WIDTH.Equals(name)) { this.width = XmlUtils.ParseNonNegativeInteger(name, value) * displayModel.ScaleFactor; } else { throw XmlUtils.CreateXmlReaderException(elementName, name, value, i); } } }
public PathText(IGraphicFactory graphicFactory, DisplayModel displayModel, string elementName, XmlReader reader) : base(graphicFactory, displayModel) { this.fill = graphicFactory.CreatePaint(); this.fill.Color = Color.BLACK; this.fill.Style = Style.FILL; this.fill.TextAlign = Align.CENTER; this.fills = new Dictionary <sbyte?, IPaint>(); this.stroke = graphicFactory.CreatePaint(); this.stroke.Color = Color.BLACK; this.stroke.Style = Style.STROKE; this.stroke.TextAlign = Align.CENTER; this.strokes = new Dictionary <sbyte?, IPaint>(); this.dyScaled = new Dictionary <sbyte?, float?>(); this.display = Display.IFSPACE; ExtractValues(graphicFactory, displayModel, elementName, reader); }
public Symbol(IGraphicFactory graphicFactory, DisplayModel displayModel, string elementName, XmlReader reader, string relativePathPrefix) : base(graphicFactory, displayModel) { this.relativePathPrefix = relativePathPrefix; this.display = Display.IFSPACE; ExtractValues(elementName, reader); }
public void RenderWayText(RenderContext renderContext, Display display, int priority, string textKey, float dy, IPaint fill, IPaint stroke, PolylineContainer way) { WayDecorator.RenderText(way.Tile, textKey, display, priority, dy, fill, stroke, way.CoordinatesAbsolute, renderContext.labels); }
public void RenderWaySymbol(RenderContext renderContext, Display display, int priority, IBitmap symbol, float dy, bool alignCenter, bool repeat, float repeatGap, float repeatStart, bool rotate, PolylineContainer way) { WayDecorator.RenderSymbol(symbol, display, priority, dy, alignCenter, repeat, repeatGap, repeatStart, rotate, way.CoordinatesAbsolute, renderContext.labels); }
public void RenderPointOfInterestSymbol(RenderContext renderContext, Display display, int priority, IBitmap symbol, PointOfInterest poi) { Point poiPosition = MercatorProjection.GetPixelAbsolute(poi.Position, renderContext.rendererJob.tile.MapSize); renderContext.labels.Add(new SymbolContainer(poiPosition, display, priority, symbol)); }
public void RenderPointOfInterestCaption(RenderContext renderContext, Display display, int priority, string caption, float horizontalOffset, float verticalOffset, IPaint fill, IPaint stroke, Position position, int maxTextWidth, PointOfInterest poi) { Point poiPosition = MercatorProjection.GetPixelAbsolute(poi.Position, renderContext.rendererJob.tile.MapSize); renderContext.labels.Add(this.graphicFactory.CreatePointTextContainer(poiPosition.Offset(horizontalOffset, verticalOffset), display, priority, caption, fill, stroke, null, position, maxTextWidth)); }
public void RenderAreaSymbol(RenderContext renderContext, Display display, int priority, IBitmap symbol, PolylineContainer way) { Point centerPosition = way.CenterAbsolute; renderContext.labels.Add(new SymbolContainer(centerPosition, display, priority, symbol)); }
public void RenderAreaCaption(RenderContext renderContext, Display display, int priority, string caption, float horizontalOffset, float verticalOffset, IPaint fill, IPaint stroke, Position position, int maxTextWidth, PolylineContainer way) { Point centerPoint = way.CenterAbsolute.Offset(horizontalOffset, verticalOffset); renderContext.labels.Add(this.graphicFactory.CreatePointTextContainer(centerPoint, display, priority, caption, fill, stroke, null, position, maxTextWidth)); }
public Caption(IGraphicFactory graphicFactory, DisplayModel displayModel, string elementName, XmlReader reader, IDictionary <string, Symbol> symbols) : base(graphicFactory, displayModel) { this.fill = graphicFactory.CreatePaint(); this.fill.Color = Color.BLACK; this.fill.Style = Style.FILL; this.fills = new Dictionary <sbyte?, IPaint>(); this.stroke = graphicFactory.CreatePaint(); this.stroke.Color = Color.BLACK; this.stroke.Style = Style.STROKE; this.strokes = new Dictionary <sbyte?, IPaint>(); this.dyScaled = new Dictionary <sbyte?, float?>(); this.display = Display.IFSPACE; this.gap = DEFAULT_GAP * displayModel.ScaleFactor; ExtractValues(graphicFactory, displayModel, elementName, reader); if (!string.ReferenceEquals(this.symbolId, null)) { Symbol symbol = symbols[this.symbolId]; if (symbol != null) { this.bitmap = symbol.Bitmap; } } if (this.position == null) { // sensible defaults: below if symbolContainer is present, center if not if (this.bitmap == null) { this.position = Position.CENTER; } else { this.position = Position.BELOW; } } else if (this.position == Position.CENTER || this.position == Position.BELOW || this.position == Position.ABOVE) { this.stroke.TextAlign = Align.CENTER; this.fill.TextAlign = Align.CENTER; } else if (this.position == Position.BELOW_LEFT || this.position == Position.ABOVE_LEFT || this.position == Position.LEFT) { this.stroke.TextAlign = Align.RIGHT; this.fill.TextAlign = Align.RIGHT; } else if (this.position == Position.BELOW_RIGHT || this.position == Position.ABOVE_RIGHT || this.position == Position.RIGHT) { this.stroke.TextAlign = Align.LEFT; this.fill.TextAlign = Align.LEFT; } else { throw new System.ArgumentException("Position invalid"); } this.maxTextWidth = displayModel.MaxTextWidth; }
private void ExtractValues(IGraphicFactory graphicFactory, DisplayModel displayModel, string elementName, XmlReader reader) { FontFamily fontFamily = FontFamily.DEFAULT; FontStyle fontStyle = FontStyle.NORMAL; for (int i = 0; i < reader.AttributeCount; ++i) { reader.MoveToAttribute(i); string name = reader.Name; string value = reader.Value; if (K.Equals(name)) { this.textKey = TextKey.getInstance(value); } else if (POSITION.Equals(name)) { this.position = Position.FromString(value); } else if (CAT.Equals(name)) { this.category = value; } else if (DISPLAY.Equals(name)) { this.display = Display.FromString(value); } else if (DY.Equals(name)) { this.dy = float.Parse(value) * displayModel.ScaleFactor; } else if (FONT_FAMILY.Equals(name)) { fontFamily = FontFamily.FromString(value); } else if (FONT_STYLE.Equals(name)) { fontStyle = FontStyle.FromString(value); } else if (FONT_SIZE.Equals(name)) { this.fontSize = XmlUtils.ParseNonNegativeFloat(name, value) * displayModel.ScaleFactor; } else if (FILL.Equals(name)) { this.fill.Color = (Color)XmlUtils.GetColor(graphicFactory, value); } else if (PRIORITY.Equals(name)) { this.priority = int.Parse(value); } else if (STROKE.Equals(name)) { this.stroke.Color = (Color)XmlUtils.GetColor(graphicFactory, value); } else if (STROKE_WIDTH.Equals(name)) { this.stroke.StrokeWidth = XmlUtils.ParseNonNegativeFloat(name, value) * displayModel.ScaleFactor; } else if (SYMBOL_ID.Equals(name)) { this.symbolId = value; } else { throw XmlUtils.CreateXmlReaderException(elementName, name, value, i); } } this.fill.SetTypeface(fontFamily, fontStyle); this.stroke.SetTypeface(fontFamily, fontStyle); XmlUtils.CheckMandatoryAttribute(elementName, K, this.textKey); }
internal static void RenderSymbol(IBitmap symbolBitmap, Display display, int priority, float dy, bool alignCenter, bool repeatSymbol, float repeatGap, float repeatStart, bool rotate, Point[][] coordinates, ICollection <MapElementContainer> currentItems) { int skipPixels = (int)repeatStart; Point[] c; if (dy == 0f) { c = coordinates[0]; } else { c = RendererUtils.ParallelPath(coordinates[0], dy); } // get the first way point coordinates double previousX = c[0].X; double previousY = c[0].Y; // draw the symbolContainer on each way segment float segmentLengthRemaining; float segmentSkipPercentage; float theta = 0; for (int i = 1; i < c.Length; ++i) { // get the current way point coordinates double currentX = c[i].X; double currentY = c[i].Y; // calculate the length of the current segment (Euclidian distance) double diffX = currentX - previousX; double diffY = currentY - previousY; double segmentLengthInPixel = Math.Sqrt(diffX * diffX + diffY * diffY); segmentLengthRemaining = (float)segmentLengthInPixel; while (segmentLengthRemaining - skipPixels > repeatStart) { // calculate the percentage of the current segment to skip segmentSkipPercentage = skipPixels / segmentLengthRemaining; // move the previous point forward towards the current point previousX += diffX * segmentSkipPercentage; previousY += diffY * segmentSkipPercentage; if (rotate) { // if we do not rotate theta will be 0, which is correct theta = (float)Math.Atan2(currentY - previousY, currentX - previousX); } Point point = new Point(previousX, previousY); currentItems.Add(new SymbolContainer(point, display, priority, symbolBitmap, theta, alignCenter)); // check if the symbolContainer should only be rendered once if (!repeatSymbol) { return; } // recalculate the distances diffX = currentX - previousX; diffY = currentY - previousY; // recalculate the remaining length of the current segment segmentLengthRemaining -= skipPixels; // set the amount of pixels to skip before repeating the symbolContainer skipPixels = (int)repeatGap; } skipPixels -= (int)segmentLengthRemaining; if (skipPixels < repeatStart) { skipPixels = (int)repeatStart; } // set the previous way point coordinates for the next loop previousX = currentX; previousY = currentY; } }
/// <summary> /// Finds the segments of a line along which a name can be drawn and then adds WayTextContainers /// to the list of drawable items. /// </summary> /// <param name="tile"> the tile on which the text will be drawn. </param> /// <param name="text"> the text to draw </param> /// <param name="priority"> priority of the text </param> /// <param name="dy"> if 0, then a line parallel to the coordinates will be calculated first </param> /// <param name="fill"> fill paint for text </param> /// <param name="stroke"> stroke paint for text </param> /// <param name="coordinates"> the list of way coordinates </param> /// <param name="currentLabels"> the list of labels to which a new WayTextContainer will be added </param> internal static void RenderText(Tile tile, string text, Display display, int priority, float dy, IPaint fill, IPaint stroke, Point[][] coordinates, ICollection <MapElementContainer> currentLabels) { // Calculate the way name length plus some margin of safety int wayNameWidth = (stroke == null) ? fill.GetTextWidth(text) + WAYNAME_SAFETY_MARGIN * 2 : stroke.GetTextWidth(text) + WAYNAME_SAFETY_MARGIN * 2; // Compute the tile boundary on which we render the name. // We make the tile smaller because otherwise we sometimes write the text beyond the tile boundary // (e.g. a road that runs parallel just below a tile boundary) double textHeight = (stroke == null) ? fill.GetTextHeight(text) : stroke.GetTextHeight(text); Rectangle tileBoundary = tile.BoundaryAbsolute.Envelope(-textHeight); int skipPixels = 0; Point[] c; if (dy == 0f) { c = coordinates[0]; } else { c = RendererUtils.ParallelPath(coordinates[0], dy); } // iterate through the segments to find those long enough to draw the way name on them for (int i = 1; i < c.Length; ++i) { LineSegment currentSegment = new LineSegment(c[i - 1], c[i]); double currentLength = currentSegment.Length(); skipPixels -= (int)currentLength; if (skipPixels > 0) { // we should still be skipping pixels, so skip this segment. Note that // this does not guarantee that we skip any certain minimum of pixels, // it is more a rule of thumb. continue; } if (currentLength < wayNameWidth) { // no point trying to clip, the segment is too short anyway continue; } // clip the current segment to the tile, so that we never overlap tile boundaries // with the way name LineSegment drawableSegment = currentSegment.ClipToRectangle(tileBoundary); if (drawableSegment == null) { // this happens if the segment does not intersect the tile continue; } double segmentLengthInPixel = drawableSegment.Length(); if (segmentLengthInPixel < wayNameWidth) { // not enough space to draw name on this segment continue; } // now calculate the actually used part of the segment to ensure the bbox of the waytext container // is as small as possible. The offset at the beginning/end is to ensure that we are a bit off the center // of an intersection (otherwise we have more collisions at the intersection) LineSegment actuallyUsedSegment = drawableSegment.SubSegment(WAYNAME_SAFETY_MARGIN, wayNameWidth - WAYNAME_SAFETY_MARGIN); // check to prevent inverted way names if (actuallyUsedSegment.Start.X <= actuallyUsedSegment.End.X) { currentLabels.Add(new WayTextContainer(actuallyUsedSegment.Start, actuallyUsedSegment.End, display, priority, text, fill, stroke, textHeight)); } else { currentLabels.Add(new WayTextContainer(actuallyUsedSegment.End, actuallyUsedSegment.Start, display, priority, text, fill, stroke, textHeight)); } skipPixels = wayNameWidth; } }
private void ExtractValues(string elementName, XmlReader reader) { this.repeatGap = REPEAT_GAP_DEFAULT * displayModel.ScaleFactor; this.repeatStart = REPEAT_START_DEFAULT * displayModel.ScaleFactor; for (int i = 0; i < reader.AttributeCount; ++i) { reader.MoveToAttribute(i); string name = reader.Name; string value = reader.Value; if (SRC.Equals(name)) { this.src = value; } else if (DISPLAY.Equals(name)) { this.display = Display.FromString(value); } else if (DY.Equals(name)) { this.dy = float.Parse(value) * displayModel.ScaleFactor; } else if (ALIGN_CENTER.Equals(name)) { this.alignCenter = bool.Parse(value); } else if (CAT.Equals(name)) { this.category = value; } else if (PRIORITY.Equals(name)) { this.priority = int.Parse(value); } else if (REPEAT.Equals(name)) { this.repeat = bool.Parse(value); } else if (REPEAT_GAP.Equals(name)) { this.repeatGap = float.Parse(value) * displayModel.ScaleFactor; } else if (REPEAT_START.Equals(name)) { this.repeatStart = float.Parse(value) * displayModel.ScaleFactor; } else if (ROTATE.Equals(name)) { this.rotate = bool.Parse(value); } else if (SYMBOL_HEIGHT.Equals(name)) { this.height = XmlUtils.ParseNonNegativeInteger(name, value) * displayModel.ScaleFactor; } else if (SYMBOL_PERCENT.Equals(name)) { this.percent = XmlUtils.ParseNonNegativeInteger(name, value); } else if (SYMBOL_SCALING.Equals(name)) { this.scaling = FromValue(value); } else if (SYMBOL_WIDTH.Equals(name)) { this.width = XmlUtils.ParseNonNegativeInteger(name, value) * displayModel.ScaleFactor; } else { throw XmlUtils.CreateXmlReaderException(elementName, name, value, i); } } }