Ejemplo n.º 1
0
        public static bool OnSegment(IntPoint start, IntPoint testPosition, IntPoint end)
        {
            if (start == end)
            {
                if (testPosition == start)
                {
                    return(true);
                }

                return(false);
            }

            IntPoint segmentDelta      = end - start;
            long     segmentLength     = segmentDelta.Length();
            IntPoint pointRelStart     = testPosition - start;
            long     distanceFromStart = segmentDelta.Dot(pointRelStart) / segmentLength;

            if (distanceFromStart >= 0 && distanceFromStart <= segmentLength)
            {
                IntPoint segmentDeltaLeft      = segmentDelta.GetPerpendicularLeft();
                long     distanceFromStartLeft = segmentDeltaLeft.Dot(pointRelStart) / segmentLength;

                if (distanceFromStartLeft == 0)
                {
                    return(true);
                }
            }

            return(false);
        }
        public static void MovePointInsideBoundary(this Polygons boundaryPolygons, IntPoint startPosition, out Tuple <int, int, IntPoint> polyPointPosition,
                                                   List <QuadTree <int> > edgeQuadTrees  = null,
                                                   List <QuadTree <int> > pointQuadTrees = null)
        {
            Tuple <int, int, IntPoint> bestPolyPointPosition = new Tuple <int, int, IntPoint>(0, 0, startPosition);

            if (boundaryPolygons.PointIsInside(startPosition, edgeQuadTrees, pointQuadTrees))
            {
                // already inside
                polyPointPosition = null;
                return;
            }

            long     bestDist      = long.MaxValue;
            IntPoint bestMoveDelta = new IntPoint();

            for (int polygonIndex = 0; polygonIndex < boundaryPolygons.Count; polygonIndex++)
            {
                var boundaryPolygon = boundaryPolygons[polygonIndex];
                if (boundaryPolygon.Count < 3)
                {
                    continue;
                }

                for (int pointIndex = 0; pointIndex < boundaryPolygon.Count; pointIndex++)
                {
                    IntPoint segmentStart = boundaryPolygon[pointIndex];

                    IntPoint pointRelStart = startPosition - segmentStart;
                    long     distFromStart = pointRelStart.Length();
                    if (distFromStart < bestDist)
                    {
                        bestDist = distFromStart;
                        bestPolyPointPosition = new Tuple <int, int, IntPoint>(polygonIndex, pointIndex, segmentStart);
                    }

                    IntPoint segmentEnd = boundaryPolygon[(pointIndex + 1) % boundaryPolygon.Count];

                    IntPoint segmentDelta      = segmentEnd - segmentStart;
                    long     segmentLength     = segmentDelta.Length();
                    IntPoint segmentLeft       = segmentDelta.GetPerpendicularLeft();
                    long     segmentLeftLength = segmentLeft.Length();

                    long distanceFromStart = segmentDelta.Dot(pointRelStart) / segmentLength;

                    if (distanceFromStart >= 0 && distanceFromStart <= segmentDelta.Length())
                    {
                        long distToBoundarySegment = segmentLeft.Dot(pointRelStart) / segmentLeftLength;

                        if (Math.Abs(distToBoundarySegment) < bestDist)
                        {
                            IntPoint pointAlongCurrentSegment = startPosition;
                            if (distToBoundarySegment != 0)
                            {
                                pointAlongCurrentSegment = startPosition - segmentLeft * distToBoundarySegment / segmentLeftLength;
                            }

                            bestDist = Math.Abs(distToBoundarySegment);
                            bestPolyPointPosition = new Tuple <int, int, IntPoint>(polygonIndex, pointIndex, pointAlongCurrentSegment);
                            bestMoveDelta         = segmentLeft;
                        }
                    }

                    segmentStart = segmentEnd;
                }
            }

            polyPointPosition = bestPolyPointPosition;
        }