Beispiel #1
0
        /// <summary>
        /// Method to place the street direction symbols
        /// </summary>
        /// <param name="map"></param>
        /// <param name="lineString"></param>
        /// <param name="graphics"></param>
        private void OnRenderInternal(SharpMap.MapViewport map, GeoAPI.Geometries.ILineString lineString,
                                      System.Drawing.Graphics graphics)
        {
            var length = lineString.Length;
            var lil    = new NetTopologySuite.LinearReferencing.LengthIndexedLine(lineString);

            if (length < RepeatInterval + ArrowLength)
            {
                var start = System.Math.Max(0, (length - ArrowLength) / 2);
                var end   = System.Math.Min(length, (length + ArrowLength) / 2);
                var arrow = (GeoAPI.Geometries.ILineString)lil.ExtractLine(start, end);

                RenderArrow(map, graphics, arrow);

                return;
            }

            var numArrows = (int)((lineString.Length - ArrowLength) / RepeatInterval);
            var offset    = (lineString.Length - numArrows * RepeatInterval - ArrowLength) * 0.5;

            while (offset + ArrowLength < lineString.Length)
            {
                var arrow = (GeoAPI.Geometries.ILineString)lil.ExtractLine(offset, offset + ArrowLength);
                RenderArrow(map, graphics, arrow);
                offset += RepeatInterval;
            }
        }
Beispiel #2
0
        public GeoAPI.Geometries.IMultiLineString SplitLineString(
            GeoAPI.Geometries.ILineString lineString,
            System.Double length)
        {
            if (lineString == null || lineString.IsEmpty)
            {
                throw new System.ArgumentException("Linestring is null or Empty", "lineString");
            }

            //var gf = new NetTopologySuite.Geometries.GeometryFactory();
            //var ntsLine = (NetTopologySuite.Geometries.LineString)
            //                SharpMap.Converters.NTS.GeometryConverter.ToNTSGeometry(lineString, gf);

            var ret = new System.Collections.Generic.List <GeoAPI.Geometries.ILineString>();
            var lil = new NetTopologySuite.LinearReferencing.LengthIndexedLine(lineString);

            double currentLength = 0d;

            while (currentLength < lineString.Length)
            {
                var tmpLine = (GeoAPI.Geometries.ILineString)
                              lil.ExtractLine(currentLength, currentLength + length);
                ret.Add(tmpLine);
                currentLength += length;
            }
            return(lineString.Factory.CreateMultiLineString(ret.ToArray()));
        }
public SharpMap.Geometries.MultiLineString SplitLineString(
    SharpMap.Geometries.LineString lineString, 
    System.Double length)
{
    if (lineString == null || lineString.IsEmpty())
        throw new System.ArgumentException("Linestring is null or Empty", "lineString");

    var gf = new NetTopologySuite.Geometries.GeometryFactory();
    var ntsLine = (NetTopologySuite.Geometries.LineString)
                    SharpMap.Converters.NTS.GeometryConverter.ToNTSGeometry(lineString, gf);

    var ret = new SharpMap.Geometries.MultiLineString();
    var lil = new NetTopologySuite.LinearReferencing.LengthIndexedLine(ntsLine);

    double currentLength = 0d;
    while (currentLength  < ntsLine.Length)
    {
        var tmpLine = (NetTopologySuite.Geometries.LineString)
            lil.ExtractLine(currentLength, currentLength + length);
        ret.LineStrings.Add((SharpMap.Geometries.LineString)
            SharpMap.Converters.NTS.GeometryConverter.ToSharpMapGeometry(tmpLine));
        currentLength += length;
    }
    return ret;
}
Beispiel #4
0
    /// <summary>
    /// Method to place the street direction symbols
    /// </summary>
    /// <param name="map"></param>
    /// <param name="lineString"></param>
    /// <param name="graphics"></param>
    private void OnRenderInternal(SharpMap.Map map, GeoAPI.Geometries.ILineString lineString,
        System.Drawing.Graphics graphics)
    {

        var length = lineString.Length;
        var lil = new NetTopologySuite.LinearReferencing.LengthIndexedLine(lineString);
        if (length < RepeatInterval + ArrowLength)
        {
            var start = System.Math.Max(0, (length - ArrowLength)/2);
            var end = System.Math.Min(length, (length + ArrowLength)/2);
            var arrow = (GeoAPI.Geometries.ILineString) lil.ExtractLine(start, end);

            RenderArrow(map, graphics, arrow);

            return;
        }

        var numArrows = (int) ((lineString.Length - ArrowLength)/RepeatInterval);
        var offset = (lineString.Length - numArrows*RepeatInterval - ArrowLength)*0.5;

        while (offset + ArrowLength < lineString.Length)
        {
            var arrow = (GeoAPI.Geometries.ILineString) lil.ExtractLine(offset, offset + ArrowLength);
            RenderArrow(map, graphics, arrow);
            offset += RepeatInterval;
        }

    }
        public SharpMap.Geometries.MultiLineString SplitLineString(
            SharpMap.Geometries.LineString lineString,
            System.Double length)
        {
            if (lineString == null || lineString.IsEmpty())
            {
                throw new System.ArgumentException("Linestring is null or Empty", "lineString");
            }

            var gf      = new NetTopologySuite.Geometries.GeometryFactory();
            var ntsLine = (NetTopologySuite.Geometries.LineString)
                          SharpMap.Converters.NTS.GeometryConverter.ToNTSGeometry(lineString, gf);

            var ret = new SharpMap.Geometries.MultiLineString();
            var lil = new NetTopologySuite.LinearReferencing.LengthIndexedLine(ntsLine);

            double currentLength = 0d;

            while (currentLength < ntsLine.Length)
            {
                var tmpLine = (NetTopologySuite.Geometries.LineString)
                              lil.ExtractLine(currentLength, currentLength + length);
                ret.LineStrings.Add((SharpMap.Geometries.LineString)
                                    SharpMap.Converters.NTS.GeometryConverter.ToSharpMapGeometry(tmpLine));
                currentLength += length;
            }
            return(ret);
        }
