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

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more