/* Copyright (c) 2016 Jean-Marc VIGLINO,
released under the CeCILL-B license (French BSD license)
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
Usefull function to handle geometric operations
*/
import ol_geom_LineString from 'ol/geom/LineString.js'
import ol_geom_LinearRing from 'ol/geom/LinearRing.js'
import ol_geom_MultiLineString from 'ol/geom/MultiLineString.js'
import ol_geom_MultiPoint from 'ol/geom/MultiPoint.js'
import ol_geom_MultiPolygon from 'ol/geom/MultiPolygon.js'
import ol_geom_Point from 'ol/geom/Point.js'
import ol_geom_Polygon from 'ol/geom/Polygon.js'
import ol_geom_Circle from 'ol/geom/Circle.js'
import {getCenter as ol_extent_getCenter} from 'ol/extent.js'
import {buffer as ol_extent_buffer} from 'ol/extent.js'
/** Distance beetween 2 points
* Usefull geometric functions
* @param {ol.Coordinate} p1 first point
* @param {ol.Coordinate} p2 second point
* @return {number} distance
*/
var ol_coordinate_dist2d = function(p1, p2) {
var dx = p1[0]-p2[0];
var dy = p1[1]-p2[1];
return Math.sqrt(dx*dx+dy*dy);
}
/** 2 points are equal
* Usefull geometric functions
* @param {ol.Coordinate} p1 first point
* @param {ol.Coordinate} p2 second point
* @return {boolean}
*/
var ol_coordinate_equal = function(p1, p2) {
return (p1[0]==p2[0] && p1[1]==p2[1]);
}
/** Get center coordinate of a feature
* @param {ol.Feature} f
* @return {ol.coordinate} the center
*/
var ol_coordinate_getFeatureCenter = function(f) {
return ol_coordinate_getGeomCenter (f.getGeometry());
};
/** Get center coordinate of a geometry
* @param {ol.geom.Geometry} geom
* @return {ol.Coordinate} the center
*/
var ol_coordinate_getGeomCenter = function(geom) {
switch (geom.getType()) {
case 'Point':
return geom.getCoordinates();
case "MultiPolygon":
geom = geom.getPolygon(0);
// fallthrough
case "Polygon":
return geom.getInteriorPoint().getCoordinates();
default:
return geom.getClosestPoint(ol_extent_getCenter(geom.getExtent()));
}
};
/** Offset a polyline
* @param {Array
} coords
* @param {number} offset
* @return {Array} resulting coord
* @see http://stackoverflow.com/a/11970006/796832
* @see https://drive.google.com/viewerng/viewer?a=v&pid=sites&srcid=ZGVmYXVsdGRvbWFpbnxqa2dhZGdldHN0b3JlfGd4OjQ4MzI5M2Y0MjNmNzI2MjY
*/
var ol_coordinate_offsetCoords = function (coords, offset) {
var path = [];
var N = coords.length-1;
var max = N;
var mi, mi1, li, li1, ri, ri1, si, si1, Xi1, Yi1;
var p0, p1, p2;
var isClosed = ol_coordinate_equal(coords[0],coords[N]);
if (!isClosed) {
p0 = coords[0];
p1 = coords[1];
p2 = [
p0[0] + (p1[1] - p0[1]) / ol_coordinate_dist2d(p0,p1) *offset,
p0[1] - (p1[0] - p0[0]) / ol_coordinate_dist2d(p0,p1) *offset
];
path.push(p2);
coords.push(coords[N])
N++;
max--;
}
for (var i = 0; i < max; i++) {
p0 = coords[i];
p1 = coords[(i+1) % N];
p2 = coords[(i+2) % N];
mi = (p1[1] - p0[1])/(p1[0] - p0[0]);
mi1 = (p2[1] - p1[1])/(p2[0] - p1[0]);
// Prevent alignements
if (Math.abs(mi-mi1) > 1e-10) {
li = Math.sqrt((p1[0] - p0[0])*(p1[0] - p0[0])+(p1[1] - p0[1])*(p1[1] - p0[1]));
li1 = Math.sqrt((p2[0] - p1[0])*(p2[0] - p1[0])+(p2[1] - p1[1])*(p2[1] - p1[1]));
ri = p0[0] + offset*(p1[1] - p0[1])/li;
ri1 = p1[0] + offset*(p2[1] - p1[1])/li1;
si = p0[1] - offset*(p1[0] - p0[0])/li;
si1 = p1[1] - offset*(p2[0] - p1[0])/li1;
Xi1 = (mi1*ri1-mi*ri+si-si1) / (mi1-mi);
Yi1 = (mi*mi1*(ri1-ri)+mi1*si-mi*si1) / (mi1-mi);
// Correction for vertical lines
if(p1[0] - p0[0] == 0) {
Xi1 = p1[0] + offset*(p1[1] - p0[1])/Math.abs(p1[1] - p0[1]);
Yi1 = mi1*Xi1 - mi1*ri1 + si1;
}
if (p2[0] - p1[0] == 0 ) {
Xi1 = p2[0] + offset*(p2[1] - p1[1])/Math.abs(p2[1] - p1[1]);
Yi1 = mi*Xi1 - mi*ri + si;
}
path.push([Xi1, Yi1]);
}
}
if (isClosed) {
path.push(path[0]);
} else {
coords.pop();
p0 = coords[coords.length-1];
p1 = coords[coords.length-2];
p2 = [
p0[0] - (p1[1] - p0[1]) / ol_coordinate_dist2d(p0,p1) *offset,
p0[1] + (p1[0] - p0[0]) / ol_coordinate_dist2d(p0,p1) *offset
];
path.push(p2);
}
return path;
}
/** Find the segment a point belongs to
* @param {ol.Coordinate} pt
* @param {Array} coords
* @return {} the index (-1 if not found) and the segment
*/
var ol_coordinate_findSegment = function (pt, coords) {
for (var i=0; i} geom
* @param {number} y the y to split
* @param {number} n contour index
* @return {Array>}
*/
var ol_coordinate_splitH = function (geom, y, n) {
var x, abs;
var list = [];
for (var i=0; iy || geom[i][1]>=y && geom[i+1][1]} d1
* @param {Arrar} d2
*/
var ol_coordinate_getIntersectionPoint = function (d1, d2) {
var d1x = d1[1][0] - d1[0][0];
var d1y = d1[1][1] - d1[0][1];
var d2x = d2[1][0] - d2[0][0];
var d2y = d2[1][1] - d2[0][1];
var det = d1x * d2y - d1y * d2x;
if (det != 0) {
var k = (d1x * d1[0][1] - d1x * d2[0][1] - d1y * d1[0][0] + d1y * d2[0][0]) / det;
return [d2[0][0] + k*d2x, d2[0][1] + k*d2y];
} else {
return false;
}
};
export { ol_coordinate_getIntersectionPoint }
var ol_extent_intersection;
(function() {
// Split at x
function splitX(pts, x) {
var pt;
for (let i=pts.length-1; i>0; i--) {
if ((pts[i][0]>x && pts[i-1][0]x)) {
pt = [ x, (x - pts[i][0]) / (pts[i-1][0]-pts[i][0]) * (pts[i-1][1]-pts[i][1]) + pts[i][1]];
pts.splice(i, 0, pt);
}
}
}
// Split at y
function splitY(pts, y) {
var pt;
for (let i=pts.length-1; i>0; i--) {
if ((pts[i][1]>y && pts[i-1][1]y)) {
pt = [ (y - pts[i][1]) / (pts[i-1][1]-pts[i][1]) * (pts[i-1][0]-pts[i][0]) + pts[i][0], y];
pts.splice(i, 0, pt);
}
}
}
/** Fast polygon intersection with an extent (used for area calculation)
* @param {ol_extent_Extent} extent
* @param {ol_geom_Polygon|ol_geom_MultiPolygon} polygon
* @returns {ol_geom_Polygon|ol_geom_MultiPolygon|null} return null if not a polygon geometry
*/
ol_extent_intersection = function(extent, polygon) {
var poly = (polygon.getType() === 'Polygon');
if (!poly && polygon.getType() !== 'MultiPolygon') return null;
var geom = polygon.getCoordinates();
if (poly) geom = [geom];
geom.forEach(function(g) {
g.forEach(function(c) {
splitX(c, extent[0]);
splitX(c, extent[2]);
splitY(c, extent[1]);
splitY(c, extent[3]);
});
})
// Snap geom to the extent
geom.forEach(function(g) {
g.forEach(function(c) {
c.forEach(function(p) {
if (p[0]extent[2]) p[0] = extent[2];
if (p[1]extent[3]) p[1] = extent[3];
})
})
})
if (poly) {
return new ol_geom_Polygon(geom[0]);
} else {
return new ol_geom_MultiPolygon(geom);
}
};
})();
export { ol_extent_intersection }
export { ol_extent_intersection as extentIntersection }
/** Add points along a segment
* @param {ol_Coordinate} p1
* @param {ol_Coordinate} p2
* @param {number} d
* @param {boolean} start include starting point, default true
* @returns {Array}
*/
var ol_coordinate_sampleAt = function(p1, p2, d, start) {
var pts = [];
if (start!==false) pts.push(p1);
var dl = ol_coordinate_dist2d(p1,p2);
if (dl) {
var nb = Math.round(dl/d);
if (nb>1) {
var dx = (p2[0]-p1[0]) / nb;
var dy = (p2[1]-p1[1]) / nb;
for (var i=1; i r) {
hasout = true;
l.push([
c[0] + r / d * (p[0]-c[0]),
c[1] + r / d * (p[1]-c[1])
]);
} else {
// hasin = true;
l.push(p);
}
});
})
});
if (!hasout) return geom;
if (geom.getType() === 'Polygon') {
return new ol_geom_Polygon(result[0]);
} else {
return new ol_geom_MultiPolygon(result);
}
}
}
} else {
console.warn('[ol/geom/Circle~intersection] Unsupported geometry type: '+geom.getType());
}
return geom;
};