private static double calculateSegmentsPointsDistance(List <MonotoneChain> chains,
                                                              List <ICoordinate> points,
                                                              double minDistance,
                                                              double threshold)
        {
            foreach (MonotoneChain chain in chains)
            {
                foreach (Segment s in chain.Segments)
                {
                    foreach (ICoordinate p in points)
                    {
                        if (p.X > Math.Max(s.V1.X, s.V2.X) + minDistance)
                        {
                            break;
                        }
                        double d = PlanimetryAlgorithms.DistanceToSegment(p, s);
                        if (d < minDistance)
                        {
                            minDistance = d;
                        }
                        if (minDistance <= threshold)
                        {
                            return(minDistance);
                        }
                    }
                }
            }

            return(minDistance);
        }
        /// <summary>
        /// Builds polygons for the z-value ranges.
        /// </summary>
        /// <param name="triangles">An object that enumerates triangles defining surface. All triangle coordinates should be instances of the MapAround.Geometry.Coordinate3D.</param>
        /// <param name="zLevels">A descending array of z-values that define ranges</param>
        /// <returns>An array containing level range polygons</returns>
        public LevelRangePolygon[] BuildPolygonsForLevelRanges(IEnumerable <Triangle> triangles, double[] zLevels)
        {
            if (triangles == null)
            {
                throw new ArgumentNullException("triangles");
            }

            for (int i = 0; i < zLevels.Length - 1; i++)
            {
                if (zLevels[i] <= zLevels[i + 1])
                {
                    throw new ArgumentException("Z-levels aren't descending and/or distinct", "zLevels");
                }
            }

            Polyline[] isolines = buildIsolinesInternal(triangles, zLevels);

            IList <ICoordinate> coonvexHull;

            List <LinePath> paths = getPathsForPolygonBuilding(triangles, isolines, out coonvexHull);

            IList <Polygon> polygons;
            IList <Segment> dangles;
            IList <Segment> cuts;

            PolygonBuilder.BuildPolygons(paths, out polygons, out dangles, out cuts);

            List <Triangle> tempTriangles = triangles.ToList();

            LevelRangePolygon[] result =
                assignLevelsToPolygons(polygons, tempTriangles, zLevels, PlanimetryAlgorithms.GetPointsBoundingRectangle(coonvexHull));

            return(result);
        }
Beispiel #3
0
        private ICoordinate PrepareForSelect(Point position)
        {
            //BoundingRectangle mapCoordsViewBox = _map.MapViewBoxFromPresentationViewBox(_viewBox);

            double x = _viewBox.Width / ActualWidth * position.X + _viewBox.MinX;
            double y = _viewBox.MaxY - _viewBox.Height / ActualHeight * position.Y;

            // Caculate the error of selecting the point and line objects
            _map.SelectionPointRadius = _selectionMargin * _viewBox.Width / ActualWidth;

            ICoordinate result = PlanimetryEnvironment.NewCoordinate(x, y);

            if (_map.OnTheFlyTransform != null)
            {
                ICoordinate    delta            = PlanimetryEnvironment.NewCoordinate(result.X + _map.SelectionPointRadius, result.Y);
                IMathTransform inverseTransform = _map.OnTheFlyTransform.Inverse();

                delta = PlanimetryEnvironment.NewCoordinate(inverseTransform.Transform(delta.Values()));

                _map.SelectionPointRadius =
                    PlanimetryAlgorithms.Distance(PlanimetryEnvironment.NewCoordinate(inverseTransform.Transform(result.Values())), delta);
            }

            return(result);
        }