Beispiel #6
0
        public void CrossAndIntersectionTest()
        {
            // Arrange
            var gf = new GeometryFactory(new PrecisionModel(100000000));

            var closestCoordinate = new Coordinate(152608, 594957);
            var closestLine       = gf.CreateLineString(new[]
            {
                new Coordinate(152348, 595130),
                new Coordinate(152421, 595061),
                new Coordinate(152455, 595033),
                new Coordinate(152524, 595001),
                new Coordinate(152593, 594973),
                new Coordinate(152622, 594946),
                new Coordinate(152634, 594930),
                new Coordinate(152641, 594921),
                new Coordinate(152649, 594910),
                new Coordinate(152863, 594623),
                new Coordinate(152873, 594607)
            });
            var    indexedLine     = new NetTopologySuite.LinearReferencing.LengthIndexedLine(closestLine);
            double projectedIndex  = indexedLine.Project(closestCoordinate);
            var    coordinateToAdd = indexedLine.ExtractPoint(projectedIndex);

            gf.PrecisionModel.MakePrecise(coordinateToAdd);

            var line = gf.CreateLineString(new[] { new Coordinate(152503, 594904), coordinateToAdd });

            ToImage(0, closestLine, line, GeometryFactory.Default.CreatePoint(coordinateToAdd));

            // act
            var intersectionPt = line.Intersection(closestLine).Coordinate;

            gf.PrecisionModel.MakePrecise(intersectionPt);

            // assert intersection point is equal to coordinate to add
            Assert.AreEqual(coordinateToAdd, intersectionPt);

            // act insertion of coordinate to add
            var lip = new NetTopologySuite.LinearReferencing.LocationIndexOfPoint(closestLine);
            var ll  = lip.IndexOf(coordinateToAdd);

            if (!ll.IsVertex)
            {
                var cl  = (ILineString)closestLine;
                var cls = cl.Factory.CoordinateSequenceFactory.Create(cl.CoordinateSequence.Count + 1, cl.CoordinateSequence.Ordinates);
                CoordinateSequences.Copy(cl.CoordinateSequence, 0, cls, 0, ll.SegmentIndex + 1);
                cls.SetOrdinate(ll.SegmentIndex + 1, Ordinate.X, coordinateToAdd.X);
                cls.SetOrdinate(ll.SegmentIndex + 1, Ordinate.Y, coordinateToAdd.Y);
                CoordinateSequences.Copy(cl.CoordinateSequence, ll.SegmentIndex + 1, cls, ll.SegmentIndex + 2, cl.CoordinateSequence.Count - ll.SegmentIndex - 1);
                closestLine = gf.CreateLineString(cls);
            }

            ToImage(1, closestLine, line, GeometryFactory.Default.CreatePoint(coordinateToAdd));

            Assert.IsTrue(line.Touches(closestLine));
            Assert.IsFalse(line.Crosses(closestLine));
        }
