private static Helper.Coordinate GetIntersection( Helper.Coordinate p1, Helper.Coordinate p2, Helper.Coordinate p3, Helper.Coordinate p4) { // http://csharphelper.com/blog/2014/08/determine-where-two-lines-intersect-in-c/ // Get the segments' parameters. var dx12 = p2.X - p1.X; var dy12 = p2.Y - p1.Y; var dx34 = p4.X - p3.X; var dy34 = p4.Y - p3.Y; // Solve for t1 and t2 var denominator = dy12 * dx34 - dx12 * dy34; var t1 = ((p1.X - p3.X) * dy34 + (p3.Y - p1.Y) * dx34) / denominator; if (double.IsInfinity(t1)) { // The lines are parallel (or close enough to it). throw new ArgumentException("Lines are parallel"); } // Find the point of intersection. return(new Helper.Coordinate(p1.X + dx12 * t1, p1.Y + dy12 * t1)); }
public static void AddCoordinatesToLineSf(Shapefile sfLines, Helper.Coordinate coordinate1, Helper.Coordinate coordinate2) { var shp = new Shape(); if (!shp.Create(ShpfileType.SHP_POLYLINE)) { throw new Exception("Error in creating shape. Error: " + shp.ErrorMsg[shp.LastErrorCode]); } if (shp.AddPoint(coordinate1.X, coordinate1.Y) < 0) { throw new Exception("Error in adding point. Error: " + shp.ErrorMsg[shp.LastErrorCode]); } if (shp.AddPoint(coordinate2.X, coordinate2.Y) < 0) { throw new Exception("Error in adding point. Error: " + shp.ErrorMsg[shp.LastErrorCode]); } // Check if this line intersects other lines, if so shorten to intersection point: var numShapes = sfLines.NumShapes; for (var i = 0; i < numShapes; i++) { var shpTesting = sfLines.Shape[i]; if (!shpTesting.Crosses(shp)) { continue; } var newCoordinate = GetIntersection(Helper.PointToCoordinate(shp.Point[0]), Helper.PointToCoordinate(shp.Point[1]), Helper.PointToCoordinate(shpTesting.Point[0]), Helper.PointToCoordinate(shpTesting.Point[1])); // Replace point: shp.Point[1] = Helper.CoordinateToPoint(newCoordinate); } if (sfLines.EditAddShape(shp) < 0) { throw new Exception("Error in adding shape. Error: " + sfLines.ErrorMsg[sfLines.LastErrorCode]); } }
private static void AddToPolygonSf(IShapefile sfPolygons, Helper.Coordinate coordinate1_1, Helper.Coordinate coordinate1_2, Helper.Coordinate coordinate2_1, Helper.Coordinate coordinate2_2) { var shp = new Shape(); if (!shp.Create(ShpfileType.SHP_POLYGON)) { throw new Exception("Error in creating shape. Error: " + shp.ErrorMsg[shp.LastErrorCode]); } if (shp.AddPoint(coordinate1_1.X, coordinate1_1.Y) < 0) { throw new Exception("Error in adding point. Error: " + shp.ErrorMsg[shp.LastErrorCode]); } if (shp.AddPoint(coordinate1_2.X, coordinate1_2.Y) < 0) { throw new Exception("Error in adding point. Error: " + shp.ErrorMsg[shp.LastErrorCode]); } if (shp.AddPoint(coordinate2_1.X, coordinate2_1.Y) < 0) { throw new Exception("Error in adding point. Error: " + shp.ErrorMsg[shp.LastErrorCode]); } if (shp.AddPoint(coordinate2_2.X, coordinate2_2.Y) < 0) { throw new Exception("Error in adding point. Error: " + shp.ErrorMsg[shp.LastErrorCode]); } // Closing: if (shp.AddPoint(coordinate1_1.X, coordinate1_1.Y) < 0) { throw new Exception("Error in adding point. Error: " + shp.ErrorMsg[shp.LastErrorCode]); } if (!shp.PartIsClockWise[0]) { shp.ReversePointsOrder(0); } if (!shp.IsValid) { shp = shp.FixUp2(tkUnitsOfMeasure.umMeters); if (shp == null) { return; } if (!shp.IsValid) { throw new Exception("Error: shape is not valid. " + shp.IsValidReason); } } // Check if this new shape is overlapping other shapes, // if so clip and add that version instead: var numShapes = sfPolygons.NumShapes; for (var i = 0; i < numShapes; i++) { var shpTesting = sfPolygons.Shape[i]; // If within, don't add again: if (shp.Within(shpTesting)) { Debug.WriteLine("Shape is within " + i); return; } // If overlaps, add only new part: if (shp.Overlaps(shpTesting)) { Debug.WriteLine(i + " overlaps. Touches: " + shp.Touches(shpTesting)); // TODO: Returns wrong part: //shp = shpTesting.Clip(shp, tkClipOperation.clDifference); //if (shp == null) return; } } if (shp.ShapeType2D != ShpfileType.SHP_POLYGON) { return; } if (!shp.PartIsClockWise[0]) { shp.ReversePointsOrder(0); } if (!shp.IsValid) { shp = shp.FixUp2(tkUnitsOfMeasure.umMeters); if (shp == null) { return; } if (!shp.IsValid) { throw new Exception("Error: shape is not valid. " + shp.IsValidReason); } } if (shp.ShapeType2D != ShpfileType.SHP_POLYGON) { return; } if (sfPolygons.EditAddShape(shp) < 0) { throw new Exception("Error in adding shape. Error: " + sfPolygons.ErrorMsg[sfPolygons.LastErrorCode]); } }
public void CreateSprayAreas() { var sfTracks = Helper.OpenShapefile(Path.Combine(@"sf", "Tracks.shp")); var sfPoints = Helper.CreateSf(ShpfileType.SHP_POINT); var sfLines = Helper.CreateSf(ShpfileType.SHP_POLYLINE); var sfPolygons = Helper.CreateSf(ShpfileType.SHP_POLYGON); // Set projection: sfPoints.GeoProjection = sfTracks.GeoProjection.Clone(); sfLines.GeoProjection = sfTracks.GeoProjection.Clone(); sfPolygons.GeoProjection = sfTracks.GeoProjection.Clone(); var tempPath = Path.GetTempPath(); var utils = new Utils(); // Debug first track point: var debugPoint = sfTracks.Shape[0].Point[0]; Debug.WriteLine(debugPoint.x); Debug.WriteLine(debugPoint.y); // Get the first shape: var shp = sfTracks.Shape[0]; var trackLength = shp.Length; // Get the first point: var firstPoint = shp.Point[0]; // Save first point to result shapefile: Helper.AddPointToPointSf(sfPoints, firstPoint); var segmentLength = 0d; // Total lenght between the points const int distance = 10; // Distance between points const int length = 15; // Length of perpendicular lines var skip = 1; while (trackLength > segmentLength) { // Create next point on line: var lastShape = sfPoints.Shape[sfPoints.NumShapes - 1]; var previousPoint = lastShape.Point[0]; var nextPoint = shp.InterpolatePoint(previousPoint, distance * skip); Helper.AddPointToPointSf(sfPoints, nextPoint); skip = 1; // reset // Create perpendicular line var angle = GetAngle(utils, previousPoint, nextPoint); var previousPointCoordinate = new Helper.Coordinate(previousPoint.x, previousPoint.y); var perpendicularCoordinate1 = new Helper.Coordinate(Math.Cos(angle) * length + previousPoint.x, Math.Sin(angle) * length + previousPoint.y); AddCoordinatesToLineSf(sfLines, previousPointCoordinate, perpendicularCoordinate1); // Add line to other side: var perpendicularCoordinate2 = new Helper.Coordinate(Math.Cos(angle) * -1 * length + previousPoint.x, Math.Sin(angle) * -1 * length + previousPoint.y); AddCoordinatesToLineSf(sfLines, previousPointCoordinate, perpendicularCoordinate2); // Create polygon from two perpendicular lines: var numShapes = sfLines.NumShapes; if (numShapes >= 4) { Debug.WriteLine("numShapes: " + numShapes); // Get first perpendicular line: var shpLine1 = sfLines.Shape[numShapes - 4]; var point1_1 = shpLine1.Point[0]; var point1_2 = shpLine1.Point[1]; var shpLine3 = sfLines.Shape[numShapes - 2]; var point3_1 = shpLine3.Point[0]; var point3_2 = shpLine3.Point[1]; AddToPolygonSf(sfPolygons, new Helper.Coordinate(point1_1.x, point1_1.y), new Helper.Coordinate(point1_2.x, point1_2.y), new Helper.Coordinate(point3_2.x, point3_2.y), new Helper.Coordinate(point3_1.x, point3_1.y)); // Other side: var shpLine2 = sfLines.Shape[numShapes - 3]; var point2_1 = shpLine2.Point[0]; var point2_2 = shpLine2.Point[1]; var shpLine4 = sfLines.Shape[numShapes - 1]; var point4_1 = shpLine4.Point[0]; var point4_2 = shpLine4.Point[1]; AddToPolygonSf(sfPolygons, new Helper.Coordinate(point2_1.x, point2_1.y), new Helper.Coordinate(point2_2.x, point2_2.y), new Helper.Coordinate(point4_2.x, point4_2.y), new Helper.Coordinate(point4_1.x, point4_1.y)); } segmentLength += distance; // Debug: if (sfPolygons.NumShapes >= 33) { break; } } // TODO: Check last point sfTracks.Close(); Helper.SaveAsShapefile(sfPoints, Path.Combine(tempPath, "InterpolatedPoints.shp")); Helper.SaveAsShapefile(sfLines, Path.Combine(tempPath, "PerpendicularLines.shp")); Helper.SaveAsShapefile(sfPolygons, Path.Combine(tempPath, "SprayAreas.shp")); }