public static List <PointLatLngAlt> CreateCorridor(List <PointLatLngAlt> polygon, double altitude, double distance, double spacing, double angle, double overshoot1, double overshoot2, StartPosition startpos, bool shutter, float minLaneSeparation, double width, float leadin = 0) { if (spacing < 4 && spacing != 0) { spacing = 4; } if (distance < 0.1) { distance = 0.1; } if (polygon.Count == 0) { return(new List <PointLatLngAlt>()); } List <PointLatLngAlt> ans = new List <PointLatLngAlt>(); // utm zone distance calcs will be done in int utmzone = polygon[0].GetUTMZone(); // utm position list List <utmpos> utmpositions = utmpos.ToList(PointLatLngAlt.ToUTM(utmzone, polygon), utmzone); var lanes = (width / distance); var start = (int)((lanes / 2) * -1); var end = start * -1; for (int lane = start; lane <= end; lane++) { // correct side of the line we are on because of list reversal int multi = 1; if ((lane - start) % 2 == 1) { multi = -1; } if (startpos != StartPosition.Home) { utmpositions.Reverse(); } GenerateOffsetPath(utmpositions, distance * multi * lane, spacing, utmzone) .ForEach(pnt => { ans.Add(pnt); }); if (startpos == StartPosition.Home) { utmpositions.Reverse(); } } // set the altitude on all points ans.ForEach(plla => { plla.Alt = altitude; }); return(ans); }
public utmpos(PointLatLngAlt pos) { double[] dd = pos.ToUTM(pos.GetUTMZone()); this.x = dd[0]; this.y = dd[1]; this.zone = pos.GetUTMZone(); this.Tag = null; }
public utmpos(PointLatLngAlt pos) { double[] dd = pos.ToUTM(); this.x = dd[0]; this.y = dd[1]; this.zone = pos.GetUTMZone(); this.Tag = null; }
public static srtm.altresponce getAltitude(double lat, double lng, double zoom = 16) { lock (index) if (index.Count == 0) { return(srtm.altresponce.Invalid); } var answer = new srtm.altresponce(); foreach (var geotiffdata in index.ToArray()) { if (geotiffdata.Area.Contains(lat, lng)) { // get answer var xf = map(lat, geotiffdata.Area.Top, geotiffdata.Area.Bottom, 0, geotiffdata.height - 1); var yf = map(lng, geotiffdata.Area.Left, geotiffdata.Area.Right, 0, geotiffdata.width - 1); //wgs84 && etrs89 if (geotiffdata.ProjectedCSTypeGeoKey >= 3038 && geotiffdata.ProjectedCSTypeGeoKey <= 3051 || geotiffdata.ProjectedCSTypeGeoKey >= 32601 && geotiffdata.ProjectedCSTypeGeoKey <= 32760 || geotiffdata.ProjectedCSTypeGeoKey >= 25828 && geotiffdata.ProjectedCSTypeGeoKey <= 25838) { var pnt = PointLatLngAlt.ToUTM((geotiffdata.UTMZone) * 1, lat, lng); xf = map(pnt[1], geotiffdata.y, geotiffdata.y - geotiffdata.height * geotiffdata.yscale, 0, geotiffdata.height - 1); yf = map(pnt[0], geotiffdata.x, geotiffdata.x + geotiffdata.width * geotiffdata.xscale, 0, geotiffdata.width - 1); } int x_int = (int)xf; double x_frac = xf - x_int; int y_int = (int)yf; double y_frac = yf - y_int; //could be on one of the other images if (x_int < 0 || y_int < 0 || x_int >= geotiffdata.width - 1 || y_int >= geotiffdata.height - 1) { continue; } double alt00 = GetAlt(geotiffdata, x_int, y_int); double alt10 = GetAlt(geotiffdata, x_int + 1, y_int); double alt01 = GetAlt(geotiffdata, x_int, y_int + 1); double alt11 = GetAlt(geotiffdata, x_int + 1, y_int + 1); double v1 = avg(alt00, alt10, x_frac); double v2 = avg(alt01, alt11, x_frac); double v = avg(v1, v2, y_frac); if (v > -1000) { answer.currenttype = srtm.tiletype.valid; } if (alt00 < -1000 || alt10 < -1000 || alt01 < -1000 || alt11 < -1000) { answer.currenttype = srtm.tiletype.invalid; } answer.alt = v; answer.altsource = "GeoTiff"; return(answer); } } return(srtm.altresponce.Invalid); }
/// <summary> /// /// </summary> /// <param name="polygon">the polygon outside edge</param> /// <param name="altitude">flight altitude</param> /// <param name="distance">distance between lines</param> /// <param name="spacing">space between triggers</param> /// <param name="angle">angle of the lines</param> /// <param name="overshoot1"></param> /// <param name="overshoot2"></param> /// <param name="startpos"></param> /// <param name="shutter"></param> /// <param name="minLaneSeparation"></param> /// <param name="leadin1"></param> /// <param name="leadin2"></param> /// <param name="HomeLocation"></param> /// <param name="useextendedendpoint">use the leadout point to find the next closes line</param> /// <returns></returns> public static List <PointLatLngAlt> CreateGrid(List <PointLatLngAlt> polygon, double altitude, double distance, double spacing, double angle, double overshoot1, double overshoot2, StartPosition startpos, bool shutter, float minLaneSeparation, float leadin1, float leadin2, PointLatLngAlt HomeLocation, bool useextendedendpoint = true) { //DoDebug(); if (spacing < 0.1 && spacing != 0) { spacing = 0.1; } if (distance < 0.1) { distance = 0.1; } if (polygon.Count == 0) { return(new List <PointLatLngAlt>()); } // Make a non round number in case of corner cases if (minLaneSeparation != 0) { minLaneSeparation += 0.5F; } // Lane Separation in meters double minLaneSeparationINMeters = minLaneSeparation * distance; List <PointLatLngAlt> ans = new List <PointLatLngAlt>(); // utm zone distance calcs will be done in int utmzone = polygon[0].GetUTMZone(); // utm position list List <utmpos> utmpositions = utmpos.ToList(PointLatLngAlt.ToUTM(utmzone, polygon), utmzone); // close the loop if its not already if (utmpositions[0] != utmpositions[utmpositions.Count - 1]) { utmpositions.Add(utmpositions[0]); // make a full loop } // get mins/maxs of coverage area Rect area = getPolyMinMax(utmpositions); // get initial grid // used to determine the size of the outer grid area double diagdist = area.DiagDistance(); // somewhere to store out generated lines List <linelatlng> grid = new List <linelatlng>(); // number of lines we need int lines = 0; // get start point middle double x = area.MidWidth; double y = area.MidHeight; addtomap(new utmpos(x, y, utmzone), "Base"); // get left extent double xb1 = x; double yb1 = y; // to the left newpos(ref xb1, ref yb1, angle - 90, diagdist / 2 + distance); // backwards newpos(ref xb1, ref yb1, angle + 180, diagdist / 2 + distance); utmpos left = new utmpos(xb1, yb1, utmzone); addtomap(left, "left"); // get right extent double xb2 = x; double yb2 = y; // to the right newpos(ref xb2, ref yb2, angle + 90, diagdist / 2 + distance); // backwards newpos(ref xb2, ref yb2, angle + 180, diagdist / 2 + distance); utmpos right = new utmpos(xb2, yb2, utmzone); addtomap(right, "right"); // set start point to left hand side x = xb1; y = yb1; // draw the outergrid, this is a grid that cover the entire area of the rectangle plus more. while (lines < ((diagdist + distance * 2) / distance)) { // copy the start point to generate the end point double nx = x; double ny = y; newpos(ref nx, ref ny, angle, diagdist + distance * 2); linelatlng line = new linelatlng(); line.p1 = new utmpos(x, y, utmzone); line.p2 = new utmpos(nx, ny, utmzone); line.basepnt = new utmpos(x, y, utmzone); grid.Add(line); // addtomap(line); newpos(ref x, ref y, angle + 90, distance); lines++; } // find intersections with our polygon // store lines that dont have any intersections List <linelatlng> remove = new List <linelatlng>(); int gridno = grid.Count; // cycle through our grid for (int a = 0; a < gridno; a++) { double closestdistance = double.MaxValue; double farestdistance = double.MinValue; utmpos closestpoint = utmpos.Zero; utmpos farestpoint = utmpos.Zero; // somewhere to store our intersections List <utmpos> matchs = new List <utmpos>(); int b = -1; int crosses = 0; utmpos newutmpos = utmpos.Zero; foreach (utmpos pnt in utmpositions) { b++; if (b == 0) { continue; } newutmpos = FindLineIntersection(utmpositions[b - 1], utmpositions[b], grid[a].p1, grid[a].p2); if (!newutmpos.IsZero) { crosses++; matchs.Add(newutmpos); if (closestdistance > grid[a].p1.GetDistance(newutmpos)) { closestpoint.y = newutmpos.y; closestpoint.x = newutmpos.x; closestpoint.zone = newutmpos.zone; closestdistance = grid[a].p1.GetDistance(newutmpos); } if (farestdistance < grid[a].p1.GetDistance(newutmpos)) { farestpoint.y = newutmpos.y; farestpoint.x = newutmpos.x; farestpoint.zone = newutmpos.zone; farestdistance = grid[a].p1.GetDistance(newutmpos); } } } if (crosses == 0) // outside our polygon { if (!PointInPolygon(grid[a].p1, utmpositions) && !PointInPolygon(grid[a].p2, utmpositions)) { remove.Add(grid[a]); } } else if (crosses == 1) // bad - shouldnt happen { } else if (crosses == 2) // simple start and finish { linelatlng line = grid[a]; line.p1 = closestpoint; line.p2 = farestpoint; grid[a] = line; } else // multiple intersections { linelatlng line = grid[a]; remove.Add(line); while (matchs.Count > 1) { linelatlng newline = new linelatlng(); closestpoint = findClosestPoint(closestpoint, matchs); newline.p1 = closestpoint; matchs.Remove(closestpoint); closestpoint = findClosestPoint(closestpoint, matchs); newline.p2 = closestpoint; matchs.Remove(closestpoint); newline.basepnt = line.basepnt; grid.Add(newline); } } } // cleanup and keep only lines that pass though our polygon foreach (linelatlng line in remove) { grid.Remove(line); } // debug foreach (linelatlng line in grid) { addtomap(line); } if (grid.Count == 0) { return(ans); } // pick start positon based on initial point rectangle utmpos startposutm; switch (startpos) { default: case StartPosition.Home: startposutm = new utmpos(HomeLocation); break; case StartPosition.BottomLeft: startposutm = new utmpos(area.Left, area.Bottom, utmzone); break; case StartPosition.BottomRight: startposutm = new utmpos(area.Right, area.Bottom, utmzone); break; case StartPosition.TopLeft: startposutm = new utmpos(area.Left, area.Top, utmzone); break; case StartPosition.TopRight: startposutm = new utmpos(area.Right, area.Top, utmzone); break; case StartPosition.Point: startposutm = new utmpos(StartPointLatLngAlt); break; } // find the closes polygon point based from our startpos selection startposutm = findClosestPoint(startposutm, utmpositions); // find closest line point to startpos linelatlng closest = findClosestLine(startposutm, grid, 0 /*Lane separation does not apply to starting point*/, angle); utmpos lastpnt; // get the closes point from the line we picked if (closest.p1.GetDistance(startposutm) < closest.p2.GetDistance(startposutm)) { lastpnt = closest.p1; } else { lastpnt = closest.p2; } // S = start // E = end // ME = middle end // SM = start middle while (grid.Count > 0) { // for each line, check which end of the line is the next closest if (closest.p1.GetDistance(lastpnt) < closest.p2.GetDistance(lastpnt)) { utmpos newstart = newpos(closest.p1, angle, -leadin1); newstart.Tag = "S"; addtomap(newstart, "S"); ans.Add(newstart); if (leadin1 < 0) { var p2 = new utmpos(newstart) { Tag = "SM" }; addtomap(p2, "SM"); ans.Add(p2); } else { closest.p1.Tag = "SM"; addtomap(closest.p1, "SM"); ans.Add(closest.p1); } if (spacing > 0) { for (double d = (spacing - ((closest.basepnt.GetDistance(closest.p1)) % spacing)); d < (closest.p1.GetDistance(closest.p2)); d += spacing) { double ax = closest.p1.x; double ay = closest.p1.y; newpos(ref ax, ref ay, angle, d); var utmpos1 = new utmpos(ax, ay, utmzone) { Tag = "M" }; addtomap(utmpos1, "M"); ans.Add(utmpos1); } } utmpos newend = newpos(closest.p2, angle, overshoot1); if (overshoot1 < 0) { var p2 = new utmpos(newend) { Tag = "ME" }; addtomap(p2, "ME"); ans.Add(p2); } else { closest.p2.Tag = "ME"; addtomap(closest.p2, "ME"); ans.Add(closest.p2); } newend.Tag = "E"; addtomap(newend, "E"); ans.Add(newend); lastpnt = closest.p2; grid.Remove(closest); if (grid.Count == 0) { break; } if (useextendedendpoint) { closest = findClosestLine(newend, grid, minLaneSeparationINMeters, angle); } else { closest = findClosestLine(closest.p2, grid, minLaneSeparationINMeters, angle); } } else { utmpos newstart = newpos(closest.p2, angle, leadin2); newstart.Tag = "S"; addtomap(newstart, "S"); ans.Add(newstart); if (leadin2 < 0) { var p2 = new utmpos(newstart) { Tag = "SM" }; addtomap(p2, "SM"); ans.Add(p2); } else { closest.p2.Tag = "SM"; addtomap(closest.p2, "SM"); ans.Add(closest.p2); } if (spacing > 0) { for (double d = ((closest.basepnt.GetDistance(closest.p2)) % spacing); d < (closest.p1.GetDistance(closest.p2)); d += spacing) { double ax = closest.p2.x; double ay = closest.p2.y; newpos(ref ax, ref ay, angle, -d); var utmpos2 = new utmpos(ax, ay, utmzone) { Tag = "M" }; addtomap(utmpos2, "M"); ans.Add(utmpos2); } } utmpos newend = newpos(closest.p1, angle, -overshoot2); if (overshoot2 < 0) { var p2 = new utmpos(newend) { Tag = "ME" }; addtomap(p2, "ME"); ans.Add(p2); } else { closest.p1.Tag = "ME"; addtomap(closest.p1, "ME"); ans.Add(closest.p1); } newend.Tag = "E"; addtomap(newend, "E"); ans.Add(newend); lastpnt = closest.p1; grid.Remove(closest); if (grid.Count == 0) { break; } if (useextendedendpoint) { closest = findClosestLine(newend, grid, minLaneSeparationINMeters, angle); } else { closest = findClosestLine(closest.p1, grid, minLaneSeparationINMeters, angle); } } } // set the altitude on all points ans.ForEach(plla => { plla.Alt = altitude; }); return(ans); }
public static List <PointLatLngAlt> CreateRotary(List <PointLatLngAlt> polygon, double altitude, double distance, double spacing, double angle, double overshoot1, double overshoot2, StartPosition startpos, bool shutter, float minLaneSeparation, float leadin, PointLatLngAlt HomeLocation) { spacing = 0; if (distance < 0.1) { distance = 0.1; } if (polygon.Count == 0) { return(new List <PointLatLngAlt>()); } List <utmpos> ans = new List <utmpos>(); // utm zone distance calcs will be done in int utmzone = polygon[0].GetUTMZone(); // utm position list List <utmpos> utmpositions = utmpos.ToList(PointLatLngAlt.ToUTM(utmzone, polygon), utmzone); // close the loop if its not already if (utmpositions[0] != utmpositions[utmpositions.Count - 1]) { utmpositions.Add(utmpositions[0]); // make a full loop } var maxlane = 200; // (Centroid(utmpositions).GetDistance(utmpositions[0]) / distance); ClipperLib.ClipperOffset clipperOffset = new ClipperLib.ClipperOffset(); clipperOffset.AddPath(utmpositions.Select(a => { return(new ClipperLib.IntPoint(a.x * 1000.0, a.y * 1000.0)); }).ToList(), ClipperLib.JoinType.jtMiter, ClipperLib.EndType.etClosedPolygon); for (int lane = 0; lane < maxlane; lane++) { List <utmpos> ans1 = new List <utmpos>(); ClipperLib.PolyTree tree = new ClipperLib.PolyTree(); clipperOffset.Execute(ref tree, (Int64)(distance * 1000.0 * -lane)); if (tree.ChildCount == 0) { break; } foreach (var treeChild in tree.Childs) { ans1 = treeChild.Contour.Select(a => new utmpos(a.X / 1000.0, a.Y / 1000.0, utmzone)) .ToList(); if (ans.Count() > 2) { var start1 = ans[ans.Count() - 1]; var end1 = ans[ans.Count() - 2]; var start2 = ans1[0]; var end2 = ans1[ans1.Count() - 1]; } ans.AddRange(ans1); } } // set the altitude on all points return(ans.Select(plla => { var a = plla.ToLLA(); a.Alt = altitude; a.Tag = "S"; return a; }).ToList()); }
public static List <PointLatLngAlt> CreateRotary(List <PointLatLngAlt> polygon, double altitude, double distance, double spacing, double angle, double overshoot1, double overshoot2, StartPosition startpos, bool shutter, float minLaneSeparation, float leadin, PointLatLngAlt HomeLocation, int clockwise_laps, bool match_spiral_perimeter, int laps) { spacing = 0; if (distance < 0.1) { distance = 0.1; } if (polygon.Count == 0) { return(new List <PointLatLngAlt>()); } List <utmpos> ans = new List <utmpos>(); // utm zone distance calcs will be done in int utmzone = polygon[0].GetUTMZone(); // utm position list List <utmpos> utmpositions = utmpos.ToList(PointLatLngAlt.ToUTM(utmzone, polygon), utmzone); // close the loop if its not already if (utmpositions[0] != utmpositions[utmpositions.Count - 1]) { utmpositions.Add(utmpositions[0]); // make a full loop } var maxlane = laps; // (Centroid(utmpositions).GetDistance(utmpositions[0]) / distance); ClipperLib.ClipperOffset clipperOffset = new ClipperLib.ClipperOffset(); clipperOffset.AddPath(utmpositions.Select(a => { return(new ClipperLib.IntPoint(a.x * 1000.0, a.y * 1000.0)); }).ToList(), ClipperLib.JoinType.jtMiter, ClipperLib.EndType.etClosedPolygon); for (int lane = 0; lane < maxlane; lane++) { List <utmpos> ans1 = new List <utmpos>(); ClipperLib.PolyTree tree = new ClipperLib.PolyTree(); clipperOffset.Execute(ref tree, (Int64)(distance * 1000.0 * -lane)); if (tree.ChildCount == 0) { break; } if (lane < clockwise_laps || clockwise_laps < 0) { ClipperLib.Clipper.ReversePaths(ClipperLib.Clipper.PolyTreeToPaths(tree)); } foreach (var treeChild in tree.Childs) { ans1 = treeChild.Contour.Select(a => new utmpos(a.X / 1000.0, a.Y / 1000.0, utmzone)) .ToList(); if (lane == 0 && clockwise_laps != 1 && match_spiral_perimeter) { ans1.Insert(0, ans1.Last <utmpos>()); // start at the last point of the first calculated lap // to make a closed polygon on the first trip around } if (lane == clockwise_laps - 1) { ans1.Add(ans1.First <utmpos>()); // revisit the first waypoint on this lap to cleanly exit the CW pattern } if (ans.Count() > 2) { var start1 = ans[ans.Count() - 1]; var end1 = ans[ans.Count() - 2]; var start2 = ans1[0]; var end2 = ans1[ans1.Count() - 1]; } ans.AddRange(ans1); } } // set the altitude on all points return(ans.Select(plla => { var a = plla.ToLLA(); a.Alt = altitude; a.Tag = "S"; return a; }).ToList()); }