Beispiel #4
0
        private List <ICoordinate> getStrokePoints(IList <ICoordinate> points,
                                                   double startLength,
                                                   double strokeLength,
                                                   ref int segmentIndex,
                                                   ref double traversedLength)
        {
            List <ICoordinate> result = new List <ICoordinate>();

            double endLength     = startLength + strokeLength;
            bool   strokeStarted = false;

            for (int i = segmentIndex; i < points.Count - 1; i++)
            {
                double currentSegmentLength = PlanimetryAlgorithms.Distance(points[i], points[i + 1]);

                if (!strokeStarted)
                {
                    if (traversedLength + currentSegmentLength < startLength)
                    {
                        traversedLength += currentSegmentLength;
                        continue;
                    }
                    else
                    {
                        double      remaindeLength = startLength - traversedLength;
                        double      f = remaindeLength / (currentSegmentLength - remaindeLength);
                        ICoordinate p = PlanimetryEnvironment.NewCoordinate(
                            (points[i].X + f * points[i + 1].X) / (1 + f),
                            (points[i].Y + f * points[i + 1].Y) / (1 + f));
                        result.Add(p);
                        strokeStarted = true;
                    }
                }
                if (strokeStarted)
                {
                    if (traversedLength + currentSegmentLength <= endLength)
                    {
                        traversedLength += currentSegmentLength;
                        result.Add(points[i + 1]);
                        continue;
                    }
                    else
                    {
                        double      remainderLength = endLength - traversedLength;
                        double      f = remainderLength / (currentSegmentLength - remainderLength);
                        ICoordinate p = PlanimetryEnvironment.NewCoordinate(
                            (points[i].X + f * points[i + 1].X) / (1 + f),
                            (points[i].Y + f * points[i + 1].Y) / (1 + f));
                        result.Add(p);
                        segmentIndex = i;
                        return(result);
                    }
                }
            }

            segmentIndex = points.Count - 1;
            return(result);
        }
        private int[] calculateOptimalAffineTransformPoints()
        {
            int[]  result  = new int[3];
            double minNorm = double.MaxValue;

            for (int i1 = 0; i1 < _sourceControlPoints.Length - 2; i1++)
            {
                for (int i2 = i1 + 1; i2 < _sourceControlPoints.Length - 1; i2++)
                {
                    for (int i3 = i2 + 1; i3 < _sourceControlPoints.Length; i3++)
                    {
                        ICoordinate p01 = _sourceControlPoints[i1];
                        ICoordinate p02 = _sourceControlPoints[i2];
                        ICoordinate p03 = _sourceControlPoints[i3];

                        ICoordinate p11 = _destinationControlPoints[i1];
                        ICoordinate p12 = _destinationControlPoints[i2];
                        ICoordinate p13 = _destinationControlPoints[i3];

                        Matrix m = getAffineTransformMatrix(p01, p02, p03, p11, p12, p13);

                        if (m != null)
                        {
                            ICoordinate[] tempPoints = new ICoordinate[_sourceControlPoints.Length];
                            for (int i = 0; i < _sourceControlPoints.Length; i++)
                            {
                                tempPoints[i] = (ICoordinate)_sourceControlPoints[i].Clone();
                            }

                            Affine affineTransform = new Affine(m);

                            for (int i = 0; i < tempPoints.Length; i++)
                            {
                                tempPoints[i] =
                                    PlanimetryEnvironment.NewCoordinate(
                                        affineTransform.Transform(tempPoints[i].Values()));
                            }

                            double currentNorm = 0;
                            for (int i = 0; i < tempPoints.Length; i++)
                            {
                                currentNorm += PlanimetryAlgorithms.Distance(_destinationControlPoints[i], PlanimetryEnvironment.NewCoordinate(tempPoints[i].X, tempPoints[i].Y));
                            }

                            if (currentNorm < minNorm)
                            {
                                minNorm   = currentNorm;
                                result[0] = i1;
                                result[1] = i2;
                                result[2] = i3;
                            }
                        }
                    }
                }
            }

            return(result);
        }
        /// <summary>
        /// Derived from <see cref="System.Object"/>.
        /// </summary>
        /// <param name="o">The System.Object to compare with the current MapAround.Geometry.PointD</param>
        public override bool Equals(object o)
        {
            if (o is ICoordinate)
            {
                return(PlanimetryAlgorithms.DistanceTolerant(this, (ICoordinate)o));
            }

            return(false);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public override double[] Transform(double[] point)
        {
            // check whether we were in a knot interpolation
            for (int k = 0; k < _sourceControlPoints.Length; k++)
            {
                if (_sourceControlPoints[k].X == point[0] &&
                    _sourceControlPoints[k].Y == point[1])
                {
                    // hit
                    return(_destinationControlPoints[k].Values());
                }
            }

            ICoordinate source = PlanimetryEnvironment.NewCoordinate(point);
            ICoordinate result =
                PlanimetryEnvironment.NewCoordinate(_optimalAffineTransform.Transform(point));

            double[] distances = new double[_sourceControlPoints.Length];
            double[] w         = new double[_sourceControlPoints.Length];

            // calculation of distances to nodes
            double maxDistance = 0;

            for (int t = 0; t < _sourceControlPoints.Length; t++)
            {
                distances[t] = PlanimetryAlgorithms.Distance(_sourceControlPoints[t], source);
                if (maxDistance < distances[t])
                {
                    maxDistance = distances[t];
                }
            }

            // calculation of the weights of the denominators of nodes
            double sum = 0;

            for (int k = 0; k < _sourceControlPoints.Length; k++)
            {
                double temp = (maxDistance - distances[k]) / (maxDistance * distances[k]);
                sum += Math.Pow(temp, 2);
            }

            // calculation of the weights of nodes
            for (int k = 0; k < _sourceControlPoints.Length; k++)
            {
                double temp = (maxDistance - distances[k]) / (maxDistance * distances[k]);
                w[k] = Math.Pow(temp, 2) / sum;
            }

            for (int k = 0; k < _sourceControlPoints.Length; k++)
            {
                result.X += w[k] * _controlPointsShifts[k].X;
                result.Y += w[k] * _controlPointsShifts[k].Y;
            }

            return(result.Values());
        }
        private List <LinePath> getPathsForPolygonBuilding(IEnumerable <Coordinate3D> surfacePoints, IEnumerable <Polyline> isolines, out IList <ICoordinate> convexHull)
        {
            List <ICoordinate> coords = new List <ICoordinate>();

            foreach (Coordinate3D c in surfacePoints)
            {
                coords.Add(c);
            }

            convexHull = PlanimetryAlgorithms.GetConvexHull(coords);
            Polyline bounds = new Polyline(convexHull);

            return(getPathsForPolygonBuilding(isolines, convexHull));
        }
        private static int[] calculateOptimalAffineTransformPoints(Point[] sourceNodes, ICoordinate[] destNodes)
        {
            int[]  result  = new int[3];
            double minNorm = double.MaxValue;

            for (int i1 = 0; i1 < sourceNodes.Length - 2; i1++)
            {
                for (int i2 = i1 + 1; i2 < sourceNodes.Length - 1; i2++)
                {
                    for (int i3 = i2 + 1; i3 < sourceNodes.Length; i3++)
                    {
                        PointF p01 = new PointF(sourceNodes[i1].X, sourceNodes[i1].Y);
                        PointF p02 = new PointF(sourceNodes[i2].X, sourceNodes[i2].Y);
                        PointF p03 = new PointF(sourceNodes[i3].X, sourceNodes[i3].Y);

                        PointF p11 = new PointF((float)destNodes[i1].X, (float)destNodes[i1].Y);
                        PointF p12 = new PointF((float)destNodes[i2].X, (float)destNodes[i2].Y);
                        PointF p13 = new PointF((float)destNodes[i3].X, (float)destNodes[i3].Y);

                        Matrix m = getAffineTransformMatrix(p01, p02, p03, p11, p12, p13);
                        if (m != null)
                        {
                            PointF[] tempPoints = new PointF[sourceNodes.Length];
                            for (int i = 0; i < sourceNodes.Length; i++)
                            {
                                tempPoints[i] = new PointF(sourceNodes[i].X, sourceNodes[i].Y);
                            }
                            m.TransformPoints(tempPoints);

                            double currentNorm = 0;
                            for (int i = 0; i < tempPoints.Length; i++)
                            {
                                currentNorm += PlanimetryAlgorithms.Distance(destNodes[i], PlanimetryEnvironment.NewCoordinate(tempPoints[i].X, tempPoints[i].Y));
                            }

                            if (currentNorm < minNorm)
                            {
                                minNorm   = currentNorm;
                                result[0] = i1;
                                result[1] = i2;
                                result[2] = i3;
                            }
                        }
                    }
                }
            }

            return(result);
        }
        private List <LinePath> getPathsForPolygonBuilding(IEnumerable <Triangle> triangles, IEnumerable <Polyline> isolines, out IList <ICoordinate> convexHull)
        {
            List <ICoordinate> coords = new List <ICoordinate>();

            foreach (Triangle t in triangles)
            {
                coords.Add(t.Cell1.DataPoint);
                coords.Add(t.Cell2.DataPoint);
                coords.Add(t.Cell3.DataPoint);
            }

            convexHull = PlanimetryAlgorithms.GetConvexHull(coords);
            Polyline bounds = new Polyline(convexHull);

            return(getPathsForPolygonBuilding(isolines, convexHull));
        }
        /// <summary>
        /// Calculates luminosity of the triangle.
        /// </summary>
        /// <param name="triangle">A triangle</param>
        /// <param name="lightX">An X component of the light vector</param>
        /// <param name="lightY">A Y component of the light vector</param>
        /// <param name="lightZ">A Z component of the light vector</param>
        /// <param name="zFactor">A value at which to multiply z-values for luminosity calculation</param>
        /// <returns>A luminosity value ranging from zero to one</returns>
        public static double GetLuminosity(Triangle triangle, double lightX, double lightY, double lightZ, double zFactor)
        {
            if (!(triangle.Cell1.DataPoint is Coordinate3D) ||
                !(triangle.Cell2.DataPoint is Coordinate3D) ||
                !(triangle.Cell3.DataPoint is Coordinate3D))
            {
                throw new ArgumentException("All coordinates should be instances of the MapAround.Geometry.Coordinate3D", "triangle");
            }

            Coordinate3D p1 = (Coordinate3D)triangle.Cell1.DataPoint.Clone();
            Coordinate3D p2 = (Coordinate3D)triangle.Cell2.DataPoint.Clone();
            Coordinate3D p3 = (Coordinate3D)triangle.Cell3.DataPoint.Clone();

            p1.Z = p1.Z * zFactor;
            p2.Z = p2.Z * zFactor;
            p3.Z = p3.Z * zFactor;

            if (PlanimetryAlgorithms.OrientationIndex(p1, p2, p3) < 0)
            {
                Coordinate3D temp = p1;
                p1 = p2;
                p2 = temp;
            }

            double A = p1.Y * (p2.Z - p3.Z) + p2.Y * (p3.Z - p1.Z) + p3.Y * (p1.Z - p2.Z);
            double B = p1.Z * (p2.X - p3.X) + p2.Z * (p3.X - p1.X) + p3.Z * (p1.X - p2.X);
            double C = p1.X * (p2.Y - p3.Y) + p2.X * (p3.Y - p1.Y) + p3.X * (p1.Y - p2.Y);
            double D = -(p1.X * (p2.Y * p3.Z - p3.Y * p2.Z) + p2.X * (p3.Y * p1.Z - p1.Y * p3.Z) + p3.X * (p1.Y * p2.Z - p2.Y * p1.Z));

            double sinePhi =
                Math.Abs(A * lightX + B * lightY + C * lightZ) /
                Math.Sqrt(A * A + B * B + C * C) /
                Math.Sqrt(lightX * lightX + lightY * lightY + lightZ * lightZ);

            Coordinate3D lightPoint = new Coordinate3D();

            lightPoint.X = p1.X + lightX;
            lightPoint.Y = p1.Y + lightY;
            lightPoint.Z = p1.Z + lightZ;

            if (A * lightPoint.X + B * lightPoint.Y + C * lightPoint.Z + D > 0)
            {
                return(0);
            }

            return(sinePhi);
        }
        private double getVertexWeight(Polyline polyline, int pathIndex, int pointIndex)
        {
            ICoordinate p1 = polyline.Paths[pathIndex].Vertices[pointIndex - 1];
            ICoordinate p2 = polyline.Paths[pathIndex].Vertices[pointIndex];
            ICoordinate p3 = polyline.Paths[pathIndex].Vertices[pointIndex + 1];

            switch (_vertexWeighting)
            {
            case VertexWeightingType.NormalizedLinear:
            case VertexWeightingType.AngleCube:
                // length of the segments
                double s1 = PlanimetryAlgorithms.Distance(p1, p2);
                double s2 = PlanimetryAlgorithms.Distance(p2, p3);

                double s1s2 = s1 * s2;

                //   angle of rotation
                double angle = Math.PI - Math.Abs(Math.Acos(((p1.X - p2.X) * (p3.X - p2.X) + (p1.Y - p2.Y) * (p3.Y - p2.Y)) / s1s2));

                if (_vertexWeighting == VertexWeightingType.SquareDifference)
                {
                    return(s1s2 * angle / (s1 + s2));
                }
                else
                {
                    return(s1s2 * angle * angle * angle);
                }

            case VertexWeightingType.SquareDifference:
                return(Math.Abs((p2.X - p1.X) * (p3.Y - p1.Y) - (p3.X - p1.X) * (p2.Y - p1.Y)));

            case VertexWeightingType.Custom:
                if (SDMinVertexWeightNeeded != null)
                {
                    SDMinVertexWeightNeededEventArgs args =
                        new SDMinVertexWeightNeededEventArgs(p1, p2, p3, pathIndex, pointIndex);
                    SDMinVertexWeightNeeded(this, args);
                    return(args.Weight);
                }
                break;
            }

            return(0);
        }
        /// <summary>
        /// Determines whether this chain crosses with other.
        /// </summary>
        /// <param name="chain">Chain</param>
        /// <returns>true, if this chain crosses with the specified chain, false otherwise</returns>
        public bool CrossesWith(MonotoneChain chain)
        {
            if (BoundsIntersect(chain))
            {
                Segment     stub       = new Segment();
                ICoordinate crossPoint = null;

                foreach (Segment s1 in this._segments)
                {
                    foreach (Segment s2 in chain._segments)
                    {
                        Dimension crossKind = PlanimetryAlgorithms.RobustSegmentsIntersection(s1, s2, out crossPoint, out stub);
                        if (crossKind == Dimension.Zero)
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Beispiel #14
0
        private void addInteriorJoin(IList <ICoordinate> vertexList, double x1, double y1, double x2, double y2, double x3, double y3)
        {
            double angle1   = getSegmentAngle(x1, y1, x2, y2) + _halfPI;
            double angle2   = getSegmentAngle(x2, y2, x3, y3) + _halfPI;
            double distance = _width / 2;

            Segment     s1           = new Segment(pointOnCircle(x1, y1, distance, angle1), pointOnCircle(x2, y2, distance, angle1));
            Segment     s2           = new Segment(pointOnCircle(x2, y2, distance, angle2), pointOnCircle(x3, y3, distance, angle2));
            ICoordinate intersection = null;

            if (PlanimetryAlgorithms.SegmentsIntersection(s1, s2, out intersection, out s1) == Dimension.Zero)
            {
                vertexList.Add(intersection);
                return;
            }

            angle1 -= Math.PI;
            angle2 -= Math.PI;

            vertexList.Add(pointOnCircle(x2, y2, distance, angle1));
            vertexList.Add(PlanimetryEnvironment.NewCoordinate(x2, y2));
            vertexList.Add(pointOnCircle(x2, y2, distance, angle2));
        }
Beispiel #15
0
        private FortuneEvent getCircleEvent(FortuneArc arc1,
                                            FortuneArc arc2,
                                            FortuneArc arc3,
                                            double y)
        {
            ICoordinate a = arc1.Site.Cell.DataPoint;
            ICoordinate b = arc2.Site.Cell.DataPoint;
            ICoordinate c = arc3.Site.Cell.DataPoint;

            //bc should turn to the right with respect to ab
            if ((b.X - a.X) * (c.Y - a.Y) - (c.X - a.X) * (b.Y - a.Y) > 0)
            {
                return(null);
            }

            ICoordinate point = getCircleCenter(a, b, c);

            if (point != null)
            {
                FortuneCircleEvent newEvent = new FortuneCircleEvent();
                newEvent.CircleCenter = point;

                double distance = PlanimetryAlgorithms.Distance(point, a);
                point = PlanimetryEnvironment.NewCoordinate(point.X, point.Y - distance);

                newEvent.Point = point;
                newEvent.Arc   = arc2;

                if (_buildTriangles)
                {
                    newEvent.Triangle = new Triangle(arc1.Site.Cell, arc2.Site.Cell, arc3.Site.Cell);
                }

                return(newEvent);
            }
            return(null);
        }
Beispiel #16
0
        /// <summary>
        /// Computes a convex hull of the specified points.
        /// </summary>
        /// <param name="points">Enumerator of coordinates for which convex hull should be computed</param>
        /// <returns>A list containing a sequence of the convex hull points</returns>
        public static IList <GeoPoint> GetConvexHull(IEnumerable <GeoPoint> points)
        {
            GeographyCollection geographyCollection = new GeographyCollection();

            foreach (GeoPoint p in points)
            {
                geographyCollection.Add(p);
            }

            GnomonicProjection projection         = GeometrySpreader.GetProjection(geographyCollection);
            GeometryCollection geometryCollection = GeometrySpreader.GetGeometries(geographyCollection, projection);
            List <ICoordinate> list = new List <ICoordinate>();

            foreach (IGeometry g in geometryCollection)
            {
                list.Add(((PointD)g).Coordinate);
            }

            IList <ICoordinate> planarResult = PlanimetryAlgorithms.GetConvexHull(list);

            geometryCollection.Clear();
            foreach (ICoordinate p in planarResult)
            {
                geometryCollection.Add(new PointD(p));
            }

            geographyCollection = GeometrySpreader.GetGeographies(geometryCollection, projection);
            List <GeoPoint> result = new List <GeoPoint>();

            foreach (GeoPoint p in geographyCollection)
            {
                result.Add(p);
            }

            return(result);
        }
        /// <summary>
        /// Computes the 2D intersections of two chains.
        /// </summary>
        /// <param name="chain">Monotone chain</param>
        /// <returns>A list containing segments that represent 2D intersections of chain</returns>
        public List <Segment> GetCrossSegments(MonotoneChain chain)
        {
            List <Segment> result = new List <Segment>();

            if (BoundsIntersect(chain))
            {
                Segment     crossSegment = new Segment();
                ICoordinate stub         = null;

                foreach (Segment s1 in this._segments)
                {
                    foreach (Segment s2 in chain._segments)
                    {
                        Dimension crossKind = PlanimetryAlgorithms.RobustSegmentsIntersection(s1, s2, out stub, out crossSegment);
                        if (crossKind == Dimension.One)
                        {
                            result.Add(crossSegment);
                        }
                    }
                }
            }

            return(result);
        }
Beispiel #18
0
        /// <summary>
        /// Request GetFeatureInfo
        /// </summary>
        protected override void GetFeatureInfo(NameValueCollection requestParams, Stream responseOutputStream, ref string responseContentType)
        {
            #region Processing Request GetFeatureInfo

            int featureCount = 1;
            if (requestParams["FEATURE_COUNT"] != null)
            {
                int.TryParse(requestParams["FEATURE_COUNT"], out featureCount);
            }

            int x = 0, y = 0;

            if (requestParams["X"] == null)
            {
                WmsException(WmsExceptionCode.NotApplicable,
                             "Required parameter X undefined.",
                             responseOutputStream,
                             ref responseContentType);
                return;
            }
            else if (!int.TryParse(requestParams["X"], out x))
            {
                WmsException(WmsExceptionCode.NotApplicable,
                             "Parameter X has wrong value.",
                             responseOutputStream,
                             ref responseContentType);
                return;
            }


            if (requestParams["Y"] == null)
            {
                WmsException(WmsExceptionCode.NotApplicable,
                             "Required parameter Y undefined.",
                             responseOutputStream,
                             ref responseContentType);
                return;
            }
            else if (!int.TryParse(requestParams["Y"], out y))
            {
                WmsException(WmsExceptionCode.NotApplicable,
                             "Parameter Y has wrong value.",
                             responseOutputStream,
                             ref responseContentType);
                return;
            }

            int width  = 0;
            int height = 0;
            if (!int.TryParse(requestParams["WIDTH"], out width))
            {
                WmsException(WmsExceptionCode.InvalidDimensionValue,
                             "Parameter WIDTH has wrong value.",
                             responseOutputStream,
                             ref responseContentType);
                return;
            }
            else if (_description.MaxWidth > 0 && width > _description.MaxWidth)
            {
                WmsException(WmsExceptionCode.OperationNotSupported,
                             "Parameter WIDTH is too large.",
                             responseOutputStream,
                             ref responseContentType);
                return;
            }
            if (!int.TryParse(requestParams["HEIGHT"], out height))
            {
                WmsException(WmsExceptionCode.InvalidDimensionValue,
                             "Parameter HEIGHT has wrong value.",
                             responseOutputStream,
                             ref responseContentType);
                return;
            }
            else if (_description.MaxHeight > 0 && height > _description.MaxHeight)
            {
                WmsException(WmsExceptionCode.OperationNotSupported,
                             "Parameter HEIGHT is too large.",
                             responseOutputStream,
                             ref responseContentType);
                return;
            }

            BoundingRectangle bbox = ParseBbox(requestParams["bbox"]);
            if (bbox == null)
            {
                WmsException(WmsExceptionCode.NotApplicable,
                             "Parameter BBOX has wrong value.",
                             responseOutputStream,
                             ref responseContentType);
                return;
            }

            string mimeTypeNeeded = "text/html";
            if (requestParams["INFO_FORMAT"] != null)
            {
                mimeTypeNeeded = requestParams["INFO_FORMAT"];
            }

            List <FeatureLayer> queryableLayers = new List <FeatureLayer>();
            if (!string.IsNullOrEmpty(requestParams["LAYERS"]))
            {
                string[] layers = requestParams["LAYERS"].Split(new[] { ',' });
                foreach (string layer in layers)
                {
                    LayerBase l = null;
                    int       i;
                    for (i = 0; i < _map.Layers.Count; i++)
                    {
                        if (string.Equals(_map.Layers[i].Alias, layer,
                                          StringComparison.InvariantCultureIgnoreCase))
                        {
                            l = _map.Layers[i];
                        }
                    }


                    if (l == null)
                    {
                        WmsException(WmsExceptionCode.LayerNotDefined,
                                     "Layer \"" + layer + "\" not found.",
                                     responseOutputStream,
                                     ref responseContentType);
                        return;
                    }
                    else if (!(l is FeatureLayer) || !((FeatureLayer)l).FeaturesSelectable)
                    {
                        WmsException(WmsExceptionCode.LayerNotQueryable,
                                     "Layer \"" + layer + "\" is not queryable.",
                                     responseOutputStream,
                                     ref responseContentType);
                        return;
                    }
                    else
                    {
                        queryableLayers.Add((FeatureLayer)l);
                    }
                }

                queryableLayers.Sort(
                    (FeatureLayer l1, FeatureLayer l2) =>
                    _map.Layers.IndexOf(l1) > _map.Layers.IndexOf(l2) ? -1 : 1);

                List <Feature> selectedFeatures = new List <Feature>();

                if (queryableLayers.Count > 0)
                {
                    lock (_syncRoot)
                    {
                        // calculate the error of selection of point and line objects
                        _map.SelectionPointRadius =
                            _selectionMargin * bbox.Width / width;

                        double resultX = bbox.Width / width * x + bbox.MinX;
                        double resultY = bbox.MaxY - bbox.Height / height * y;

                        ICoordinate point = PlanimetryEnvironment.NewCoordinate(resultX, resultY);

                        ICoordinate tempPoint = PlanimetryEnvironment.NewCoordinate(x, y);
                        if (_map.OnTheFlyTransform != null)
                        {
                            ICoordinate delta =
                                PlanimetryEnvironment.NewCoordinate(tempPoint.X + _map.SelectionPointRadius,
                                                                    tempPoint.Y);
                            IMathTransform inverseTransform = _map.OnTheFlyTransform.Inverse();

                            delta =
                                PlanimetryEnvironment.NewCoordinate(inverseTransform.Transform(delta.Values()));

                            _map.SelectionPointRadius =
                                PlanimetryAlgorithms.Distance(
                                    PlanimetryEnvironment.NewCoordinate(
                                        inverseTransform.Transform(tempPoint.Values())), delta);
                        }
                        if (queryableLayers[0].Map.OnTheFlyTransform != null)
                        {
                            IMathTransform inverseTransform = queryableLayers[0].Map.OnTheFlyTransform.Inverse();
                            point =
                                PlanimetryEnvironment.NewCoordinate(inverseTransform.Transform(point.Values()));
                        }

                        foreach (LayerBase l in queryableLayers)
                        {
                            FeatureLayer fl = l as FeatureLayer;
                            if (fl != null)
                            {
                                Feature feature = null;
                                fl.SelectObject(point, out feature);
                                if (feature != null)
                                {
                                    selectedFeatures.Add(feature);
                                }

                                if (selectedFeatures.Count == featureCount)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }


                WmsFeaturesInfoNeededEventArgs args = new WmsFeaturesInfoNeededEventArgs(selectedFeatures,
                                                                                         mimeTypeNeeded,
                                                                                         responseOutputStream,
                                                                                         responseContentType);
                OnFeaturesInfoNeeded(args);
                responseContentType = args.ResponseContentType;

                return;
            }

            StringBuilder sb = new StringBuilder();
            sb.Append("none");

            byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString().ToCharArray());
            responseOutputStream.Write(bytes, 0, bytes.Length);
            responseContentType = "text/html";

            #endregion
        }
Beispiel #19
0
        /// <summary>
        ///GetFeatureInfo request
        /// </summary>
        protected override void GetFeatureInfo(NameValueCollection requestParams, Stream responseOutputStream, ref string responseContentType)
        {
            #region Request processing GetFeatureInfo

            int x = 0, y = 0, featureCount = 1;
            int row, column;

            if (requestParams["FEATURE_COUNT"] != null)
            {
                int.TryParse(requestParams["FEATURE_COUNT"], out featureCount);
            }

            if (requestParams["I"] == null)
            {
                WmtsException(WmtsExceptionCode.NotApplicable,
                              "Required parameter I undefined.",
                              responseOutputStream,
                              ref responseContentType);
                return;
            }
            else if (!int.TryParse(requestParams["I"], out x))
            {
                WmtsException(WmtsExceptionCode.NotApplicable,
                              "Parameter I has wrong value.",
                              responseOutputStream,
                              ref responseContentType);
                return;
            }

            if (requestParams["J"] == null)
            {
                WmtsException(WmtsExceptionCode.NotApplicable,
                              "Required parameter J undefined.",
                              responseOutputStream,
                              ref responseContentType);
                return;
            }
            else if (!int.TryParse(requestParams["J"], out y))
            {
                WmtsException(WmtsExceptionCode.NotApplicable,
                              "Parameter J has wrong value.",
                              responseOutputStream,
                              ref responseContentType);
                return;
            }

            if (requestParams["TILEROW"] == null)
            {
                WmtsException(WmtsExceptionCode.NotApplicable,
                              "Required parameter TILEROW undefined.",
                              responseOutputStream,
                              ref responseContentType);
                return;
            }
            else if (!int.TryParse(requestParams["TILEROW"], out row))
            {
                WmtsException(WmtsExceptionCode.NotApplicable,
                              "Parameter TILEROW has wrong value.",
                              responseOutputStream,
                              ref responseContentType);
                return;
            }

            if (requestParams["TILECOL"] == null)
            {
                WmtsException(WmtsExceptionCode.NotApplicable,
                              "Required parameter TILECOL undefined.",
                              responseOutputStream,
                              ref responseContentType);
                return;
            }
            else if (!int.TryParse(requestParams["TILECOL"], out column))
            {
                WmtsException(WmtsExceptionCode.NotApplicable,
                              "Parameter TILECOL has wrong value.",
                              responseOutputStream,
                              ref responseContentType);
                return;
            }

            string mimeTypeNeeded = "text/html";
            if (requestParams["INFO_FORMAT"] != null)
            {
                mimeTypeNeeded = requestParams["INFO_FORMAT"];
            }

            Tile tile             = new Tile(_map, (uint)row, (uint)column);
            //_description.Tile = tile; //
            //tile.PixelSize = _description.GetScaleDenominator(_description.ZoomLevel[tileMatrixName]); //
            //tile.ScaleDenominator = _description.GetPixelSize(_description.ZoomLevel[tileMatrixName]); //
            BoundingRectangle bbox = tile.BBox;
            int width = tile.Width, height = tile.Height;

            List <FeatureLayer> queryableLayers = new List <FeatureLayer>();
            if (!string.IsNullOrEmpty(requestParams["LAYER"]))
            {
                string[] layers = requestParams["LAYER"].Split(new[] { ',' });
                foreach (string layer in layers)
                {
                    LayerBase l = null;
                    int       i;
                    for (i = 0; i < _map.Layers.Count; i++)
                    {
                        if (string.Equals(_map.Layers[i].Alias, layer,
                                          StringComparison.InvariantCultureIgnoreCase))
                        {
                            l = _map.Layers[i];
                        }
                    }


                    if (l == null)
                    {
                        WmtsException(WmtsExceptionCode.LayerNotDefined,
                                      "Layer \"" + layer + "\" not found.",
                                      responseOutputStream,
                                      ref responseContentType);
                        return;
                    }
                    else if (!(l is FeatureLayer) || !((FeatureLayer)l).FeaturesSelectable)
                    {
                        WmtsException(WmtsExceptionCode.LayerNotQueryable,
                                      "Layer \"" + layer + "\" is not queryable.",
                                      responseOutputStream,
                                      ref responseContentType);
                        return;
                    }
                    else
                    {
                        queryableLayers.Add((FeatureLayer)l);
                    }
                }

                queryableLayers.Sort(
                    (FeatureLayer l1, FeatureLayer l2) =>
                    _map.Layers.IndexOf(l1) > _map.Layers.IndexOf(l2) ? -1 : 1);

                List <Feature> selectedFeatures = new List <Feature>();

                if (queryableLayers.Count > 0)
                {
                    lock (_syncRoot)
                    {
                        // calculate the error of selection of point and line objects
                        _map.SelectionPointRadius =
                            _selectionMargin * bbox.Width / width;

                        double resultX = bbox.Width / width * x + bbox.MinX;
                        double resultY = bbox.MaxY - bbox.Height / height * y;

                        ICoordinate point = PlanimetryEnvironment.NewCoordinate(resultX, resultY);

                        ICoordinate tempPoint = PlanimetryEnvironment.NewCoordinate(x, y);

                        if (_map.OnTheFlyTransform != null)
                        {
                            ICoordinate delta =
                                PlanimetryEnvironment.NewCoordinate(tempPoint.X + _map.SelectionPointRadius,
                                                                    tempPoint.Y);
                            IMathTransform inverseTransform = _map.OnTheFlyTransform.Inverse();

                            delta =
                                PlanimetryEnvironment.NewCoordinate(inverseTransform.Transform(delta.Values()));

                            _map.SelectionPointRadius =
                                PlanimetryAlgorithms.Distance(
                                    PlanimetryEnvironment.NewCoordinate(
                                        inverseTransform.Transform(tempPoint.Values())), delta);
                        }

                        if (queryableLayers[0].Map.OnTheFlyTransform != null)
                        {
                            IMathTransform inverseTransform = queryableLayers[0].Map.OnTheFlyTransform.Inverse();
                            point =
                                PlanimetryEnvironment.NewCoordinate(inverseTransform.Transform(point.Values()));
                        }

                        foreach (LayerBase l in queryableLayers)
                        {
                            FeatureLayer fl = l as FeatureLayer;
                            if (fl != null)
                            {
                                Feature feature = null;
                                fl.SelectObject(point, out feature);
                                if (feature != null)
                                {
                                    selectedFeatures.Add(feature);
                                }

                                if (selectedFeatures.Count == featureCount)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }

                WmsFeaturesInfoNeededEventArgs args = new WmsFeaturesInfoNeededEventArgs(selectedFeatures,
                                                                                         mimeTypeNeeded,
                                                                                         responseOutputStream,
                                                                                         responseContentType);
                OnFeaturesInfoNeeded(args);
                responseContentType = args.ResponseContentType;

                return;
            }

            StringBuilder sb = new StringBuilder();
            sb.Append("none");

            byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString().ToCharArray());
            responseOutputStream.Write(bytes, 0, bytes.Length);
            responseContentType = "text/html";

            #endregion
        }
        private static void calculateRubberSheetTransform(int width, int height, PointF[,] source, ICoordinate[,] result, ICoordinate[] sourceNodes, ICoordinate[] destNodesShifts, RasterBindingProgress progress)
        {
            double[] w         = new double[sourceNodes.Length];
            double[] distances = new double[sourceNodes.Length];

            int    startProgressPercent = 30;
            int    endProgressPercent   = 70;
            double completed            = 0;
            double previousPercent      = 0;

            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    // проверяем попали ли мы в узел интерполяции
                    bool isNode = false;
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        if (sourceNodes[k].X == source[i, j].X &&
                            sourceNodes[k].Y == source[i, j].Y)
                        {
                            // попали
                            result[i, j] =
                                PlanimetryEnvironment.NewCoordinate(destNodesShifts[k].X + source[i, j].X,
                                                                    destNodesShifts[k].Y + source[i, j].Y);
                            isNode = true;
                        }
                    }

                    if (isNode)
                    {
                        continue;
                    }

                    // расчет расстояний до узлов
                    double maxDistance = 0;
                    for (int t = 0; t < sourceNodes.Length; t++)
                    {
                        ICoordinate p = PlanimetryEnvironment.NewCoordinate(sourceNodes[t].X, sourceNodes[t].Y);
                        distances[t] = PlanimetryAlgorithms.Distance(p,
                                                                     PlanimetryEnvironment.NewCoordinate(source[i, j].X,
                                                                                                         source[i, j].Y));

                        if (maxDistance < distances[t])
                        {
                            maxDistance = distances[t];
                        }
                    }

                    // расчет знаменателей весов узловых точек
                    double sum = 0;
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        double temp = (maxDistance - distances[k]) / (maxDistance * distances[k]);
                        sum += Math.Pow(temp, 2);
                    }

                    // расчет весов узловых точек
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        double temp = (maxDistance - distances[k]) / (maxDistance * distances[k]);
                        w[k] = Math.Pow(temp, 2) / sum;
                    }

                    // расчет значений новых координат
                    result[i, j] = PlanimetryEnvironment.NewCoordinate(source[i, j].X, source[i, j].Y);
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        result[i, j].X += w[k] * destNodesShifts[k].X;
                        result[i, j].Y += w[k] * destNodesShifts[k].Y;
                    }
                }

                notifyProgessListenerIfNeeded(progress, startProgressPercent, endProgressPercent, ref completed, ref previousPercent, width);
            }
        }
        private static double calculateDistanceBrutForce(IGeometry geometry1,
                                                         IGeometry geometry2,
                                                         List <ICoordinate> points1,
                                                         List <ICoordinate> points2,
                                                         double threshold)
        {
            List <MonotoneChain> chains1 = getGeometryChains(geometry1);
            List <MonotoneChain> chains2 = getGeometryChains(geometry2);

            // If both pieces contain sections, they can overlap
            // if the segments intersect - the distance between the figures of zero
            if ((geometry1 is Polygon || geometry1 is Polyline) &&
                (geometry2 is Polygon || geometry2 is Polyline))
            {
                foreach (MonotoneChain chain1 in chains1)
                {
                    foreach (MonotoneChain chain2 in chains2)
                    {
                        if (chain1.BoundsIntersect(chain2) &&
                            chain1.CrossesWith(chain2))
                        {
                            return(0);
                        }
                    }
                }
            }

            PlanimetryAlgorithms.SortCoordsHorizontally(points1);
            PlanimetryAlgorithms.SortCoordsHorizontally(points2);

            double minDistance = double.MaxValue;

            // handle the distance from the segments of the first figure to the points in the second
            if (geometry1 is Polygon || geometry1 is Polyline)
            {
                minDistance = calculateSegmentsPointsDistance(chains1, points2, minDistance, threshold);
                if (minDistance <= threshold)
                {
                    return(minDistance);
                }
            }

            // handle the distance from the segments of the second figure to the points of the first
            if (geometry2 is Polygon || geometry2 is Polyline)
            {
                minDistance = calculateSegmentsPointsDistance(chains2, points1, minDistance, threshold);
                if (minDistance <= threshold)
                {
                    return(minDistance);
                }
            }

            // process the distance between the points of the two figures
            foreach (ICoordinate p1 in points1)
            {
                foreach (ICoordinate p2 in points2)
                {
                    if (p1.X < p2.X - minDistance)
                    {
                        continue;
                    }
                    if (p2.X > p1.X + minDistance)
                    {
                        break;
                    }
                    double d = PlanimetryAlgorithms.Distance(p1, p2);
                    if (d < minDistance)
                    {
                        minDistance = d;
                    }
                    if (minDistance <= threshold)
                    {
                        return(minDistance);
                    }
                }
            }

            return(minDistance);
        }
        /// <summary>
        /// Splits the segments of the chain at the specified points.
        /// </summary>
        /// <param name="list">A list contatinig points where you need to split the chain</param>
        /// <returns>true, if se segment was splitted, false otherwise</returns>
        public bool Split(List <ICoordinate> list)
        {
            if (list.Count == 0)
            {
                return(false);
            }

            PlanimetryAlgorithms.SortCoordsHorizontally(list);
            List <Segment>      newSegments = new List <Segment>();
            List <SegmentLabel> newLabels   = new List <SegmentLabel>();

            List <Segment> splittedSegments = new List <Segment>();
            int            objectIndex      = this.Labels[0].ObjectIndex;
            int            sequenceEndex    = this.Labels[0].SequenceIndex;

            double tolerance = PlanimetryAlgorithms.Tolerance;

            bool hasSplits = false;

            int k = 0;

            foreach (Segment s in _segments)
            {
                bool wasSplitted = false;

                List <ICoordinate>  splitPoints    = null;
                List <SegmentLabel> splittedLabels = null;
                BoundingRectangle   br             = s.GetBoundingRectangle();

                for (int i = 0; i < list.Count; i++)
                {
                    if (br.ContainsPoint(list[i]))
                    {
                        if (PlanimetryAlgorithms.DistanceToSegment(list[i], s) < tolerance &&
                            PlanimetryAlgorithms.Distance(list[i], s.V1) > tolerance &&
                            PlanimetryAlgorithms.Distance(list[i], s.V2) > tolerance)
                        {
                            wasSplitted = true;

                            if (splitPoints == null)
                            {
                                splitPoints    = new List <ICoordinate>();
                                splittedLabels = new List <SegmentLabel>();
                            }

                            splitPoints.Add(list[i]);
                            splittedLabels.Add(new SegmentLabel(objectIndex, sequenceEndex, _labels[k].IndexInSequence));
                        }
                    }
                }

                if (!wasSplitted)
                {
                    newSegments.Add(s);
                    newLabels.Add(Labels[k]);
                }
                else
                {
                    hasSplits = true;
                    splitPoints.Add(s.V1);
                    splittedLabels.Add(new SegmentLabel(objectIndex, sequenceEndex, _labels[k].IndexInSequence));
                    splitPoints.Add(s.V2);
                    splittedLabels.Add(new SegmentLabel(objectIndex, sequenceEndex, _labels[k].IndexInSequence));
                    PlanimetryAlgorithms.OrderPointsOverSegment(splitPoints, s);
                    if (splitPoints[0].ExactEquals(s.V1))
                    {
                        for (int i = 0; i < splitPoints.Count - 1; i++)
                        {
                            newSegments.Add(new Segment(splitPoints[i], splitPoints[i + 1]));
                            newLabels.Add(splittedLabels[i]);
                        }
                    }
                    else
                    {
                        for (int i = splitPoints.Count - 1; i > 0; i--)
                        {
                            newSegments.Add(new Segment(splitPoints[i], splitPoints[i - 1]));
                            newLabels.Add(splittedLabels[i]);
                        }
                    }
                }
                k++;
            }

            if (hasSplits)
            {
                _segments.Clear();
                _labels.Clear();
                for (int i = 0; i < newSegments.Count; i++)
                {
                    internalInsertSegment(newSegments[i], newLabels[i]);
                }
            }

            return(hasSplits);
        }
 /// <summary>
 /// Returns true if coordinates are equal (used tolerance value stored in
 /// <see cref="MapAround.Geometry.PlanimetryAlgorithms.Tolerance"/>).
 /// </summary>
 public static bool operator ==(Coordinate3D p1, ICoordinate p2)
 {
     return(PlanimetryAlgorithms.DistanceTolerant(p1, p2));
 }
        private bool checkWeightedVertex(Polyline polyline, KDTree vertexIndex, SDMinVertex currentVertex, KDTree crossPointIndex)
        {
            // probably not an internal vertex
            if (currentVertex.Previous == null || currentVertex.Next == null)
            {
                return(true);
            }

            // top with infinite weight ("do not remove")
            if (double.IsPositiveInfinity(currentVertex.Weight))
            {
                return(true);
            }


            SDMinVertex previous = currentVertex.Previous;
            SDMinVertex next     = currentVertex.Next;

            // One of the segments formed by the vertex in question may be one of the intersection points.
            // If so, you can not remove the top, as point of self-intersection, it may be removed.
            Segment s1 = new Segment(pointOfWeightedVertex(polyline, currentVertex),
                                     pointOfWeightedVertex(polyline, previous));
            Segment s2 = new Segment(pointOfWeightedVertex(polyline, currentVertex),
                                     pointOfWeightedVertex(polyline, next));

            List <SDMinCrossPoint> crossPoints = new List <SDMinCrossPoint>();

            crossPointIndex.QueryObjectsInRectangle(s1.GetBoundingRectangle(), crossPoints);
            crossPointIndex.QueryObjectsInRectangle(s2.GetBoundingRectangle(), crossPoints);
            foreach (SDMinCrossPoint point in crossPoints)
            {
                if (PlanimetryAlgorithms.LiesOnSegment(point.Point, s1))
                {
                    currentVertex.IsCrossSegmentVertex          = true;
                    currentVertex.Previous.IsCrossSegmentVertex = true;
                    return(false);
                }
                if (PlanimetryAlgorithms.LiesOnSegment(point.Point, s2))
                {
                    currentVertex.IsCrossSegmentVertex      = true;
                    currentVertex.Next.IsCrossSegmentVertex = true;
                    return(false);
                }
            }

            //One of the polyline vertices can belong to a triangle,
            //the apex of which is considered the top. In this case,
            //the top can not be deleted because will be a new point of self-intersection.
            Polygon triangle = new Polygon(new ICoordinate[] { pointOfWeightedVertex(polyline, previous),
                                                               pointOfWeightedVertex(polyline, currentVertex),
                                                               pointOfWeightedVertex(polyline, next) });

            List <SDMinVertex> vertices = new List <SDMinVertex>();

            vertexIndex.QueryObjectsInRectangle <SDMinVertex>(triangle.GetBoundingRectangle(), vertices);

            foreach (SDMinVertex vertex in vertices)
            {
                ICoordinate p = pointOfWeightedVertex(polyline, vertex);

                //point should not be the top of the triangle
                if (p.ExactEquals(triangle.Contours[0].Vertices[0]) ||
                    p.ExactEquals(triangle.Contours[0].Vertices[1]) ||
                    p.ExactEquals(triangle.Contours[0].Vertices[2]))
                {
                    continue;
                }

                if (triangle.ContainsPoint(p))
                {
                    return(false);
                }
            }

            return(true);
        }
 /// <summary>
 /// Gets a value indicating whether this coordinate is equal to another.
 /// Comparisions performs with tolerance value stored in
 /// <see cref="MapAround.Geometry.PlanimetryAlgorithms.Tolerance"/>.
 /// Z values are not compared.
 /// </summary>
 /// <param name="p">The MapAround.Geometry.ICoordinate implementor to compare with the current object</param>
 public bool Equals(ICoordinate p)
 {
     return(PlanimetryAlgorithms.Distance(this, p) < PlanimetryAlgorithms.Tolerance);
 }
Beispiel #26
0
        private void addJoin(LineJoin join, IList <ICoordinate> vertexList, double x1, double y1, double x2, double y2, double x3, double y3)
        {
            double angleBetweenSegments = getAngle(PlanimetryEnvironment.NewCoordinate(x1, y1), PlanimetryEnvironment.NewCoordinate(x2, y2), PlanimetryEnvironment.NewCoordinate(x3, y3), true);

            if (angleBetweenSegments < Math.PI)
            {
                addInteriorJoin(vertexList, x1, y1, x2, y2, x3, y3);
                return;
            }

            double angle1 = getSegmentAngle(x1, y1, x2, y2) - _halfPI;
            double angle2 = getSegmentAngle(x2, y2, x3, y3) - _halfPI;

            if (join == LineJoin.Round && _width <= 2)
            {
                join = LineJoin.Bevel;
            }

            double halfWidth = _width / 2;

            switch (join)
            {
            case LineJoin.Bevel:
                vertexList.Add(pointOnCircle(x2, y2, halfWidth, angle1));
                vertexList.Add(pointOnCircle(x2, y2, halfWidth, angle2));
                break;

            case LineJoin.Round:
                ICoordinate[] points =
                    getCirclePoints(PlanimetryEnvironment.NewCoordinate(x2, y2),
                                    angle1,
                                    angle1 - Math.PI + angleBetweenSegments,
                                    halfWidth,
                                    (int)(Math.Round(_width * Math.PI) / 2));

                foreach (ICoordinate p in points)
                {
                    vertexList.Add(p);
                }
                break;

            case LineJoin.Miter:
            case LineJoin.MiterClipped:

                Segment s1 = new Segment(pointOnCircle(x1, y1, halfWidth, angle1), pointOnCircle(x2, y2, halfWidth, angle1));
                Segment s2 = new Segment(pointOnCircle(x3, y3, halfWidth, angle2), pointOnCircle(x2, y2, halfWidth, angle2));

                ICoordinate miterPoint = null;

                if (PlanimetryAlgorithms.DirectsIntersection(s1, s2, ref miterPoint) == Dimension.Zero)
                {
                    double miterDistance2 = PlanimetryAlgorithms.Distance(miterPoint, PlanimetryEnvironment.NewCoordinate(x2, y2));
                    if (miterDistance2 < _miterLimit * _width / 2)
                    {
                        vertexList.Add(miterPoint);
                    }
                    else
                    {
                        if (join == LineJoin.MiterClipped)
                        {
                            vertexList.Add(pointOnCircle(x2, y2, halfWidth, angle1));
                            vertexList.Add(pointOnCircle(x2, y2, halfWidth, angle2));
                        }
                        else
                        {
                            double l = _miterLimit * _width * 0.5;
                            double miterDistance1 = PlanimetryAlgorithms.Distance(s1.V2, miterPoint);
                            double clipDistance   = ((miterDistance2 - l) * (miterDistance2 - l) + l) / miterDistance1;

                            double f = clipDistance / (miterDistance1 - clipDistance);
                            vertexList.Add(PlanimetryEnvironment.NewCoordinate((f * s1.V2.X + miterPoint.X) / (1 + f),
                                                                               (f * s1.V2.Y + miterPoint.Y) / (1 + f)));
                            vertexList.Add(PlanimetryEnvironment.NewCoordinate((f * s2.V2.X + miterPoint.X) / (1 + f),
                                                                               (f * s2.V2.Y + miterPoint.Y) / (1 + f)));
                        }
                    }
                }
                else
                {
                    if (join == LineJoin.MiterClipped)
                    {
                        vertexList.Add(pointOnCircle(x2, y2, halfWidth, angle1));
                        vertexList.Add(pointOnCircle(x2, y2, halfWidth, angle2));
                    }
                    else
                    {
                        double d     = Math.Sqrt(_width * _width / 4 + _miterLimit * _miterLimit);
                        double alpha = Math.Atan(1 / _miterLimit);
                        vertexList.Add(pointOnCircle(x2, y2, d, angle1 - alpha));
                        vertexList.Add(pointOnCircle(x2, y2, d, angle1 + alpha));
                    }
                }
                break;
            }
        }
 /// <summary>
 /// Returns true if coordinates are not equal (used tolerance value stored in
 /// <see cref="MapAround.Geometry.PlanimetryAlgorithms.Tolerance"/>).
 /// </summary>
 public static bool operator !=(ReadOnlyCoordinate3D p1, ICoordinate p2)
 {
     return(!PlanimetryAlgorithms.DistanceTolerant(p1, p2));
 }