Retour à la documentation
/**
* @class spw.api.GeometryUtils
* @classdesc Classe utilitaire permettant de réaliser des opération topologiques sur
*/
define([
'dojo/_base/lang', 'dojo/_base/array', 'esri/geometry/geometryEngine',
'spw/api/GeometryConverter', 'esri/geometry/Polyline', 'spw/api/ProjectionManager',
'esri/geometry/Point',
'spw/libs/turf'
],
/** @lends spw.api.GeometryUtils.prototype */
function(lang, array, geometryEngine, GeometryConverter, Polyline, ProjectionManager, Point, turf) {
var self = {
buffer: function(geoms, distance, unit, union) {
geoms = [].concat(geoms);
// array.forEach(geoms, lang.hitch(this, function(geom) {
// geom.getExtent && geom.getExtent(); // to generate cache
// }));
union = (union == null ? true : union);
// var results = [];
//
// array.forEach(geoms, function(geom) {
//
// var wgs84 = self._transformGeometry(geom.spatialReference.wkid, '4326', geom);
//
// var geojson = self.toGeoJSON(wgs84);
//
// geojson = turf.buffer({
// type: 'Feature',
// properties: {},
// geometry: geojson
// }, distance, unit);
//
// if (geojson.type === 'FeatureCollection') {
// geojson = turf.combine(geojson).geometry;
// }
// else {
// geojson = geojson.feature.geometry;
// }
//
// wgs84 = self.toEsri(geojson);
//
// results.push(self._transformGeometry('4326', geom.spatialReference.wkid, wgs84));
// });
//
// if (union === true) {
// return self.union(results);
// }
// else {
// return results;
// }
var multiplier = 1;
if (array.some(geoms, lang.hitch(this, function(geom) {
var srid = lang.getObject('spatialReference.wkid', false, geom);
return srid == 4326 || srid == 3857;
}))) {
multiplier = 1.60934;
}
var distances = array.map(geoms, function(){ return distance * multiplier; });
var res = geometryEngine.buffer(geoms, distances, unit, union);
if (res == null) {
return res;
}
return res.length === 1 ? res[0] : res;
},
intersection: function(polygon, line) {
var wgsPoly = self._transformGeometry(polygon.spatialReference.wkid, '4326', polygon);
var geojsonPoly = self.toGeoJSON(wgsPoly);
var wgsLine = self._transformGeometry(line.spatialReference.wkid, '4326', line);
var geojsonLine = self.toGeoJSON(wgsLine);
var lineSlices = self.lineSliceAtIntersection({
type: 'Feature',
properties: {},
geometry: geojsonLine
}, {
type: 'Feature',
properties: {},
geometry: geojsonPoly
});
var pt = null;
for (var i = 0; pt == null && i < lineSlices.features.length - 1; ++i) {
var previous = lineSlices.features[i === 0 ? lineSlices.features.length - 1 : i - 1].geometry;
var next = lineSlices.features[i + 1].geometry;
var current = lineSlices.features[i].geometry;
if (self.equal(current.coordinates[0], previous.coordinates[1])) {
pt = new Point(current.coordinates[0]);
pt.setSpatialReference(line.spatialReference);
}
else if (self.equal(current.coordinates[1], next.coordinates[0])) {
pt = new Point(current.coordinates[1]);
pt.setSpatialReference(line.spatialReference);
}
}
return self._transformGeometry('4326', line.spatialReference.wkid, pt);
},
lineSliceAtIntersection: function(line, segmenter) {
var coordRings = [];
var segmenterFeatures = (segmenter.type === 'FeatureCollection') ?
segmenter.features :
[segmenter];
var segments = [line.geometry.coordinates.slice()];
for (var i = 0; i < segmenterFeatures.length; i++) {
switch (segmenterFeatures[i].geometry.type) {
case 'LineString':
coordRings = [segmenterFeatures[i].geometry.coordinates];
break;
case 'MultiLineString':
case 'Polygon':
coordRings = segmenterFeatures[i].geometry.coordinates;
break;
case 'MultiPolygon':
for (var p = 0; p < segmenterFeatures[i].geometry.coordinates.length; p++) {
coordRings = coordRings.concat(segmenterFeatures[i].geometry.coordinates[p]);
}
break;
}
for (var j = 0; j < coordRings.length; j++) {
segments = self.testLineAndRing(segments, coordRings[j]);
}
}
return turf.featurecollection(segments.map(function (segment) {
return turf.linestring(segment, lang.mixin({}, line.properties));
}));
},
testLineAndRing: function(segments, ring) {
var tempSegments = [];
for (var k = 0; k < segments.length; k++) {
var curr = [];
for (var l = 0; l < segments[k].length - 1; l++) {
curr.push(segments[k][l]);
for (var m = 0; m < ring.length - 1; m++) {
if (self.equal(segments[k][l], ring[m])) {
tempSegments.push(curr.slice());
curr = [segments[k][l]];
continue;
}
var is = self.linesIntersect(
segments[k][l],
segments[k][l + 1],
ring[m],
ring[m + 1]
);
if (is) {
curr.push(is);
tempSegments.push(curr.slice());
curr = [is];
}
}
}
curr.push(segments[k][segments[k].length - 1]);
tempSegments.push(curr.slice());
}
return tempSegments;
},
equal: function(pt1, pt2) {
return (pt1[0] === pt2[0] && pt1[1] === pt2[1]);
},
linesIntersect: function(a1, a2, b1, b2) {
var uaT = (b2[0] - b1[0]) * (a1[1] - b1[1]) - (b2[1] - b1[1]) * (a1[0] - b1[0]),
ubT = (a2[0] - a1[0]) * (a1[1] - b1[1]) - (a2[1] - a1[1]) * (a1[0] - b1[0]),
uB = (b2[1] - b1[1]) * (a2[0] - a1[0]) - (b2[0] - b1[0]) * (a2[1] - a1[1]);
if (uB !== 0) {
var ua = uaT / uB,
ub = ubT / uB;
if (ua > 0 && ua < 1 && ub > 0 && ub < 1) {
return [a1[0] + ua * (a2[0] - a1[0]), a1[1] + ua * (a2[1] - a1[1])];
}
}
},
area: function(geom, unit) {
// var geojson = {
// type: 'Feature',
// properties: {},
// geometry: self.toGeoJSON(self._transformGeometry(geom.spatialReference.wkid, '4326', geom))
// };
//
// return turf.area(geojson);
return (geom.spatialReference.wkid != 4326 && geom.spatialReference.wkid != 3857) ? geometryEngine.planarArea(geom, unit) : geometryEngine.geodesicArea(geom, unit);
},
geometryLength: function(geom, unit) {
return (geom.spatialReference.wkid != 4326 && geom.spatialReference.wkid != 3857) ? geometryEngine.planarLength(geom, unit) : geometryEngine.geodesicLength(geom, unit);
},
union: function(geometries) {
return geometryEngine.union(geometries);
},
projectOnLine: function(line, pt) {
var goodLine = line;
if (line.paths.length > 1) {
var minDis = Infinity;
array.forEach(line.paths, function(path) {
var tmp = new Polyline(line.spatialReference);
tmp.addPath(path);
var dis = self.distance(tmp, pt);
if (dis < minDis) {
minDis = dis;
goodLine = tmp;
}
});
}
var lineWgs84 = self._transformGeometry(goodLine.spatialReference.wkid, '4326', goodLine);
var ptWgs84 = self._transformGeometry(pt.spatialReference.wkid, '4326', pt);
var lineGeoJSON = {
type: 'Feature',
properties: {},
geometry: self.toGeoJSON(lineWgs84)
};
var ptGeoJSON = {
type: 'Feature',
properties: {},
geometry: self.toGeoJSON(ptWgs84)
};
var snapped = turf.pointOnLine(lineGeoJSON, ptGeoJSON);
var wgs84 = self.toEsri(snapped.geometry);
return self._transformGeometry('4326', goodLine.spatialReference.wkid, wgs84);
},
slice: function(pt1, pt2, line) {
var lineWgs84 = self._transformGeometry(line.spatialReference.wkid, '4326', line);
var pt1Wgs84 = self._transformGeometry(pt1.spatialReference.wkid, '4326', pt1);
var pt2Wgs84 = self._transformGeometry(pt2.spatialReference.wkid, '4326', pt2);
var lineGeoJSON = {
type: 'Feature',
properties: {},
geometry: self.toGeoJSON(lineWgs84)
};
var pt1GeoJSON = {
type: 'Feature',
properties: {},
geometry: self.toGeoJSON(pt1Wgs84)
};
var pt2GeoJSON = {
type: 'Feature',
properties: {},
geometry: self.toGeoJSON(pt2Wgs84)
};
var sliced = turf.lineSlice(pt1GeoJSON, pt2GeoJSON, lineGeoJSON);
var wgs84 = self.toEsri(sliced.geometry);
return self._transformGeometry('4326', line.spatialReference.wkid, wgs84);
},
merge: function(features) {
if (features.length === 1) {
return features[0];
}
for (var i = 1; i < features.length; ++i) {
array.forEach(features[i].paths, function(path) {
features[0].addPath(path);
});
}
return features[0];
/*var ftc = {
type: 'FeatureCollection',
features: array.map(features, function(feature) {
var wgs84 = self._transformGeometry(feature.spatialReference.wkid, '4326', feature);
var geojson = self.toGeoJSON(wgs84);
return {
type: 'Feature',
properties: {},
geometry: geojson
};
})
};
var merged = turf.merge(ftc);
var wgs84 = self.toEsri(merged.geometry);
return self._transformGeometry('4326', features[0].spatialReference.wkid, wgs84);*/ // multiple paths
},
distance: function(from, to) {
return geometryEngine.distance(from, to);
},
nearestPoint: function(geometry, pt) {
return geometryEngine.nearestVertex(geometry, pt);
},
angleBetweenLines: function(line1, line2) {
var l1pt1 = line1.getPoint(0, 0);
var l1pt2 = line1.getPoint(0, 1);
var l2pt1 = line2.getPoint(0, 0);
var l2pt2 = line2.getPoint(0, 1);
var angle1 = Math.atan2(l1pt1.y - l1pt2.y, l1pt1.x - l1pt2.x);
var angle2 = Math.atan2(l2pt1.y - l2pt2.y, l2pt1.x - l2pt2.x);
return self.radToDeg(angle1 - angle2);
},
length: function(geom) {
return geometryEngine.planarLength(geom, 'meters');
},
rotate: function(geom, angle, pt) {
return geometryEngine.rotate(geom, angle, pt);
},
radToDeg: function(rad) {
return (rad * 180) / Math.PI;
},
degToRad: function(deg) {
return (deg * Math.PI) / 180;
},
contains: function(container, contained) {
var containers = [].concat(container);
var unioned = self.union(array.map(containers, function(c) {
if (c.getExtent) {
c.getExtent();
}
return c;
}));
if (contained.cache == null) {
contained.getExtent();
}
return geometryEngine.contains(unioned, contained);
},
toGeoJSON: function(geom) {
return GeometryConverter.esriToGeoJSON(geom);
},
touches: function(geom1, geom2) {
return geometryEngine.touches(geom1, geom2);
},
intersects: function(geom1, geom2) {
return geometryEngine.intersects(geom1, geom2);
},
toEsri: function(geojson) {
var esri = GeometryConverter.geoJSONToEsri(geojson);
// to refresh geometry's cache !
if (esri.getExtent) {
esri.getExtent();
}
return esri;
},
_transformGeometry: function(source, dest, geometry) {
return ProjectionManager.getInstance().transform(source, dest, geometry);
}
};
return self;
});