diff --git a/README.md b/README.md index b45d9bd..93b7d60 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,19 @@ The cubic projection. [](https://observablehq.com/@fil/dodecahedral-projection) -The dodecahedral projection. +The pentagonal dodecahedral projection. + +# d3.geoRhombicDodecahedral() · [Source](https://github.com/d3/d3-geo-polygon/blob/main/src/polyhedral/rhombic.js), [Examples](https://observablehq.com/d/881a8431e638b408) + +[](https://observablehq.com/d/881a8431e638b408) + +The rhombic dodecahedral projection. + +# d3.geoDeltoidalHexecontahedral() · [Source](https://github.com/d3/d3-geo-polygon/blob/main/src/polyhedral/deltoidal.js), [Examples](https://observablehq.com/d/881a8431e638b408) + +[](https://observablehq.com/d/881a8431e638b408) + +The deltoidal hexecontahedral projection. # d3.geoIcosahedral() · [Source](https://github.com/d3/d3-geo-polygon/blob/main/src/icosahedral.js), [Examples](https://observablehq.com/@fil/icosahedral-projections) diff --git a/src/deltoidal.js b/src/deltoidal.js index 0c0deb7..bfc8203 100644 --- a/src/deltoidal.js +++ b/src/deltoidal.js @@ -8,16 +8,19 @@ */ import { atan, degrees } from "./math.js"; import voronoi from "./polyhedral/voronoi.js"; +import { geoCentroid, geoInterpolate } from "d3-geo"; - -export default function() { +export default function () { var theta = atan(0.5) * degrees; // construction inspired by // https://en.wikipedia.org/wiki/Regular_icosahedron#Spherical_coordinates - var vertices = [[0, 90], [0, -90]].concat( - [0,1,2,3,4,5,6,7,8,9].map(function(i) { - var phi = (i * 36 + 180) % 360 - 180; + var vertices = [ + [0, 90], + [0, -90], + ].concat( + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(function (i) { + var phi = ((i * 36 + 180) % 360) - 180; return [phi, i & 1 ? theta : -theta]; }) ); @@ -43,126 +46,120 @@ export default function() { [1, 4, 6], [1, 6, 8], [1, 8, 10], - [1, 10, 2] // South - ].map(function(face) { - var t = face.map(function(i) { + [1, 10, 2], // South + ].map(function (face) { + var t = face.map(function (i) { return vertices[i]; }); // create 3 polygons from these using centroid and midpoints var f1 = [ - t[0], - d3.geoInterpolate(t[0],t[1])(0.5), - d3.geoCentroid({type:"MultiPoint", coordinates:t}), - d3.geoInterpolate(t[0],t[2])(0.5) + t[0], + geoInterpolate(t[0], t[1])(0.5), + geoCentroid({ type: "MultiPoint", coordinates: t }), + geoInterpolate(t[0], t[2])(0.5), ]; var f2 = [ - t[1], - d3.geoInterpolate(t[1],t[2])(0.5), - d3.geoCentroid({type:"MultiPoint", coordinates:t}), - d3.geoInterpolate(t[1],t[0])(0.5) + t[1], + geoInterpolate(t[1], t[2])(0.5), + geoCentroid({ type: "MultiPoint", coordinates: t }), + geoInterpolate(t[1], t[0])(0.5), ]; var f3 = [ - t[2], - d3.geoInterpolate(t[2],t[0])(0.5), - d3.geoCentroid({type:"MultiPoint", coordinates:t}), - d3.geoInterpolate(t[2],t[1])(0.5) + t[2], + geoInterpolate(t[2], t[0])(0.5), + geoCentroid({ type: "MultiPoint", coordinates: t }), + geoInterpolate(t[2], t[1])(0.5), ]; return [f1, f2, f3]; }); var polygons = { type: "FeatureCollection", - features: polyhedron.flat().map(function(face) { - face.push(face[0]); + features: polyhedron.flat().map(function (face) { return { - properties: { sitecoordinates: d3.geoCentroid({type:"MultiPoint", coordinates: face}) }, + properties: { + sitecoordinates: geoCentroid({ + type: "MultiPoint", + coordinates: face, + }), + }, geometry: { type: "Polygon", - coordinates: [ face ] - } + coordinates: [[...face, face[0]]], + }, }; - }) + }), }; var parents = [ - -1, // 0 - 2, // 1 - 0, // 2 - 5, // 3 - 5, // 4 - 22, // 5 - 8, // 6 - 8, // 7 - 28, // 8 - 11, // 9 - 11, // 10 - 34, // 11 - 14, // 12 - 14, // 13 - 40, // 14 - 16, // 15 - 2, // 16 - 16, // 17 - 17, // 18 - 18, // 19 - 18, // 20 - 19, // 21 - 21, // 22 - 21, // 23 - 23, // 24 - 24, // 25 - 24, // 26 - 25, // 27 - 27, // 28 - 27, // 29 - 29, // 30 - 30, // 31 - 30, // 32 - 31, // 33 - 33, // 34 - 33, // 35 - 35, // 36 - 36, // 37 - 36, // 38 - 37, // 39 - 39, // 40 - 39, // 41 - 41, // 42 - 42, // 43 - 42, // 44 - 46, // 45 - 20, // 46 - 46, // 47 - 49, // 48 - 26, // 49 - 49, // 50 - 52, // 51 - 32, // 52 - 52, // 53 - 55, // 54 - 38, // 55 - 55, // 56 - 58, // 57 - 44, // 58 - 58, // 59 - ]; + -1, // 0 + 2, // 1 + 0, // 2 + 5, // 3 + 5, // 4 + 22, // 5 + 8, // 6 + 8, // 7 + 28, // 8 + 11, // 9 + 11, // 10 + 34, // 11 + 14, // 12 + 14, // 13 + 40, // 14 + 16, // 15 + 2, // 16 + 16, // 17 + 17, // 18 + 18, // 19 + 18, // 20 + 19, // 21 + 21, // 22 + 21, // 23 + 23, // 24 + 24, // 25 + 24, // 26 + 25, // 27 + 27, // 28 + 27, // 29 + 29, // 30 + 30, // 31 + 30, // 32 + 31, // 33 + 33, // 34 + 33, // 35 + 35, // 36 + 36, // 37 + 36, // 38 + 37, // 39 + 39, // 40 + 39, // 41 + 41, // 42 + 42, // 43 + 42, // 44 + 46, // 45 + 20, // 46 + 46, // 47 + 49, // 48 + 26, // 49 + 49, // 50 + 52, // 51 + 32, // 52 + 52, // 53 + 55, // 54 + 38, // 55 + 55, // 56 + 58, // 57 + 44, // 58 + 58, // 59 + ]; //return polygons; return voronoi() - .parents(parents) - .angle(0) - .polygons(polygons) - .rotate([108,0]) - .scale(131.777) - .center([162, 0]); - } - - -/* - // Jarke J. van Wijk, "Unfolding the Earth: Myriahedral Projections", - // The Cartographic Journal Vol. 45 No. 1 pp. 32–42 February 2008, fig. 8 - // https://bl.ocks.org/espinielli/475f5fde42a5513ab7eba3f53033ea9e - d3.geoIcosahedral().parents([-1,0,1,11,3,0,7,1,7,8,9,10,11,12,13,6,8,10,19,15]) - .angle(-60) - .rotate([-83.65929, 25.44458, -87.45184]) -*/ \ No newline at end of file + .parents(parents) + .polygons(polygons) + .angle(3) + .rotate([108, 0]) + .translate([72, 252]) + .scale(136.67); +} diff --git a/src/rhombic.js b/src/rhombic.js index 4c9ec25..9463c75 100644 --- a/src/rhombic.js +++ b/src/rhombic.js @@ -7,26 +7,27 @@ */ import { atan, degrees } from "./math.js"; import voronoi from "./polyhedral/voronoi.js"; +import { geoCentroid } from "d3-geo"; -export default function() { +export default function () { var phi1 = atan(Math.SQRT1_2) * degrees; var vertices = [ - [0, 90], // 0 - [0, phi1], // 1 - [90, phi1], // 2 - [180, phi1], // 3 - [-90, phi1], // 4 - [45, 0], // 5 - [135, 0], // 6 - [-135, 0], // 7 - [-45, 0], // 8 - [0, -phi1], // 9 - [90, -phi1], // 10 + [0, 90], // 0 + [0, phi1], // 1 + [90, phi1], // 2 + [180, phi1], // 3 + [-90, phi1], // 4 + [45, 0], // 5 + [135, 0], // 6 + [-135, 0], // 7 + [-45, 0], // 8 + [0, -phi1], // 9 + [90, -phi1], // 10 [180, -phi1], // 11 [-90, -phi1], // 12 - [0, -90] // 13 + [0, -90], // 13 ]; - + // rhombic dodecahedron var polyhedron = [ [0, 1, 8, 4], @@ -42,46 +43,51 @@ export default function() { [8, 9, 13, 12], [5, 10, 13, 9], [6, 11, 13, 10], - [7, 12, 13, 11] - ].map(function(face) { - return face.map(function(i) { - return vertices[i]; - }); + [7, 12, 13, 11], + ].map(function (face) { + return face.map(function (i) { + return vertices[i]; + }); }); var polygons = { type: "FeatureCollection", - features: polyhedron.map(function(face) { + features: polyhedron.map(function (face) { return { - properties: { sitecoordinates: d3.geoCentroid({type:"MultiPoint", coordinates: face}) }, + properties: { + sitecoordinates: geoCentroid({ + type: "MultiPoint", + coordinates: face, + }), + }, geometry: { type: "Polygon", - coordinates: [[...face, face[0]]] - } + coordinates: [[...face, face[0]]], + }, }; - }) + }), }; var parents = [ - -1, // 0 - 0, // 1 - 6, // 2 - 2, // 3 - 1, // 4 - 9, // 5 - 11, // 6 - 3, // 7 - 4, // 8 - 8, // 9 - 5, // 10 - 10, // 11 - ]; - + -1, // 0 + 0, // 1 + 6, // 2 + 2, // 3 + 1, // 4 + 9, // 5 + 11, // 6 + 3, // 7 + 4, // 8 + 8, // 9 + 5, // 10 + 10, // 11 + ]; return voronoi() .polygons(polygons) .parents(parents) .angle(20) - .rotate([-76.5, 27, -84]); + .rotate([0.001, 0]) + .translate([213, 252]) + .scale(106.48) } - diff --git a/test/snapshots.js b/test/snapshots.js index 05dc266..2064fd2 100644 --- a/test/snapshots.js +++ b/test/snapshots.js @@ -8,6 +8,8 @@ import { geoCahillKeyes, geoComplexLog, geoCubic, + geoDeltoidalHexecontahedral, + geoRhombicDodecahedral, geoDodecahedral, geoIcosahedral, geoImago, @@ -100,6 +102,14 @@ export async function polyhedralWaterman() { return renderWorld(geoPolyhedralWaterman().precision(0.1)); } +export async function deltoidalHexecontahedral() { + return renderWorld(geoDeltoidalHexecontahedral().precision(0.1)); +} + +export async function rhombicDodecahedral() { + return renderWorld(geoRhombicDodecahedral().precision(0.1)); +} + export async function tetrahedralLee() { return renderWorld(geoTetrahedralLee().precision(0.1)); } diff --git a/test/snapshots/deltoidalHexecontahedral.png b/test/snapshots/deltoidalHexecontahedral.png new file mode 100644 index 0000000..0e26552 Binary files /dev/null and b/test/snapshots/deltoidalHexecontahedral.png differ diff --git a/test/snapshots/rhombicDodecahedral.png b/test/snapshots/rhombicDodecahedral.png new file mode 100644 index 0000000..1daa9ae Binary files /dev/null and b/test/snapshots/rhombicDodecahedral.png differ