d3-geo-voronoi
Advanced tools
Comparing version 1.0.2 to 1.1.0
@@ -1,2 +0,2 @@ | ||
// https://github.com/Fil/d3-geo-voronoi Version 1.0.2. Copyright 2018 Philippe Riviere. | ||
// https://github.com/Fil/d3-geo-voronoi Version 1.1.0. Copyright 2018 Philippe Riviere. | ||
(function (global, factory) { | ||
@@ -11,4 +11,4 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-delaunay'), require('d3-geo'), require('d3-array')) : | ||
var tau = pi * 2; | ||
var degrees = 180 / pi; | ||
@@ -95,6 +95,12 @@ var radians = pi / 180; | ||
// Spherical excess of a triangle (in spherical coordinates) | ||
function excess(triangle) { | ||
triangle = triangle.map(p => cartesian(p)); | ||
return cartesianDot(triangle[0], cartesianCross(triangle[2], triangle[1])); | ||
} | ||
function geoDelaunay(points) { | ||
const delaunay = geo_delaunay_from(points), | ||
edges = geo_edges(delaunay, points.length), | ||
triangles = geo_triangles(delaunay, points.length), | ||
edges = geo_edges(triangles, points), | ||
neighbors = geo_neighbors(triangles, points.length), | ||
@@ -106,3 +112,3 @@ find = geo_find(neighbors, points), | ||
mesh = geo_mesh(polygons), | ||
hull = geo_hull(triangles,points), | ||
hull = geo_hull(triangles, points), | ||
// Urquhart ; returns a function that takes a distance array as argument. | ||
@@ -182,19 +188,13 @@ urquhart = geo_urquhart(edges, triangles); | ||
function geo_edges(delaunay, npoints) { | ||
const geo_edges = [], | ||
halfedges = delaunay.halfedges, | ||
triangles = delaunay.triangles, | ||
seen = {}; | ||
if (!halfedges) return geo_edges; | ||
for (let i = 0, n = halfedges.length; i < n; ++i) { | ||
const j = halfedges[i]; | ||
if (j < i) continue; | ||
let [a, b] = d3Array.extent([triangles[i], triangles[j]]); | ||
if (b >= npoints && a < npoints) (b = a), (a = 0); | ||
if (b > 0 && b < npoints && (a > 0 || (!seen[b]++ && (seen[b] = true)))) | ||
geo_edges.push([a, b]); | ||
} | ||
return geo_edges; | ||
function geo_edges(triangles, points) { | ||
const _index = {}; | ||
if (points.length === 2) return [[0, 1]]; | ||
triangles.forEach(tri => { | ||
if (excess(tri.map(i => points[i])) < 0) return; | ||
for (let i = 0, j; i < 3; i++) { | ||
j = (i + 1) % 3; | ||
_index[d3Array.extent([tri[i], tri[j]]).join("-")] = true; | ||
} | ||
}); | ||
return Object.keys(_index).map(d => d.split("-").map(Number)); | ||
} | ||
@@ -396,3 +396,2 @@ | ||
function geo_hull(triangles, points) { | ||
@@ -402,10 +401,3 @@ const _hull = {}, | ||
triangles.map(tri => { | ||
const p = { | ||
type: "Polygon", | ||
coordinates: [ | ||
[points[tri[0]], points[tri[1]], points[tri[2]], points[tri[0]]] | ||
] | ||
}; | ||
if (d3Geo.geoArea(p) > tau) return; | ||
if (excess(tri.map(i => points[i > points.length ? 0 : i])) < 0) return; | ||
for (let i = 0; i < 3; i++) { | ||
@@ -519,20 +511,18 @@ let e = [tri[i], tri[(i + 1) % 3]], | ||
features: v.delaunay.triangles | ||
.map((tri, i) => ({ | ||
.map((tri, index) => { | ||
tri = tri.map(i => v.points[i]); | ||
tri.center = v.delaunay.centers[index]; | ||
return tri; | ||
}) | ||
.filter(tri => excess(tri) > 0) | ||
.map(tri => ({ | ||
type: "Feature", | ||
properties: { | ||
circumcenter: v.delaunay.centers[i] | ||
circumcenter: tri.center | ||
}, | ||
geometry: { | ||
type: "Polygon", | ||
coordinates: [ | ||
[ | ||
v.points[tri[0]], | ||
v.points[tri[1]], | ||
v.points[tri[2]], | ||
v.points[tri[0]] | ||
] | ||
] | ||
coordinates: [[...tri, tri[0]]] | ||
} | ||
})) | ||
.filter(d => d3Geo.geoArea(d) <= tau) | ||
}; | ||
@@ -539,0 +529,0 @@ }; |
@@ -1,1 +0,1 @@ | ||
(function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("d3-delaunay"),require("d3-geo"),require("d3-array")):"function"==typeof define&&define.amd?define(["exports","d3-delaunay","d3-geo","d3-array"],t):t(e.d3=e.d3||{},e.d3,e.d3,e.d3)})(this,function(e,t,n,o){"use strict";var r=Math.PI,a=r/2,u=2*r,i=180/r,l=r/180,s=Math.atan2,c=Math.cos,f=Math.max,p=Math.min,d=Math.sin,h=Math.sign||function(e){return e>0?1:e<0?-1:0},g=Math.sqrt;function y(e,t){return[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]]}function m(e,t){return[e[0]+t[0],e[1]+t[1],e[2]+t[2]]}function v(e){var t=g(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);return[e[0]/t,e[1]/t,e[2]/t]}function _(e){return[s(e[1],e[0])*i,(t=f(-1,p(1,e[2])),(t>1?a:t<-1?-a:Math.asin(t))*i)];var t}function b(e){var t=e[0]*l,n=e[1]*l,o=c(n);return[o*c(t),o*d(t),d(n)]}function M(e){const a=function(e){if(e.length<2)return{};const o=n.geoRotation(e[0]),a=n.geoStereographic().translate([0,0]).scale(1).rotate(o.invert([180,0])),u=[0];let i=1;for(let t=1,n=(e=e.map(a)).length;t<n;t++){let n=e[t][0]*e[t][0]+e[t][1]*e[t][1];isNaN(n)&&u.push(t),n>i&&(i=n)}const l=1e6*g(i);u.forEach((t,n)=>e[n]=[l/2,0]);for(let t=0;t<4;t++)e.push([l*c(t/2*r),l*d(t/2*r)]);const s=t.Delaunay.from(e);return s.projection=a,s}(e),i=function(e,t){const n=[],r=e.halfedges,a=e.triangles,u={};if(!r)return n;for(let e=0,i=r.length;e<i;++e){const i=r[e];if(i<e)continue;let[l,s]=o.extent([a[e],a[i]]);s>=t&&l<t&&(s=l,l=0),s>0&&s<t&&(l>0||!u[s]++&&(u[s]=!0))&&n.push([l,s])}return n}(a,e.length),l=function(e,t){if(!e.triangles)return[];const n=e.triangles.slice().map(e=>e>=t?0:e),o=[];for(let e=0,t=n.length/3;e<t;e++){const t=n[3*e],r=n[3*e+1],a=n[3*e+2];t!==r&&r!==a&&a!==t&&o.push([t,a,r])}return o}(a,e.length),s=function(e,t){const n=[];e.forEach((e,t)=>{for(let t=0;t<3;t++){const o=e[t],r=e[(t+1)%3];n[o]=n[o]||[],n[o].push(r)}}),0===e.length&&(2===t?(n[0]=[1],n[1]=[0]):1===t&&(n[0]=[]));return n}(l,e.length),f=function(e,t){return function(o,r,a){let u,i,l=0;void 0===a&&(a=0);do{u=a,a=null,i=n.geoDistance([o,r],t[u]),e[u].forEach(e=>{let u=n.geoDistance([o,r],t[e]);if(u<i)return i=u,a=e,void(l=e)})}while(null!==a);return l}}(s,e),p=function(e,t){return e.map(e=>{const n=e.map(e=>t[e]).map(b),o=m(m(y(n[1],n[0]),y(n[2],n[1])),y(n[0],n[2]));return _(v(o))})}(l,e),{polygons:h,centers:M}=function(e,t,n){const o=[],r=e.slice();if(0===t.length){if(n.length<2)return{polygons:o,centers:r};if(2===n.length){const e=b(n[0]),t=b(n[1]),u=v(m(e,t)),i=v(y(e,t)),l=y(u,i),s=[u,y(u,l),y(y(u,l),l),y(y(y(u,l),l),l)].map(_).map(a);return o.push(s),o.push(s.slice().reverse()),{polygons:o,centers:r}}}function a(e){let n=-1;return r.slice(t.length,1/0).forEach((o,r)=>{o[0]===e[0]&&o[1]===e[1]&&(n=r+t.length)}),n<0&&(n=r.length,r.push(e)),n}return t.forEach((e,t)=>{for(let n=0;n<3;n++){const r=e[n],a=e[(n+1)%3],u=e[(n+2)%3];o[r]=o[r]||[],o[r].push([a,u,t,[r,a,u]])}}),{polygons:o.map(e=>{const t=[e[0][2]];let o=e[0][1];for(let n=1;n<e.length;n++)for(let n=0;n<e.length;n++)if(e[n][0]==o){o=e[n][1],t.push(e[n][2]);break}if(t.length>2)return t;if(2==t.length){const o=j(n[e[0][3][0]],n[e[0][3][1]],r[t[0]]),u=j(n[e[0][3][2]],n[e[0][3][0]],r[t[0]]),i=a(o),l=a(u);return[t[0],l,t[1],i]}console&&console.warn({here:"unreachable",poly:e})}),centers:r}}(p,l,e);return{delaunay:a,edges:i,triangles:l,centers:M,neighbors:s,polygons:h,mesh:function(e){const t=[];return e.forEach(e=>{if(!e)return;let n=e[e.length-1];for(let o of e)o>n&&t.push([n,o]),n=o}),t}(h),hull:function(e,t){const o={},r=[];e.map(e=>{const r={type:"Polygon",coordinates:[[t[e[0]],t[e[1]],t[e[2]],t[e[0]]]]};if(!(n.geoArea(r)>u))for(let t=0;t<3;t++){let n=[e[t],e[(t+1)%3]],r=`${n[1]}-${n[0]}`;o[r]?delete o[r]:o[n.join("-")]=!0}});const a={};let i;if(Object.keys(o).forEach(e=>{e=e.split("-").map(Number),a[e[0]]=e[1],i=e[0]}),void 0===i)return r;let l=i;do{r.push(l),l=a[l]}while(l!==i);return r}(l,e),urquhart:function(e,t){return function(n){const r={},a={};return e.forEach((e,t)=>{const o=e.join("-");r[o]=n[t],a[o]=!0}),t.forEach(e=>{let t=0,n=-1;for(var u=0;u<3;u++){let a=o.extent([e[u],e[(u+1)%3]]).join("-");r[a]>t&&(t=r[a],n=a)}a[n]=!1}),e.map(e=>a[e.join("-")])}}(i,l),find:f}}function j(e,t,n){e=b(e),t=b(t),n=b(n);const o=h(function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]}(y(t,e),n));return _(v(m(e,t)).map(e=>o*e))}e.geoDelaunay=M,e.geoVoronoi=function(e){const t=function(e){return t.delaunay=null,t._data=e,"object"==typeof t._data&&"FeatureCollection"===t._data.type&&(t._data=t._data.features),"object"==typeof t._data&&(t.points=t._data.map(e=>[t._vx(e),t._vy(e)]),t.delaunay=M(t.points)),t};return t._vx=function(e){return"object"==typeof e&&"type"in e?n.geoCentroid(e)[0]:0 in e?e[0]:void 0},t._vy=function(e){return"object"==typeof e&&"type"in e?n.geoCentroid(e)[1]:1 in e?e[1]:void 0},t.x=function(e){return e?(t._vx=e,t):t._vx},t.y=function(e){return e?(t._vy=e,t):t._vy},t.polygons=function(e){return void 0!==e&&t(e),!!t.delaunay&&(0===t._data.length?null:1===t._data.length?{type:"Sphere"}:{type:"FeatureCollection",features:t.delaunay.polygons.map((e,n)=>({type:"Feature",geometry:e?{type:"Polygon",coordinates:[[...e,e[0]].map(e=>t.delaunay.centers[e])]}:null,properties:{site:t._data[n],sitecoordinates:t.points[n],neighbours:t.delaunay.neighbors[n]}}))})},t.triangles=function(e){return void 0!==e&&t(e),!!t.delaunay&&{type:"FeatureCollection",features:t.delaunay.triangles.map((e,n)=>({type:"Feature",properties:{circumcenter:t.delaunay.centers[n]},geometry:{type:"Polygon",coordinates:[[t.points[e[0]],t.points[e[1]],t.points[e[2]],t.points[e[0]]]]}})).filter(e=>n.geoArea(e)<=u)}},t.links=function(e){if(void 0!==e&&t(e),!t.delaunay)return!1;const o=t.delaunay.edges.map(e=>n.geoDistance(t.points[e[0]],t.points[e[1]])),r=t.delaunay.urquhart(o);return{type:"FeatureCollection",features:t.delaunay.edges.map((e,n)=>({type:"Feature",properties:{source:t._data[e[0]],target:t._data[e[1]],length:o[n],urquhart:!!r[n]},geometry:{type:"LineString",coordinates:[t.points[e[0]],t.points[e[1]]]}}))}},t.mesh=function(e){return void 0!==e&&t(e),!!t.delaunay&&{type:"MultiLineString",coordinates:t.delaunay.edges.map(e=>[t.points[e[0]],t.points[e[1]]])}},t.cellMesh=function(e){if(void 0!==e&&t(e),!t.delaunay)return!1;const{centers:n,polygons:o}=t.delaunay,r=[];for(const e of o)if(e)for(let t=e.length,o=e[t-1],a=e[0],u=0;u<t;o=a,a=e[++u])a>o&&r.push([n[o],n[a]]);return{type:"MultiLineString",coordinates:r}},t._found=void 0,t.find=function(e,o,r){if(t._found=t.delaunay.find(e,o,t._found),!r||n.geoDistance([e,o],t.points[t._found])<r)return t._found},t.hull=function(e){void 0!==e&&t(e);const n=t.delaunay.hull,o=t.points;return 0===n.length?null:{type:"Polygon",coordinates:[[...n.map(e=>o[e]),o[n[0]]]]}},e?t(e):t},Object.defineProperty(e,"__esModule",{value:!0})}); | ||
(function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("d3-delaunay"),require("d3-geo"),require("d3-array")):"function"==typeof define&&define.amd?define(["exports","d3-delaunay","d3-geo","d3-array"],t):t(e.d3=e.d3||{},e.d3,e.d3,e.d3)})(this,function(e,t,n,o){"use strict";var r=Math.PI,a=r/2,u=180/r,i=r/180,l=Math.atan2,s=Math.cos,c=Math.max,f=Math.min,p=Math.sin,d=Math.sign||function(e){return e>0?1:e<0?-1:0},h=Math.sqrt;function y(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]}function g(e,t){return[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]]}function m(e,t){return[e[0]+t[0],e[1]+t[1],e[2]+t[2]]}function v(e){var t=h(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);return[e[0]/t,e[1]/t,e[2]/t]}function _(e){return[l(e[1],e[0])*u,(t=c(-1,f(1,e[2])),(t>1?a:t<-1?-a:Math.asin(t))*u)];var t}function b(e){var t=e[0]*i,n=e[1]*i,o=s(n);return[o*s(t),o*p(t),p(n)]}function j(e){return y((e=e.map(e=>b(e)))[0],g(e[2],e[1]))}function M(e){const a=function(e){if(e.length<2)return{};const o=n.geoRotation(e[0]),a=n.geoStereographic().translate([0,0]).scale(1).rotate(o.invert([180,0])),u=[0];let i=1;for(let t=1,n=(e=e.map(a)).length;t<n;t++){let n=e[t][0]*e[t][0]+e[t][1]*e[t][1];isNaN(n)&&u.push(t),n>i&&(i=n)}const l=1e6*h(i);u.forEach((t,n)=>e[n]=[l/2,0]);for(let t=0;t<4;t++)e.push([l*s(t/2*r),l*p(t/2*r)]);const c=t.Delaunay.from(e);return c.projection=a,c}(e),u=function(e,t){if(!e.triangles)return[];const n=e.triangles.slice().map(e=>e>=t?0:e),o=[];for(let e=0,t=n.length/3;e<t;e++){const t=n[3*e],r=n[3*e+1],a=n[3*e+2];t!==r&&r!==a&&a!==t&&o.push([t,a,r])}return o}(a,e.length),i=function(e,t){const n={};return 2===t.length?[[0,1]]:(e.forEach(e=>{if(!(j(e.map(e=>t[e]))<0))for(let t,r=0;r<3;r++)t=(r+1)%3,n[o.extent([e[r],e[t]]).join("-")]=!0}),Object.keys(n).map(e=>e.split("-").map(Number)))}(u,e),l=function(e,t){const n=[];e.forEach((e,t)=>{for(let t=0;t<3;t++){const o=e[t],r=e[(t+1)%3];n[o]=n[o]||[],n[o].push(r)}}),0===e.length&&(2===t?(n[0]=[1],n[1]=[0]):1===t&&(n[0]=[]));return n}(u,e.length),c=function(e,t){return function(o,r,a){let u,i,l=0;void 0===a&&(a=0);do{u=a,a=null,i=n.geoDistance([o,r],t[u]),e[u].forEach(e=>{let u=n.geoDistance([o,r],t[e]);if(u<i)return i=u,a=e,void(l=e)})}while(null!==a);return l}}(l,e),f=function(e,t){return e.map(e=>{const n=e.map(e=>t[e]).map(b),o=m(m(g(n[1],n[0]),g(n[2],n[1])),g(n[0],n[2]));return _(v(o))})}(u,e),{polygons:d,centers:y}=function(e,t,n){const o=[],r=e.slice();if(0===t.length){if(n.length<2)return{polygons:o,centers:r};if(2===n.length){const e=b(n[0]),t=b(n[1]),u=v(m(e,t)),i=v(g(e,t)),l=g(u,i),s=[u,g(u,l),g(g(u,l),l),g(g(g(u,l),l),l)].map(_).map(a);return o.push(s),o.push(s.slice().reverse()),{polygons:o,centers:r}}}function a(e){let n=-1;return r.slice(t.length,1/0).forEach((o,r)=>{o[0]===e[0]&&o[1]===e[1]&&(n=r+t.length)}),n<0&&(n=r.length,r.push(e)),n}return t.forEach((e,t)=>{for(let n=0;n<3;n++){const r=e[n],a=e[(n+1)%3],u=e[(n+2)%3];o[r]=o[r]||[],o[r].push([a,u,t,[r,a,u]])}}),{polygons:o.map(e=>{const t=[e[0][2]];let o=e[0][1];for(let n=1;n<e.length;n++)for(let n=0;n<e.length;n++)if(e[n][0]==o){o=e[n][1],t.push(e[n][2]);break}if(t.length>2)return t;if(2==t.length){const o=x(n[e[0][3][0]],n[e[0][3][1]],r[t[0]]),u=x(n[e[0][3][2]],n[e[0][3][0]],r[t[0]]),i=a(o),l=a(u);return[t[0],l,t[1],i]}console&&console.warn({here:"unreachable",poly:e})}),centers:r}}(f,u,e);return{delaunay:a,edges:i,triangles:u,centers:y,neighbors:l,polygons:d,mesh:function(e){const t=[];return e.forEach(e=>{if(!e)return;let n=e[e.length-1];for(let o of e)o>n&&t.push([n,o]),n=o}),t}(d),hull:function(e,t){const n={},o=[];e.map(e=>{if(!(j(e.map(e=>t[e>t.length?0:e]))<0))for(let t=0;t<3;t++){let o=[e[t],e[(t+1)%3]],r=`${o[1]}-${o[0]}`;n[r]?delete n[r]:n[o.join("-")]=!0}});const r={};let a;if(Object.keys(n).forEach(e=>{e=e.split("-").map(Number),r[e[0]]=e[1],a=e[0]}),void 0===a)return o;let u=a;do{o.push(u),u=r[u]}while(u!==a);return o}(u,e),urquhart:function(e,t){return function(n){const r={},a={};return e.forEach((e,t)=>{const o=e.join("-");r[o]=n[t],a[o]=!0}),t.forEach(e=>{let t=0,n=-1;for(var u=0;u<3;u++){let a=o.extent([e[u],e[(u+1)%3]]).join("-");r[a]>t&&(t=r[a],n=a)}a[n]=!1}),e.map(e=>a[e.join("-")])}}(i,u),find:c}}function x(e,t,n){e=b(e),t=b(t),n=b(n);const o=d(y(g(t,e),n));return _(v(m(e,t)).map(e=>o*e))}e.geoDelaunay=M,e.geoVoronoi=function(e){const t=function(e){return t.delaunay=null,t._data=e,"object"==typeof t._data&&"FeatureCollection"===t._data.type&&(t._data=t._data.features),"object"==typeof t._data&&(t.points=t._data.map(e=>[t._vx(e),t._vy(e)]),t.delaunay=M(t.points)),t};return t._vx=function(e){return"object"==typeof e&&"type"in e?n.geoCentroid(e)[0]:0 in e?e[0]:void 0},t._vy=function(e){return"object"==typeof e&&"type"in e?n.geoCentroid(e)[1]:1 in e?e[1]:void 0},t.x=function(e){return e?(t._vx=e,t):t._vx},t.y=function(e){return e?(t._vy=e,t):t._vy},t.polygons=function(e){return void 0!==e&&t(e),!!t.delaunay&&(0===t._data.length?null:1===t._data.length?{type:"Sphere"}:{type:"FeatureCollection",features:t.delaunay.polygons.map((e,n)=>({type:"Feature",geometry:e?{type:"Polygon",coordinates:[[...e,e[0]].map(e=>t.delaunay.centers[e])]}:null,properties:{site:t._data[n],sitecoordinates:t.points[n],neighbours:t.delaunay.neighbors[n]}}))})},t.triangles=function(e){return void 0!==e&&t(e),!!t.delaunay&&{type:"FeatureCollection",features:t.delaunay.triangles.map((e,n)=>((e=e.map(e=>t.points[e])).center=t.delaunay.centers[n],e)).filter(e=>j(e)>0).map(e=>({type:"Feature",properties:{circumcenter:e.center},geometry:{type:"Polygon",coordinates:[[...e,e[0]]]}}))}},t.links=function(e){if(void 0!==e&&t(e),!t.delaunay)return!1;const o=t.delaunay.edges.map(e=>n.geoDistance(t.points[e[0]],t.points[e[1]])),r=t.delaunay.urquhart(o);return{type:"FeatureCollection",features:t.delaunay.edges.map((e,n)=>({type:"Feature",properties:{source:t._data[e[0]],target:t._data[e[1]],length:o[n],urquhart:!!r[n]},geometry:{type:"LineString",coordinates:[t.points[e[0]],t.points[e[1]]]}}))}},t.mesh=function(e){return void 0!==e&&t(e),!!t.delaunay&&{type:"MultiLineString",coordinates:t.delaunay.edges.map(e=>[t.points[e[0]],t.points[e[1]]])}},t.cellMesh=function(e){if(void 0!==e&&t(e),!t.delaunay)return!1;const{centers:n,polygons:o}=t.delaunay,r=[];for(const e of o)if(e)for(let t=e.length,o=e[t-1],a=e[0],u=0;u<t;o=a,a=e[++u])a>o&&r.push([n[o],n[a]]);return{type:"MultiLineString",coordinates:r}},t._found=void 0,t.find=function(e,o,r){if(t._found=t.delaunay.find(e,o,t._found),!r||n.geoDistance([e,o],t.points[t._found])<r)return t._found},t.hull=function(e){void 0!==e&&t(e);const n=t.delaunay.hull,o=t.points;return 0===n.length?null:{type:"Polygon",coordinates:[[...n.map(e=>o[e]),o[n[0]]]]}},e?t(e):t},Object.defineProperty(e,"__esModule",{value:!0})}); |
{ | ||
"name": "d3-geo-voronoi", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"description": "Spherical Voronoi Diagram and Delaunay Triangulation", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -9,6 +9,18 @@ // | ||
import { Delaunay } from "d3-delaunay"; | ||
import { geoArea, geoDistance, geoRotation, geoStereographic } from "d3-geo"; | ||
import { geoDistance, geoRotation, geoStereographic } from "d3-geo"; | ||
import { extent } from "d3-array"; | ||
import { asin, atan2, cos, degrees, max, min, pi, radians, sign, sin, sqrt, tau } from "./math.js"; | ||
import { | ||
asin, | ||
atan2, | ||
cos, | ||
degrees, | ||
max, | ||
min, | ||
pi, | ||
radians, | ||
sign, | ||
sin, | ||
sqrt | ||
} from "./math.js"; | ||
import { | ||
cartesianNormalize as normalize, | ||
@@ -36,6 +48,12 @@ cartesianCross as cross, | ||
// Spherical excess of a triangle (in spherical coordinates) | ||
export function excess(triangle) { | ||
triangle = triangle.map(p => cartesian(p)); | ||
return dot(triangle[0], cross(triangle[2], triangle[1])); | ||
} | ||
export function geoDelaunay(points) { | ||
const delaunay = geo_delaunay_from(points), | ||
edges = geo_edges(delaunay, points.length), | ||
triangles = geo_triangles(delaunay, points.length), | ||
edges = geo_edges(triangles, points), | ||
neighbors = geo_neighbors(triangles, points.length), | ||
@@ -47,3 +65,3 @@ find = geo_find(neighbors, points), | ||
mesh = geo_mesh(polygons), | ||
hull = geo_hull(triangles,points), | ||
hull = geo_hull(triangles, points), | ||
// Urquhart ; returns a function that takes a distance array as argument. | ||
@@ -123,19 +141,13 @@ urquhart = geo_urquhart(edges, triangles); | ||
function geo_edges(delaunay, npoints) { | ||
const geo_edges = [], | ||
halfedges = delaunay.halfedges, | ||
triangles = delaunay.triangles, | ||
seen = {}; | ||
if (!halfedges) return geo_edges; | ||
for (let i = 0, n = halfedges.length; i < n; ++i) { | ||
const j = halfedges[i]; | ||
if (j < i) continue; | ||
let [a, b] = extent([triangles[i], triangles[j]]); | ||
if (b >= npoints && a < npoints) (b = a), (a = 0); | ||
if (b > 0 && b < npoints && (a > 0 || (!seen[b]++ && (seen[b] = true)))) | ||
geo_edges.push([a, b]); | ||
} | ||
return geo_edges; | ||
function geo_edges(triangles, points) { | ||
const _index = {}; | ||
if (points.length === 2) return [[0, 1]]; | ||
triangles.forEach(tri => { | ||
if (excess(tri.map(i => points[i])) < 0) return; | ||
for (let i = 0, j; i < 3; i++) { | ||
j = (i + 1) % 3; | ||
_index[extent([tri[i], tri[j]]).join("-")] = true; | ||
} | ||
}); | ||
return Object.keys(_index).map(d => d.split("-").map(Number)); | ||
} | ||
@@ -340,3 +352,2 @@ | ||
function geo_hull(triangles, points) { | ||
@@ -346,10 +357,3 @@ const _hull = {}, | ||
triangles.map(tri => { | ||
const p = { | ||
type: "Polygon", | ||
coordinates: [ | ||
[points[tri[0]], points[tri[1]], points[tri[2]], points[tri[0]]] | ||
] | ||
}; | ||
if (geoArea(p) > tau) return; | ||
if (excess(tri.map(i => points[i > points.length ? 0 : i])) < 0) return; | ||
for (let i = 0; i < 3; i++) { | ||
@@ -380,2 +384,2 @@ let e = [tri[i], tri[(i + 1) % 3]], | ||
return hull; | ||
} | ||
} |
@@ -9,4 +9,4 @@ // | ||
import { extent } from "d3-array"; | ||
import { geoArea, geoCentroid, geoDistance } from "d3-geo"; | ||
import { geoDelaunay } from "./delaunay.js"; | ||
import { geoCentroid, geoDistance } from "d3-geo"; | ||
import { geoDelaunay, excess } from "./delaunay.js"; | ||
import { tau } from "./math.js"; | ||
@@ -88,20 +88,18 @@ | ||
features: v.delaunay.triangles | ||
.map((tri, i) => ({ | ||
.map((tri, index) => { | ||
tri = tri.map(i => v.points[i]); | ||
tri.center = v.delaunay.centers[index]; | ||
return tri; | ||
}) | ||
.filter(tri => excess(tri) > 0) | ||
.map(tri => ({ | ||
type: "Feature", | ||
properties: { | ||
circumcenter: v.delaunay.centers[i] | ||
circumcenter: tri.center | ||
}, | ||
geometry: { | ||
type: "Polygon", | ||
coordinates: [ | ||
[ | ||
v.points[tri[0]], | ||
v.points[tri[1]], | ||
v.points[tri[2]], | ||
v.points[tri[0]] | ||
] | ||
] | ||
coordinates: [[...tri, tri[0]]] | ||
} | ||
})) | ||
.filter(d => geoArea(d) <= tau) | ||
}; | ||
@@ -108,0 +106,0 @@ }; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
0
57050
1124