Published
Edited
Dec 2, 2021
3 forks
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
let {point, segment, circle, arc, Polygon} = Flatten;
let pw = width/48;
let ph = height/48;
// Create new polygon
let polygon = new Polygon([point(12*pw,12*ph), point(12*pw, 36*ph),
point(24*pw, 24*ph), point(36*pw, 36*ph),
point(38*pw, 12*ph)]);
let stage = d3.select(DOM.svg(width, height));

// Add svg element to svg stage container
stage.html(polygon.svg());

return stage.node()
}
Insert cell
Insert cell
Insert cell
{
let { point, segment, circle, arc, Polygon } = Flatten;
let pw = width / 48;
let ph = height / 48;

// Create new instance of polygon
let polygon = new Polygon();
// Add face from array of points - segment edges will be created
polygon.addFace([
point(12 * pw, 12 * ph),
point(12 * pw, 36 * ph),
point(24 * pw, 24 * ph),
point(36 * pw, 36 * ph),
point(38 * pw, 12 * ph)
]);
// Add another 3 faces - circular arcs
polygon.addFace([circle(point(18 * pw, 20 * ph), 2 * pw).toArc()]);
polygon.addFace([circle(point(4 * pw, 24 * ph), 3 * pw).toArc()]);
polygon.addFace([circle(point(40 * pw, 28 * ph), 3 * pw).toArc()]);

let stage = d3.select(DOM.svg(width, height));

// Add svg element to svg stage container
stage.html(polygon.svg());

return stage.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
polygon = {
// Fetch json from gist file
// let json = await d3.json("https://gist.githubusercontent.com/alexbol99/b4fe6ac529758b0b1e981e37676d87b9/raw/f624e3a3665f8114c6b35e80cf0082c43ff08032/polygon.json")
let json = await
d3.json("https://gist.githubusercontent.com/alexbol99/af17f2f1b9dc8de9e29a60a826e0ebf2/raw/67cccc9a5739f6d4cb27bf39e6f657eb93f0150b/test_xml_0.json")
// Create polygon from json
let polygon = new Flatten.Polygon(json);
return polygon;
}
Insert cell
Insert cell
{
let stage = d3.select(DOM.svg(width, height))

// Add svg path to stage container
stage.html(polygon.svg());

let data = [polygon];

// Bind data to svg elements.
let selection = stage.selectAll("*")
.data(data);

//specify what to do when zoom event listener is triggered
function zoom_action(){
selection.attr("stroke-width", 1/d3.event.transform.k);
selection.attr("transform", d3.event.transform);
}

//create zoom handler
let zoom_handler = d3.zoom()
.on("zoom", zoom_action);

// Create zoom behavior
stage.call(zoom_handler);
initial_transform(width, height, zoom_handler);

// Initial transform define transformation from real world to center of the stage
function initial_transform(canvasWidth, canvasHeight, zoom_handler) {
let box = new Flatten.Box();
selection.each( geom => box = box.merge(geom.box) )
let width = box.xmax - box.xmin;
let height = box.ymax - box.ymin;
let k = Math.min( canvasWidth / (1.1*width), canvasHeight / (1.1*height) );
let tx = canvasWidth/2 - k*(box.xmin + box.xmax)/2;
let ty = canvasHeight/2 - k*(box.ymin + box.ymax)/2;
let t = d3.zoomIdentity.translate(tx, ty).scale(k, -k);
stage.transition().duration(1000).call(zoom_handler.transform, t);
}

return stage.node()
}
Insert cell
Insert cell
md`First of all, our polygon has ${polygon.faces.size} face and ${polygon.edges.size} edges`
Insert cell
md`Area of the polygon is equal to ***${[...polygon.faces][0].area()}*** (of some squared units).`
Insert cell
md`Then, for each face we may ask about *orientation*. For the single face of our polygon *the orientation* is ***${[...polygon.faces][0].orientation() == Flatten.CW ? "clockwise" : "counter clockwise"}***.`
Insert cell
Insert cell
md`And the answer is: polygon has ***${answer.numSegments}*** segments and ***${answer.numArcs}*** arcs`
Insert cell
answer = {
let numSegments = 0;
let numArcs = 0;
for (let face of polygon.faces) {
for (let edge of face) {
if (edge.shape instanceof Flatten.Segment) {
numSegments++;
}
else {
numArcs++;
}
}
}
return {numSegments, numArcs}
}
Insert cell
Insert cell
Insert cell
Insert cell
polygon2 = {
let polygon2 = polygon.clone();
// Iterate on faces
for (let face of polygon2.faces) {
// Iterate on edges in face
for (let edge of face) {
if (edge.shape instanceof Flatten.Arc) {
// Break arc into array of functional arcs
let brokenArcs = edge.shape.breakToFunctional()
if (brokenArcs.length === 1)
continue;

// Arc was really broken to functional arcs
let edgePrev = edge.prev; // keep prev for insertion
// remove current arc edge
face.remove(polygon2.edges,edge);

// insert functional arcs as new edges
for (let brokenArc of brokenArcs) {
face.insert(polygon2.edges, new Flatten.Edge(brokenArc), edgePrev);
edgePrev = edgePrev.next;
}
}
}
}
return polygon2
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
Flatten = require("@flatten-js/core")
Insert cell
d3 = require("d3@5")
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more