public GeoAPI.Geometries.IMultiLineString SplitLineString(
    GeoAPI.Geometries.ILineString lineString, 
    System.Double length)
{
    if (lineString == null || lineString.IsEmpty)
        throw new System.ArgumentException("Linestring is null or Empty", "lineString");

    //var gf = new NetTopologySuite.Geometries.GeometryFactory();
    //var ntsLine = (NetTopologySuite.Geometries.LineString)
    //                SharpMap.Converters.NTS.GeometryConverter.ToNTSGeometry(lineString, gf);

    var ret = new System.Collections.Generic.List<GeoAPI.Geometries.ILineString>();
    var lil = new NetTopologySuite.LinearReferencing.LengthIndexedLine(lineString);

    double currentLength = 0d;
    while (currentLength  < lineString.Length)
    {
        var tmpLine = (GeoAPI.Geometries.ILineString)
            lil.ExtractLine(currentLength, currentLength + length);
        ret.Add(tmpLine);
        currentLength += length;
    }
    return lineString.Factory.CreateMultiLineString(ret.ToArray());
}
Beispiel #8
0
        private static BaseLabel CreatePathLabel(ILineString line, string text, SizeF textMeasure,
                                                 int priority, LabelStyle style, MapViewport map)
        {
            if (line == null)
            {
                return(null);
            }

            var factory = line.Factory;

            // Simplify the line for smoother labeling
            double avgCharacterSpace = 2d * textMeasure.Width / text.Length * map.PixelWidth;
            var    simplifier        = new NetTopologySuite.Simplify.VWLineSimplifier(line.Coordinates, avgCharacterSpace);

            line = factory.CreateLineString(simplifier.Simplify());

            var labelLength = textMeasure.Width * map.PixelWidth;
            var labelHeight = textMeasure.Height * map.PixelHeight;

            var offsetX = style.Offset.X * map.PixelWidth;  // positive = increasing measure
            var offsetY = style.Offset.Y * map.PixelHeight; // positive = right side of line

            var start = 0d;

            if (style.HorizontalAlignment == LabelStyle.HorizontalAlignmentEnum.Center)
            {
                start = line.Length * 0.5 - labelLength * 0.5;
            }
            else if (style.HorizontalAlignment == LabelStyle.HorizontalAlignmentEnum.Right)
            {
                start = line.Length - labelLength;
            }

            start += offsetX;

            // Constrain label length
            if (labelLength > 0.95 * line.Length && !style.IgnoreLength ||
                start + labelLength < 0 || start > line.Length)
            {
                return(null);
            }

            // LengthIndexedLine idea courtesy FObermaier
            NetTopologySuite.LinearReferencing.LengthIndexedLine lil;

            // optimize for detailed lines (eg labelling rivers at continental level)
            // ratio and NumPoints based on instinct.... feel free to revise
            var mid = start + labelLength / 2.0;

            if (labelLength / line.Length < 0.5 && line.NumPoints > 200 && mid >= 0 && mid < line.Length)
            {
                lil = new NetTopologySuite.LinearReferencing.LengthIndexedLine(line);
                var midPt = lil.ExtractPoint(mid);
                // extract slightly more than label length to ensure offsetCurve follows line geometry
                var halfLen = labelLength * 0.6;
                // ensure non-negative indexes constrained to line length (due to special LengthIndexLine functionality)
                line = (LineString)lil.ExtractLine(Math.Max(0, mid - halfLen), Math.Min(mid + halfLen, line.Length));
                // reset start
                lil   = new NetTopologySuite.LinearReferencing.LengthIndexedLine(line);
                mid   = lil.IndexOf(midPt);
                start = mid - labelLength / 2.0;
            }

            // basic extend
            var end = start + labelLength;

            if (start < 0 || end > line.Length)
            {
                line = ExtendLine(line,
                                  start <0 ? -1 * start : 0,
                                         end> line.Length ? end - line.Length : 0);
                start = 0;
                end   = start + labelLength;
            }

            lil = new NetTopologySuite.LinearReferencing.LengthIndexedLine(line);
            // reverse
            var startPt = lil.ExtractPoint(start);
            var endPt   = lil.ExtractPoint(end);

            if (LineNeedsReversing(startPt, endPt, false, map))
            {
                start = end;
                end   = start - labelLength;
            }
            line = (ILineString)lil.ExtractLine(start, end);

            // Build offset curve
            ILineString offsetCurve;
            var         bufferParameters =
                new NetTopologySuite.Operation.Buffer.BufferParameters(4,
                                                                       GeoAPI.Operation.Buffer.EndCapStyle.Flat);

            // determine offset curve that will run through the vertical centre of the text
            if (style.VerticalAlignment != LabelStyle.VerticalAlignmentEnum.Middle)
            {
                var ocb = new NetTopologySuite.Operation.Buffer.OffsetCurveBuilder(factory.PrecisionModel,
                                                                                   bufferParameters);

                // Left side positive
                var offsetCurvePoints = ocb.GetOffsetCurve(line.Coordinates,
                                                           ((int)style.VerticalAlignment - 1) * 0.5 * labelHeight - offsetY);
                offsetCurve = factory.CreateLineString(offsetCurvePoints);
            }
            else
            {
                offsetCurve = line;
            }

            // basic extend
            var ratio = labelLength / offsetCurve.Length;

            if (ratio > 1.01)
            {
                var diff = labelLength - offsetCurve.Length;
                offsetCurve = ExtendLine(offsetCurve, diff / 2d, diff / 2d);
            }

            // enclosing polygon in world coords
            var affectedArea = (IPolygon)offsetCurve.Buffer(0.5d * labelHeight, bufferParameters);

            // fast, basic check (technically should use polygons for rotated views)
            if (!map.Envelope.Contains(affectedArea.EnvelopeInternal))
            {
                return(null);
            }

            // using labelBox to pass text height to WarpedPath
            return(new PathLabel(text, LineStringToPath(offsetCurve, map), 0, priority,
                                 new LabelBox(0, 0, textMeasure.Width, textMeasure.Height), style)
            {
                AffectedArea = affectedArea
            });
        }
