ol-ext
Version:
A set of cool extensions for OpenLayers (ol) in node modules structure
153 lines (141 loc) • 4.92 kB
JavaScript
/* 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
*/
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
import ol_geom_MultiLineString from 'ol/geom/MultiLineString.js'
import ol_geom_Polygon from 'ol/geom/Polygon.js'
import ol_geom_MultiPolygon from 'ol/geom/MultiPolygon.js'
import '../render/Cspline.js'
import { ol_coordinate_splitH } from "./GeomUtils.js";
/**
* Calculate a MultiPolyline to fill a Polygon with a scribble effect that appears hand-made
* @param {} options
* @param {Number} options.interval interval beetween lines
* @param {Number} options.angle hatch angle in radian, default PI/2
* @return {ol_geom_MultiLineString|null} the resulting MultiLineString geometry or null if none
*/
ol_geom_MultiPolygon.prototype.scribbleFill = function (options) {
var scribbles = [];
var poly = this.getPolygons();
var i, p, s;
for (i=0; p=poly[i]; i++) {
var mls = p.scribbleFill(options);
if (mls) scribbles.push(mls);
}
if (!scribbles.length) return null;
// Merge scribbles
var scribble = scribbles[0];
var ls;
for (i = 0; s = scribbles[i]; i++) {
ls = s.getLineStrings();
for (var k = 0; k < ls.length; k++) {
scribble.appendLineString(ls[k]);
}
}
return scribble;
};
/**
* Calculate a MultiPolyline to fill a Polygon with a scribble effect that appears hand-made
* @param {} options
* @param {Number} options.interval interval beetween lines
* @param {Number} options.angle hatch angle in radian, default PI/2
* @return {ol_geom_MultiLineString|null} the resulting MultiLineString geometry or null if none
*/
ol_geom_Polygon.prototype.scribbleFill = function (options) {
var step = options.interval;
var angle = options.angle || Math.PI/2;
var i, k,l;
// Geometry + rotate
var geom = this.clone();
geom.rotate(angle, [0,0]);
var coords = geom.getCoordinates();
// Merge holes
var coord = coords[0];
for (i=1; i<coords.length; i++) {
// Add a separator
coord.push([]);
// Add the hole
coord = coord.concat(coords[i]);
}
// Extent
var ext = geom.getExtent();
// Split polygon with horizontal lines
var lines = [];
for (var y = (Math.floor(ext[1]/step)+1)*step; y<ext[3]; y += step) {
l = ol_coordinate_splitH(coord, y, i);
lines = lines.concat(l);
}
if (!lines.length) return null;
// Order lines on segment index
var mod = coord.length-1;
var first = lines[0][0].index;
for (k=0; l=lines[k]; k++) {
lines[k][0].index = (lines[k][0].index-first+mod) % mod;
lines[k][1].index = (lines[k][1].index-first+mod) % mod;
}
var scribble = [];
while (true) {
for (k=0; l=lines[k]; k++) {
if (!l[0].done) break;
}
if (!l) break;
var scrib = [];
while (l) {
l[0].done = true;
scrib.push(l[0].pt);
scrib.push(l[1].pt);
var nexty = l[0].pt[1] + step;
var d0 = Infinity;
var l2 = null;
while (lines[k]) {
if (lines[k][0].pt[1] > nexty) break;
if (lines[k][0].pt[1] === nexty) {
var d = Math.min(
(lines[k][0].index - l[0].index + mod) % mod,
(l[0].index - lines[k][0].index + mod) % mod
);
var d2 = Math.min(
(l[1].index - l[0].index + mod) % mod,
(l[0].index - l[1].index + mod) % mod
);
if (d<d0 && d<d2) {
d0 = d;
if (!lines[k][0].done) l2 = lines[k];
else l2 = null;
}
}
k++;
}
l = l2;
}
if (scrib.length) {
scribble.push(scrib);
}
}
// Return the scribble as MultiLineString
if (!scribble.length) return null;
var mline = new ol_geom_MultiLineString(scribble);
mline.rotate(-angle,[0,0]);
return mline.cspline({ pointsPerSeg:8, tension:.9 });
};
/** Calculate a MultiPolyline to fill a geomatry (Polygon or MultiPolygon) with a scribble effect that appears hand-made
* @param {ol_geom_Geometry} geom the geometry to scribble
* @param {Object} options
* @param {Number} options.interval interval beetween lines
* @param {Number} options.angle hatch angle in radian, default PI/2
* @return {ol_geom_Geometry} the resulting MultiLineString geometry or initial geometry
*/
var ol_geom_scribbleFill = function(geom, options) {
switch (geom.getType()) {
case 'Polygon': {
return ol_geom_Polygon.prototype.scribbleFill.call(geom, options)
}
case 'MultiPolygon': {
return ol_geom_MultiPolygon.prototype.scribbleFill.call(geom, options)
}
default: return geom
}
}
export default ol_geom_scribbleFill