public static bool polygonCollidesWithlineSegment(Polygon poly, IntPoint transformed_startPoint, IntPoint transformed_endPoint, PointMatrix transformation_matrix) { IntPoint p0 = transformation_matrix.apply(poly.back()); foreach (IntPoint p1_ in poly) { IntPoint p1 = transformation_matrix.apply(p1_); if ((p0.Y >= transformed_startPoint.Y && p1.Y <= transformed_startPoint.Y) || (p1.Y >= transformed_startPoint.Y && p0.Y <= transformed_startPoint.Y)) { long x; if (p1.Y == p0.Y) { x = p0.X; } else { x = p0.X + (p1.X - p0.X) * (transformed_startPoint.Y - p0.Y) / (p1.Y - p0.Y); } if (x >= transformed_startPoint.X && x <= transformed_endPoint.X) { return(true); } } p0 = p1; } return(false); }
public static bool polygonCollidesWithlineSegment(Polygon poly, IntPoint startPoint, IntPoint endPoint) { IntPoint diff = endPoint - startPoint; PointMatrix transformation_matrix = new PointMatrix(diff); IntPoint transformed_startPoint = transformation_matrix.apply(startPoint); IntPoint transformed_endPoint = transformation_matrix.apply(endPoint); return(polygonCollidesWithlineSegment(poly, transformed_startPoint, transformed_endPoint, transformation_matrix)); }
public static void ApplyMatrix(this Polygons polygons, PointMatrix matrix) { for (int i = 0; i < polygons.Count; i++) { for (int j = 0; j < polygons[i].Count; j++) { polygons[i][j] = matrix.apply(polygons[i][j]); } } }
private void CalcMinMax() { int errorDist = 100; for (int bounderyIndex = 0; bounderyIndex < bounderyPolygons.Count; bounderyIndex++) { Polygon boundryPolygon = bounderyPolygons[bounderyIndex]; minXPosition[bounderyIndex] = long.MaxValue; maxXPosition[bounderyIndex] = long.MinValue; IntPoint previousPosition = lineToSameYMatrix.apply(boundryPolygon[boundryPolygon.Count - 1]); for (int pointIndex = 0; pointIndex < boundryPolygon.Count; pointIndex++) { IntPoint currentPosition = lineToSameYMatrix.apply(boundryPolygon[pointIndex]); if ((previousPosition.Y + errorDist >= rotatedStartPoint.Y && currentPosition.Y - errorDist <= rotatedStartPoint.Y) || (currentPosition.Y + errorDist >= rotatedStartPoint.Y && previousPosition.Y - errorDist <= rotatedStartPoint.Y)) // prev -> current crosses the start -> end { if (currentPosition.Y != previousPosition.Y) { long x = previousPosition.X + (currentPosition.X - previousPosition.X) * (rotatedStartPoint.Y - previousPosition.Y) / (currentPosition.Y - previousPosition.Y); if (x + errorDist >= rotatedStartPoint.X && x - errorDist <= rotatedEndPoint.X) { if (x - errorDist <= minXPosition[bounderyIndex]) { minXPosition[bounderyIndex] = x; indexOfMinX[bounderyIndex] = pointIndex; } if (x + errorDist > maxXPosition[bounderyIndex]) { maxXPosition[bounderyIndex] = x; indexOfMaxX[bounderyIndex] = pointIndex; } } } } previousPosition = currentPosition; } } }
void calcMinMax() { for (int bounderyIndex = 0; bounderyIndex < bounderyPolygons.Count; bounderyIndex++) { Polygon boundryPolygon = bounderyPolygons[bounderyIndex]; minXPosition[bounderyIndex] = long.MaxValue; maxXPosition[bounderyIndex] = long.MinValue; IntPoint previousPosition = matrix.apply(boundryPolygon[boundryPolygon.Count - 1]); for (int pointIndex = 0; pointIndex < boundryPolygon.Count; pointIndex++) { IntPoint currentPosition = matrix.apply(boundryPolygon[pointIndex]); if ((previousPosition.Y > nomalizedStartPoint.Y && currentPosition.Y < nomalizedStartPoint.Y) || (currentPosition.Y > nomalizedStartPoint.Y && previousPosition.Y < nomalizedStartPoint.Y)) { long x = previousPosition.X + (currentPosition.X - previousPosition.X) * (nomalizedStartPoint.Y - previousPosition.Y) / (currentPosition.Y - previousPosition.Y); if (x >= nomalizedStartPoint.X && x <= normalizedEndPoint.X) { if (x < minXPosition[bounderyIndex]) { minXPosition[bounderyIndex] = x; indexOfMinX[bounderyIndex] = pointIndex; } if (x > maxXPosition[bounderyIndex]) { maxXPosition[bounderyIndex] = x; indexOfMaxX[bounderyIndex] = pointIndex; } } } previousPosition = currentPosition; } } }
bool collisionTest(IntPoint startPoint, IntPoint endPoint) { IntPoint diff = endPoint - startPoint; matrix = new PointMatrix(diff); this.nomalizedStartPoint = matrix.apply(startPoint); this.normalizedEndPoint = matrix.apply(endPoint); for (int bounderyIndex = 0; bounderyIndex < bounderyPolygons.Count; bounderyIndex++) { Polygon boundryPolygon = bounderyPolygons[bounderyIndex]; if (boundryPolygon.Count < 1) { continue; } IntPoint lastPosition = matrix.apply(boundryPolygon[boundryPolygon.Count - 1]); for (int pointIndex = 0; pointIndex < boundryPolygon.Count; pointIndex++) { IntPoint currentPosition = matrix.apply(boundryPolygon[pointIndex]); if ((lastPosition.Y > nomalizedStartPoint.Y && currentPosition.Y < nomalizedStartPoint.Y) || (currentPosition.Y > nomalizedStartPoint.Y && lastPosition.Y < nomalizedStartPoint.Y)) { long x = lastPosition.X + (currentPosition.X - lastPosition.X) * (nomalizedStartPoint.Y - lastPosition.Y) / (currentPosition.Y - lastPosition.Y); if (x > nomalizedStartPoint.X && x < normalizedEndPoint.X) { return(true); } } lastPosition = currentPosition; } } return(false); }
public static bool polygonCollidesWithlineSegment(Polygons polys, IntPoint startPoint, IntPoint endPoint) { IntPoint diff = endPoint - startPoint; PointMatrix transformation_matrix = new PointMatrix(diff); IntPoint transformed_startPoint = transformation_matrix.apply(startPoint); IntPoint transformed_endPoint = transformation_matrix.apply(endPoint); return polygonCollidesWithlineSegment(polys, transformed_startPoint, transformed_endPoint, transformation_matrix); }
public bool CreatePathInsideBoundary(IntPoint startPoint, IntPoint endPoint, List <IntPoint> pathThatIsInside) { if (saveDebugData) { using (StreamWriter sw = File.AppendText("test.txt")) { if (boundry) { string pointsString = bounderyPolygons.WriteToString(); sw.WriteLine(pointsString); } sw.WriteLine(startPoint.ToString() + " " + endPoint.ToString()); } } if ((endPoint - startPoint).ShorterThen(1500)) { // If the movement is very short (not a lot of time to ooze filament) // then don't add any points return(true); } bool addEndpoint = false; //Check if we are inside the comb boundaries if (!PointIsInsideBoundary(startPoint)) { if (!MovePointInsideBoundary(ref startPoint)) { //If we fail to move the point inside the comb boundary we need to retract. return(false); } pathThatIsInside.Add(startPoint); } if (!PointIsInsideBoundary(endPoint)) { if (!MovePointInsideBoundary(ref endPoint)) { //If we fail to move the point inside the comb boundary we need to retract. return(false); } addEndpoint = true; } // Check if we are crossing any bounderies if (!DoesLineCrossBoundery(startPoint, endPoint)) { //We're not crossing any boundaries. So skip the comb generation. if (!addEndpoint && pathThatIsInside.Count == 0) { //Only skip if we didn't move the start and end point. return(true); } } // Calculate the matrix to change points so they are in the direction of the line segment. { IntPoint diff = endPoint - startPoint; lineToSameYMatrix = new PointMatrix(diff); this.rotatedStartPoint = lineToSameYMatrix.apply(startPoint); this.rotatedEndPoint = lineToSameYMatrix.apply(endPoint); } // Calculate the minimum and maximum positions where we cross the comb boundary CalcMinMax(); long nomalizedStartX = rotatedStartPoint.X; List <IntPoint> pointList = new List <IntPoint>(); // Now walk trough the crossings, for every boundary we cross, find the initial cross point and the exit point. // Then add all the points in between to the pointList and continue with the next boundary we will cross, // until there are no more boundaries to cross. // This gives a path from the start to finish curved around the holes that it encounters. while (true) { // if we go up enough we should run into the boundry int abovePolyIndex = GetPolygonIndexAbove(nomalizedStartX); if (abovePolyIndex < 0) { break; } pointList.Add(lineToSameYMatrix.unapply(new IntPoint(minXPosition[abovePolyIndex] - 200, rotatedStartPoint.Y))); if ((indexOfMinX[abovePolyIndex] - indexOfMaxX[abovePolyIndex] + bounderyPolygons[abovePolyIndex].Count) % bounderyPolygons[abovePolyIndex].Count > (indexOfMaxX[abovePolyIndex] - indexOfMinX[abovePolyIndex] + bounderyPolygons[abovePolyIndex].Count) % bounderyPolygons[abovePolyIndex].Count) { for (int i = indexOfMinX[abovePolyIndex]; i != indexOfMaxX[abovePolyIndex]; i = (i < bounderyPolygons[abovePolyIndex].Count - 1) ? (i + 1) : (0)) { pointList.Add(GetBounderyPointWithOffset(abovePolyIndex, i)); } } else { indexOfMinX[abovePolyIndex]--; if (indexOfMinX[abovePolyIndex] == -1) { indexOfMinX[abovePolyIndex] = bounderyPolygons[abovePolyIndex].Count - 1; } indexOfMaxX[abovePolyIndex]--; if (indexOfMaxX[abovePolyIndex] == -1) { indexOfMaxX[abovePolyIndex] = bounderyPolygons[abovePolyIndex].Count - 1; } for (int i = indexOfMinX[abovePolyIndex]; i != indexOfMaxX[abovePolyIndex]; i = (i > 0) ? (i - 1) : (bounderyPolygons[abovePolyIndex].Count - 1)) { pointList.Add(GetBounderyPointWithOffset(abovePolyIndex, i)); } } pointList.Add(lineToSameYMatrix.unapply(new IntPoint(maxXPosition[abovePolyIndex] + 200, rotatedStartPoint.Y))); nomalizedStartX = maxXPosition[abovePolyIndex]; } pointList.Add(endPoint); if (addEndpoint) { pointList.Add(endPoint); } #if false // Optimize the pointList, skip each point we could already reach by connecting directly to the next point. for (int startIndex = 0; startIndex < pointList.Count - 2; startIndex++) { IntPoint startPosition = pointList[startIndex]; // make sure there is at least one point between the start and the end to optomize if (pointList.Count > startIndex + 2) { for (int checkIndex = pointList.Count - 1; checkIndex > startIndex + 1; checkIndex--) { IntPoint checkPosition = pointList[checkIndex]; if (!DoesLineCrossBoundery(startPosition, checkPosition)) { // Remove all the points from startIndex+1 to checkIndex-1, inclusive. for (int i = startIndex + 1; i < checkIndex; i++) { pointList.RemoveAt(startIndex + 1); } // we removed all the points up to start so we are done with the inner loop break; } } } } #endif foreach (IntPoint point in pointList) { pathThatIsInside.Add(point); } return(true); }
public bool CreatePathInsideBoundary(IntPoint startPoint, IntPoint endPoint, List<IntPoint> pathThatIsInside) { if (saveDebugData) { using (StreamWriter sw = File.AppendText("test.txt")) { if (boundry) { string pointsString = bounderyPolygons.WriteToString(); sw.WriteLine(pointsString); } sw.WriteLine(startPoint.ToString() + " " + endPoint.ToString()); } } if ((endPoint - startPoint).ShorterThen(1500)) { // If the movement is very short (not a lot of time to ooze filament) // then don't add any points return true; } bool addEndpoint = false; //Check if we are inside the comb boundaries if (!PointIsInsideBoundary(startPoint)) { if (!MovePointInsideBoundary(ref startPoint)) { //If we fail to move the point inside the comb boundary we need to retract. return false; } pathThatIsInside.Add(startPoint); } if (!PointIsInsideBoundary(endPoint)) { if (!MovePointInsideBoundary(ref endPoint)) { //If we fail to move the point inside the comb boundary we need to retract. return false; } addEndpoint = true; } // Check if we are crossing any bounderies if (!DoesLineCrossBoundery(startPoint, endPoint)) { //We're not crossing any boundaries. So skip the comb generation. if (!addEndpoint && pathThatIsInside.Count == 0) { //Only skip if we didn't move the start and end point. return true; } } // Calculate the matrix to change points so they are in the direction of the line segment. { IntPoint diff = endPoint - startPoint; lineToSameYMatrix = new PointMatrix(diff); this.rotatedStartPoint = lineToSameYMatrix.apply(startPoint); this.rotatedEndPoint = lineToSameYMatrix.apply(endPoint); } // Calculate the minimum and maximum positions where we cross the comb boundary CalcMinMax(); long nomalizedStartX = rotatedStartPoint.X; List<IntPoint> pointList = new List<IntPoint>(); // Now walk trough the crossings, for every boundary we cross, find the initial cross point and the exit point. // Then add all the points in between to the pointList and continue with the next boundary we will cross, // until there are no more boundaries to cross. // This gives a path from the start to finish curved around the holes that it encounters. while (true) { // if we go up enough we should run into the boundry int abovePolyIndex = GetPolygonIndexAbove(nomalizedStartX); if (abovePolyIndex < 0) { break; } pointList.Add(lineToSameYMatrix.unapply(new IntPoint(minXPosition[abovePolyIndex] - 200, rotatedStartPoint.Y))); if ((indexOfMinX[abovePolyIndex] - indexOfMaxX[abovePolyIndex] + bounderyPolygons[abovePolyIndex].Count) % bounderyPolygons[abovePolyIndex].Count > (indexOfMaxX[abovePolyIndex] - indexOfMinX[abovePolyIndex] + bounderyPolygons[abovePolyIndex].Count) % bounderyPolygons[abovePolyIndex].Count) { for (int i = indexOfMinX[abovePolyIndex]; i != indexOfMaxX[abovePolyIndex]; i = (i < bounderyPolygons[abovePolyIndex].Count - 1) ? (i + 1) : (0)) { pointList.Add(GetBounderyPointWithOffset(abovePolyIndex, i)); } } else { indexOfMinX[abovePolyIndex]--; if (indexOfMinX[abovePolyIndex] == -1) { indexOfMinX[abovePolyIndex] = bounderyPolygons[abovePolyIndex].Count - 1; } indexOfMaxX[abovePolyIndex]--; if (indexOfMaxX[abovePolyIndex] == -1) { indexOfMaxX[abovePolyIndex] = bounderyPolygons[abovePolyIndex].Count - 1; } for (int i = indexOfMinX[abovePolyIndex]; i != indexOfMaxX[abovePolyIndex]; i = (i > 0) ? (i - 1) : (bounderyPolygons[abovePolyIndex].Count - 1)) { pointList.Add(GetBounderyPointWithOffset(abovePolyIndex, i)); } } pointList.Add(lineToSameYMatrix.unapply(new IntPoint(maxXPosition[abovePolyIndex] + 200, rotatedStartPoint.Y))); nomalizedStartX = maxXPosition[abovePolyIndex]; } pointList.Add(endPoint); if (addEndpoint) { pointList.Add(endPoint); } #if false // Optimize the pointList, skip each point we could already reach by connecting directly to the next point. for (int startIndex = 0; startIndex < pointList.Count - 2; startIndex++) { IntPoint startPosition = pointList[startIndex]; // make sure there is at least one point between the start and the end to optomize if (pointList.Count > startIndex + 2) { for (int checkIndex = pointList.Count - 1; checkIndex > startIndex + 1; checkIndex--) { IntPoint checkPosition = pointList[checkIndex]; if (!DoesLineCrossBoundery(startPosition, checkPosition)) { // Remove all the points from startIndex+1 to checkIndex-1, inclusive. for (int i = startIndex + 1; i < checkIndex; i++) { pointList.RemoveAt(startIndex + 1); } // we removed all the points up to start so we are done with the inner loop break; } } } } #endif foreach (IntPoint point in pointList) { pathThatIsInside.Add(point); } return true; }
public static bool polygonCollidesWithlineSegment(Polygon poly, IntPoint transformed_startPoint, IntPoint transformed_endPoint, PointMatrix transformation_matrix) { IntPoint p0 = transformation_matrix.apply(poly.back()); foreach (IntPoint p1_ in poly) { IntPoint p1 = transformation_matrix.apply(p1_); if ((p0.Y >= transformed_startPoint.Y && p1.Y <= transformed_startPoint.Y) || (p1.Y >= transformed_startPoint.Y && p0.Y <= transformed_startPoint.Y)) { long x; if (p1.Y == p0.Y) { x = p0.X; } else { x = p0.X + (p1.X - p0.X) * (transformed_startPoint.Y - p0.Y) / (p1.Y - p0.Y); } if (x >= transformed_startPoint.X && x <= transformed_endPoint.X) return true; } p0 = p1; } return false; }