Beispiel #9
0
        private void RenderLineLabel(TextSymbolizer textSymbolizer, Feature feature)
        {
            //TODO labels could be not strings
            var str = feature.Attributes.Exists(textSymbolizer.LabelAttribute) ? feature.Attributes[textSymbolizer.LabelAttribute] as string : null;

            if (string.IsNullOrWhiteSpace(str))
            {
                return;
            }

            var emSize = Graphics.DpiY * textSymbolizer.FontSize / 72;

            //ref http://msdn.microsoft.com/en-us/library/xwf9s90b(v=vs.110).aspx
            var font   = FontCache[textSymbolizer];
            var ascent = emSize * font.FontFamily.GetCellAscent(FontStyle.Bold) / font.FontFamily.GetEmHeight(FontStyle.Bold);

            Graphics.SmoothingMode = SmoothingMode.HighQuality;

            var   size    = Graphics.MeasureString(str, font);
            float spacing = textSymbolizer.Spacing;

            var coords        = ProjectToCoordinate(feature.Geometry.Coordinates);
            var coordsAsLine  = new LineString(coords);
            var lengthIndexed = new NetTopologySuite.LinearReferencing.LengthIndexedLine(coordsAsLine);

            var labelCount = (int)((coordsAsLine.Length - spacing) / (size.Width + spacing));

            if (labelCount < 1 || textSymbolizer.Spacing == 0)
            {
                labelCount = 1;
            }

            //work out spacing based on the amount of labels we'll be putting on
            spacing = ((float)coordsAsLine.Length / labelCount) - size.Width;

            for (var i = 0; i < labelCount; i++)
            {
                var labelCenterLength = (spacing + size.Width) * (0.5f + i);
                var subLine           = lengthIndexed.ExtractLine(labelCenterLength - (size.Width / 2), labelCenterLength + (size.Width / 2));
                if (subLine.Coordinates.Length < 2)
                {
                    continue;
                }

                var firstCoord             = subLine.Coordinates[0];
                var lastCoord              = subLine.Coordinates[subLine.Coordinates.Length - 1];
                var middleOfLabelLinePoint = lengthIndexed.ExtractPoint(labelCenterLength);


                var midPoint = new PointF((float)(firstCoord.X + lastCoord.X + middleOfLabelLinePoint.X + middleOfLabelLinePoint.X) * 0.25f, (float)(firstCoord.Y + lastCoord.Y + middleOfLabelLinePoint.Y + middleOfLabelLinePoint.Y) * 0.25f);

                var angle = (float)(Math.Atan2(lastCoord.Y - firstCoord.Y, lastCoord.X - firstCoord.X) * 180 / Math.PI);
                //Keep the text up the right way
                while (angle + Config.Angle > 90)
                {
                    angle -= 180;
                }
                while (angle + Config.Angle < -90)
                {
                    angle += 180;
                }

                TryRenderText(textSymbolizer, feature, emSize, str, midPoint, SizeF.Empty, new SizeF(size.Width, ascent), angle);
            }
        }
