public static Feature Along(LineString line, double distance, string units = "kilometers") { var coords = line.Coordinates; double travelled = 0; for (var i = 0; i < coords.Count; i++) { if (distance >= travelled && i == coords.Count - 1) { break; } else if (travelled >= distance) { var overshot = distance - travelled; if (Math.Abs(overshot) < double.Epsilon) { return(Turf.Point(coords[i])); } else { var direction = Turf.Bearing(coords[i], coords[i - 1]) - 180; var interpolated = Turf.Destination(coords[i], overshot, direction, units); return(interpolated); } } else { travelled += Turf.Distance(coords[i], coords[i + 1], units); } } return(Turf.Point(coords[coords.Count - 1])); }
/** * Takes a set of features, calculates the bbox of all input features, and returns a bounding box. * * @name bbox * @param {(Feature|FeatureCollection)} geojson input features * @return {Array<number>} bbox extent in [minX, minY, maxX, maxY] order * @example * var pt1 = point([114.175329, 22.2524]) * var pt2 = point([114.170007, 22.267969]) * var pt3 = point([114.200649, 22.274641]) * var pt4 = point([114.200649, 22.274641]) * var pt5 = point([114.186744, 22.265745]) * var features = featureCollection([pt1, pt2, pt3, pt4, pt5]) * * var bbox = turf.bbox(features); * * var bboxPolygon = turf.bboxPolygon(bbox); * * //=bbox * * //=bboxPolygon */ public static List <double> Bbox(IGeoJSONObject geojson) { var bbox = new List <double>() { double.PositiveInfinity, double.PositiveInfinity, double.NegativeInfinity, double.NegativeInfinity }; Turf.CoordEach(geojson, (List <double> coord) => { if (bbox[0] > coord[0]) { bbox[0] = coord[0]; } if (bbox[1] > coord[1]) { bbox[1] = coord[1]; } if (bbox[2] < coord[0]) { bbox[2] = coord[0]; } if (bbox[3] < coord[1]) { bbox[3] = coord[1]; } }); return(bbox); }
/** * Takes a {@link Feature} or {@link FeatureCollection} and returns the absolute center point of all features. * * @name center * @param {(Feature|FeatureCollection)} layer input features * @return {Feature<Point>} a Point feature at the absolute center point of all input features * @example * var features = { * "type": "FeatureCollection", * "features": [ * { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.522259, 35.4691] * } * }, { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.502754, 35.463455] * } * }, { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.508269, 35.463245] * } * }, { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.516809, 35.465779] * } * }, { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.515372, 35.467072] * } * }, { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.509363, 35.463053] * } * }, { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.511123, 35.466601] * } * }, { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.518547, 35.469327] * } * }, { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.519706, 35.469659] * } * }, { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.517839, 35.466998] * } * }, { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.508678, 35.464942] * } * }, { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-97.514914, 35.463453] * } * } * ] * }; * * var centerPt = turf.center(features); * centerPt.properties['marker-size'] = 'large'; * centerPt.properties['marker-color'] = '#000'; * * var resultFeatures = features.features.concat(centerPt); * var result = { * "type": "FeatureCollection", * "features": resultFeatures * }; * * //=result */ public static Feature Center(IGeoJSONObject layer) { var ext = Bbox(layer); var x = (ext[0] + ext[2]) / 2; var y = (ext[1] + ext[3]) / 2; return(Turf.Point(new double[] { x, y })); }
/** * Takes a feature or set of features and returns all positions as * {@link Point|points}. * * @name explode * @param {(Feature|FeatureCollection)} geojson input features * @return {FeatureCollection<point>} points representing the exploded input features * @throws {Error} if it encounters an unknown geometry type * @example * var poly = { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Polygon", * "coordinates": [[ * [177.434692, -17.77517], * [177.402076, -17.779093], * [177.38079, -17.803937], * [177.40242, -17.826164], * [177.438468, -17.824857], * [177.454948, -17.796746], * [177.434692, -17.77517] * ]] * } * }; * * var points = turf.explode(poly); * * //=poly * * //=points */ public static FeatureCollection Explode(IGeoJSONObject geojson) { var points = new List <Feature>(); CoordEach(geojson, (GeographicPosition coord) => { points.Add(Turf.Point(coord)); }); return(new FeatureCollection(points)); }
/** * Takes one or more features and calculates the centroid using * the mean of all vertices. * This lessens the effect of small islands and artifacts when calculating * the centroid of a set of polygons. * * @name centroid * @param {(Feature|FeatureCollection)} features input features * @return {Feature<Point>} the centroid of the input features * @example * var poly = { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Polygon", * "coordinates": [[ * [105.818939,21.004714], * [105.818939,21.061754], * [105.890007,21.061754], * [105.890007,21.004714], * [105.818939,21.004714] * ]] * } * }; * * var centroidPt = turf.centroid(poly); * * var result = { * "type": "FeatureCollection", * "features": [poly, centroidPt] * }; * * //=result */ public static Feature Centroid(IGeoJSONObject features) { double xSum = 0; double ySum = 0; int len = 0; Turf.CoordEach(features, (List <double> coord) => { xSum += coord[0]; ySum += coord[1]; len++; }, true); return(Turf.Point(new double[] { xSum / (double)len, ySum / (double)len })); }
private static double Distance(List <double> from, List <double> to, string units = "kilometers") { var degrees2radians = Math.PI / 180; var dLat = degrees2radians * (to[1] - from[1]); var dLon = degrees2radians * (to[0] - from[0]); var lat1 = degrees2radians * from[1]; var lat2 = degrees2radians * to[1]; var a = Math.Pow(Math.Sin(dLat / 2), 2) + Math.Pow(Math.Sin(dLon / 2), 2) * Math.Cos(lat1) * Math.Cos(lat2); return(Turf.RadiansToDistance(2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)), units)); }
/** * Takes a {@link Point} and calculates the circle polygon given a radius in degrees, radians, miles, or kilometers; and steps for precision. * * @name circle * @param {Feature<Point>} center center point * @param {number} radius radius of the circle * @param {number} [steps=64] number of steps * @param {string} [units=kilometers] miles, kilometers, degrees, or radians * @returns {Feature<Polygon>} circle polygon * @example * var center = point([-75.343, 39.984]); * var radius = 5; * var steps = 10; * var units = 'kilometers'; * * var circle = turf.circle(center, radius, steps, units); * * //=circle */ public static Feature Circle(Feature center, double radius, int steps = 64, string units = "kilometers") { List <IPosition> coordinates = new List <IPosition>(); for (var i = 0; i < steps; i++) { coordinates.Add(((Point)Turf.Destination(center, radius, i * 360 / steps, units).Geometry).Coordinates); } coordinates.Add(coordinates[0]); return(new Feature( new Polygon(new List <LineString>() { new LineString(coordinates) }) )); }
private static Feature Destination(List <double> from, double distance, double bearing, string units = "kilometers") { var degrees2radians = Math.PI / 180; var radians2degrees = 180 / Math.PI; var coordinates1 = Turf.GetCoord(from); var longitude1 = degrees2radians * coordinates1[0]; var latitude1 = degrees2radians * coordinates1[1]; var bearing_rad = degrees2radians * bearing; var radians = Turf.DistanceToRadians(distance, units); var latitude2 = Math.Asin(Math.Sin(latitude1) * Math.Cos(radians) + Math.Cos(latitude1) * Math.Sin(radians) * Math.Cos(bearing_rad)); var longitude2 = longitude1 + Math.Atan2(Math.Sin(bearing_rad) * Math.Sin(radians) * Math.Cos(latitude1), Math.Cos(radians) - Math.Sin(latitude1) * Math.Sin(latitude2)); return(Turf.Point(new double[] { radians2degrees *longitude2, radians2degrees *latitude2 })); }
/** * Takes a {@link Point} and a {@link Polygon} or {@link MultiPolygon} and determines if the point resides inside the polygon. The polygon can * be convex or concave. The function accounts for holes. * * @name inside * @param {Feature<Point>} point input point * @param {Feature<(Polygon|MultiPolygon)>} polygon input polygon or multipolygon * @return {boolean} `true` if the Point is inside the Polygon; `false` if the Point is not inside the Polygon * @example * var pt = point([-77, 44]); * var poly = polygon([[ * [-81, 41], * [-81, 47], * [-72, 47], * [-72, 41], * [-81, 41] * ]]); * * var isInside = turf.inside(pt, poly); * * //=isInside */ static public bool Inside(Feature point, Feature poly) { var type = poly.Geometry.Type; if (type == GeoJSONObjectType.Polygon) { return(Inside_(Turf.GetCoord(point), new List <Polygon>() { (Polygon)poly.Geometry })); } else if (type == GeoJSONObjectType.MultiPolygon) { return(Inside_(Turf.GetCoord(point), ((MultiPolygon)poly.Geometry).Coordinates)); } else { throw new Exception("2nd argument must be Polygon or MultiPolygon"); } }
public static double Bearing(Feature start, Feature end) { return(Bearing(Turf.GetCoord(start), Turf.GetCoord(end))); }
/** * Takes two {@link Point|points} and finds the geographic bearing between them. * * @name bearing * @param {Feature<Point>} start starting Point * @param {Feature<Point>} end ending Point * @returns {number} bearing in decimal degrees * @example * var point1 = { * "type": "Feature", * "properties": { * "marker-color": '#f00' * }, * "geometry": { * "type": "Point", * "coordinates": [-75.343, 39.984] * } * }; * var point2 = { * "type": "Feature", * "properties": { * "marker-color": '#0f0' * }, * "geometry": { * "type": "Point", * "coordinates": [-75.534, 39.123] * } * }; * * var points = { * "type": "FeatureCollection", * "features": [point1, point2] * }; * * //=points * * var bearing = turf.bearing(point1, point2); * * //=bearing */ public static double Bearing(IPosition start, IPosition end) { return(Bearing(Turf.GetCoord(start), Turf.GetCoord(end))); }
public static double Distance(Feature from, Feature to, string units = "kilometers") { return(Distance(Turf.GetCoord(from), Turf.GetCoord(to), units)); }
/** * Calculates the distance between two {@link Point|points} in degrees, radians, * miles, or kilometers. This uses the * [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula) * to account for global curvature. * * @name distance * @param {Feature<Point>} from origin point * @param {Feature<Point>} to destination point * @param {string} [units=kilometers] can be degrees, radians, miles, or kilometers * @return {number} distance between the two points * @example * var from = { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-75.343, 39.984] * } * }; * var to = { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [-75.534, 39.123] * } * }; * var units = "miles"; * * var points = { * "type": "FeatureCollection", * "features": [from, to] * }; * * //=points * * var distance = turf.distance(from, to, units); * * //=distance */ public static double Distance(IPosition from, IPosition to, string units = "kilometers") { return(Distance(Turf.GetCoord(from), Turf.GetCoord(to), units)); }
public static Feature Destination(Feature from, double distance, double bearing, string units = "kilometers") { return(Destination(Turf.GetCoord(from), distance, bearing, units)); }