Beispiel #10
0
        /// <summary>
        /// Computes a snapped coordinate.  If the mouse is near the selected feature, the output
        /// location of the mouse will be the coordinates on the feature rather than the actual
        /// mouse coords.
        /// </summary>
        /// <param name="mouseRect">The event args.</param>
        /// <param name="feat">set if a coordinate is found</param>
        /// <param name="layer">the feature's layer</param>
        /// <param name="snappedCoord">the coordinate of the mouse</param>
        /// <returns>true if snap found</returns>
        protected bool ComputeSnappedLocation_ForSelectedFeature(Rectangle mouseRect, ref IFeature feat, IFeatureLayer layer, ref Coordinate snappedCoord)
        {
            SnappingType      = string.Empty;
            SnappedCoordIndex = 0;

            if (!DoSnapping)
            {
                return(false);
            }
            if (mouseRect == null || feat == null || layer == null || snappedCoord == null)
            {
                return(false);
            }

            Extent pix = Map.PixelToProj(mouseRect);

            if (pix == null)
            {
                return(false);
            }

            Envelope mouseEnv = pix.ToEnvelope();

            NetTopologySuite.Geometries.Point mouse_onEarth = new NetTopologySuite.Geometries.Point(snappedCoord);
            IGeometry featGeom = feat.Geometry;

            // If the feature is partially or totaly visible in the view.
            if (Map.ViewExtents.Intersects(featGeom.EnvelopeInternal))
            {
                bool doCoord_Snap;

                // System.Console.WriteLine(feat.Fid);
                int coordCounter = 0;
                foreach (Coordinate c in feat.Geometry.Coordinates)
                {
                    doCoord_Snap = true;

                    if (layer.SnapVertices)
                    {
                        if (coordCounter == 0 && !layer.SnapStartPoint)
                        {
                            doCoord_Snap = false;
                        }
                        if (coordCounter == (feat.Geometry.Coordinates.Length - 1) && !layer.SnapEndPoint)
                        {
                            doCoord_Snap = false;
                        }

                        if (doCoord_Snap)
                        {
                            // If the mouse envelope contains the current coordinate, we found a snap location.
                            if (mouseEnv.Contains(c))
                            {
                                snappedCoord      = c;
                                SnappedCoordIndex = coordCounter;
                                SnappedFeature    = feat;
                                SnappingType      = SnappingTypeVertex;
                                return(true);
                            }
                        }
                    }

                    if (coordCounter > 0 && layer.SnapEdges && feat.FeatureType != FeatureType.Point && feat.FeatureType != FeatureType.MultiPoint)
                    {
                        double edge_Distance = 0;
                        if (layer.DataSet.CoordinateType.Equals(CoordinateType.Z))
                        {
                            edge_Distance = feat.Geometry.Coordinates[coordCounter - 1].Distance3D(c);
                        }
                        else
                        {
                            edge_Distance = feat.Geometry.Coordinates[coordCounter - 1].Distance(c);
                        }

                        if (edge_Distance > 0)
                        {
                            List <Coordinate> edgeCoords = new List <Coordinate>();
                            edgeCoords.Add(feat.Geometry.Coordinates[coordCounter - 1]);
                            edgeCoords.Add(c);

                            LineString edge = new LineString(edgeCoords.ToArray());

                            if (mouse_onEarth.Distance(edge) <= (mouseEnv.Width / 2))
                            {
                                NetTopologySuite.LinearReferencing.LengthIndexedLine indexedEedge = new NetTopologySuite.LinearReferencing.LengthIndexedLine(edge);
                                double proj_Index = indexedEedge.Project(mouse_onEarth.Coordinate);

                                if (proj_Index > (mouseEnv.Width / 2) && proj_Index < (edge.Length - (mouseEnv.Width / 2)))
                                {
                                    snappedCoord       = indexedEedge.ExtractPoint(proj_Index);
                                    SnappedCoordKeeped = snappedCoord; /* c.Clone() as Coordinate;*/
                                    SnappedCoordIndex  = coordCounter;
                                    SnappedFeature     = feat;
                                    SnappingType       = SnappingTypeEdge;
                                    return(true);
                                }
                            }
                        }
                    }

                    coordCounter++;
                }
            }

            SnappedFeature = null;
            return(false);
        }