Javascript Voronoi points from polygons - javascript

I'm using R. Hill's Voronoi implementation to create polygons using an array of points:
sites=[{x:23, y:33}, {...}]
and also using an array with the canvas size:
box = {xl: 0, xr: 800, yt: 0, yb: 600}
Vornoi is generated with:
var diagram = voronoi.compute(sites, bbox);
The returned 'diagram' variable is a Javascript object with the following properties:
diagram.edges, diagram.cells, diagram.vertices
The object diagram.cells contains multiple cells each with 4 half-edges. Each half-edge has a lSite, rSite, va and vb objects containing x and y values.
However I am interested in obtaining an array of points (x,y) that form each polygon in the voronoi diagram and I have no idea how to do it.
Can anyone help please?

Found it: the method getStartpoint() can be applied to all the halfedges objects from within a cell object to obtain an array of points that form the polygon:
For example for cell 0:
var cellpoints=[];
for(e=0; e<diagram.cells[0].halfedges.length; e++){
cellpoints.push([diagram.cells[0].halfedges[e].getStartpoint().x, diagram.cells[0].halfedges[e].getStartpoint().y])
}

Related

Input geometry is not a valid Polygon in turf.js

I try to use turf.js and its function intersect in my Leaflet project. My original question can be found here. The problem is I cannot get a proper polygon in order to call it. The idea is to get the waypoints of the calculated route make a polgyon out of them and check where they intersect with a given buffered area.
var testpoint = turf.point([9.9354, 49.799]);
var buffered = turf.buffer(testpoint, 50, {units: 'meters'});
var array = []
control._routes[0]['coordinates'].forEach(function(e){
array.push([e['lat'],e['lng']])
});
var test = turf.polygon(L.polygon([[array]]))
var intersection = turf.lineIntersect(buffered, test)
I am getting the following error message:
Uncaught Error: Input geometry is not a valid Polygon or MultiPolygon
Here I have to point out that, when using line.intersect(buffered,buffered) it is working correctly, therefore I am assuming that the buffered variable is correct.
When it comes down to the test variable, I have tried with no [], one pair and double pair. But they all result in the same problem. I also tried to pass the array to turf.polygon but it couldn`t be done.

Tensorflow Error: Constructing tensor of shape (120800) should match the length of values (121881)

I am new to machine and new to tensorflow. As a method of learning, I have been following along with Dan Shiffman of the Coding Train as he shows how to create a color classifier.
I, however, wanted to do something different, so I collected data of hand-drawn shapes. Each shape has a label (square, circle, or triangle) and also has an array of 400 pixels (each picture was draw in a 20x20 grid). The data is stored in an object, which is contained within a JSON file.
Using p5.js's 'loadJSON' function, I can access the JSON file, iterate the entries, and create two arrays: 'shapes,' which is a an array of an array of pixels, and 'labels,' which is an array of the corresponding labels.
Below is the code, which utilizes p5's 'preload' and 'setup' functions.
let data;
let model;
// list of labels from which you can get the oneHot index
let labelList = [
"square",
"circle",
"triangle"
];
// function that is ran before setup
function preload() {
data = loadJSON('shapeData.json'); // loads the json file
}
// called after preload
function setup() {
let shapes = []; // an array of the pixels of hand-drawn shapes
let labels = []; // the corresponding label of each hand-drawn shape
// iterates over all of the entries in data
for (let record of data.entries) {
let pixels = record.pixels;
shapes.push(pixels);
labels.push(labelList.indexOf(record.label));
}
// ---------------- ERROR ------------------------
let xs = tf.tensor2d(shapes);
// these tensors work great
let labelsTensor = tf.tensor1d(labels, 'int32');
let ys = tf.oneHot(labelsTensor, 3);
}
The problem arises when I try to create the 'xs' as a tensor2d.
I get the error:
Error: Constructing tensor of shape (120800) should match the length of values (121881)
at assert (tfjs#0.11.7:2)
at new e (tfjs#0.11.7:2)
at Function.e.make (tfjs#0.11.7:2)
at Function.e.tensor (tfjs#0.11.7:2)
at Object.e.tensor2d (tfjs#0.11.7:2)
at setup (sketch.js:27)
at p5.<anonymous> (p5.js:46551)
at _runIfPreloadsAreDone (p5.js:46499)
at p5._decrementPreload (p5.js:46509)
at p5.js:59586
I have a total of 302 data points, each of which is an array of 400 binary numbers. Therefore the shape of the tensor should be [302, 400], and when I change the shape to something that is wrong (like [303, 401]) it gives an error saying that it should be [302, 400].
I am new to this whole process, so any help will be appreciated.
Thanks
I have found the fix! The separate script which downloads the data had an error. This created data of different lengths...
For instance, one shape had 400 pixels and another had 410 pixels. This difference created a problem within tensorflow. After removing the data points that did not have 400 pixels, the program worked just fine!

Find adjacent tiles in a two-dimensional grid

I have a two-dimensional grid, in which all tiles are defined by two coordinates x and y. I'm storing the tiles in an array like this var tiles = [];. Each tile is an object with an x and y property:
Tile = {
x: ...,
y: ...
}
For drawing purposes (canvas) I want to find out which tiles are adjacent to each other. I could do that by looping through each element and check if it is adjacent. Since that would take n^n number of accesses I don't think this is the right way to do it. I think there would be a more efficient algorithm.
I also thought that maybe storing the data in a different way would help, but again, I wouldn't know how.
You have 2 ways to create a grid :
Using a 2 dimensional Array which must be the easier thing for a grid
Store adjacent Tile of a Tile in it with something like that :
var tile0 = {
x:0, y:1
}
var tile1 = {
x:1,y:1, tileLeft : tile0
}
It can be useful if you want to create Pentagonal or Hexagonal... grid, ofcourse create your grid automatically with a for loop.
EDIT
A two dimensional array is simply an Array of Array
var arr = new Array()
for(var i = 0 ; i < 10 ; i++){
arr[i] = new Array()
}
Now you can set value like in a grid, for example :
arr[0][2] = {x:2,y:2} //It's a bit useless since indexes can be use for x and y
In that case, i have 10 Array stored in one Array so :
arr[10][0]
Will return following error : Uncaught TypeError: Cannot set property '2' of undefined, because index of arr are only define between 0 and 9.
With your data construct I can't see a way to check for all adjacent tiles without accessing each tile.
The "tried and true" two dimensional grid data construct would be...a simple two dimensional array. Then you can access tiles directly by their coordinates.

Plot within a tooltip in d3.js

I would like to create a d3-based plot which graphs a plot within a tooltip. Unfortunately, I haven't found any examples on the web. Here is a sample JSON file.
[{"x":[0.4],
"y":[0.2],
"scatter.x":[0.54,0.9297,0.6024,-1.9224,2.2819],
"scatter.y":[0.4139,1.1298,-0.1119,2.3624,-1.1947]},
{"x":[0.1],
"y":[0.9],
"scatter.x":[-0.8566,-0.5806,-0.9326,0.8329,-0.5792],
"scatter.y":[-0.5462,-0.7054,1.0264,-3.4874,-1.0431]}]
The idea is to have a scatter plot for (x,y) coordinates first. However, when one mouses over a point, a different scatter plot within a tooltip appears based on [scatter.x, scatter.y] coordinates for that respective point.
I can do the scatter plots separately but have been struggling to put them together. Could anyone shed some light on this and/or provide a minimal example?
This was too long for a comment but I'm not certain if it's the answer you were looking for. One of the issues you might find is that your nested data is formatted differently-- one uses JSON objects with x and y, while the other uses two arrays of points.
My solution to this would be to create an extensible function:
function makeScatterPlot(elem, width, height, data, fill)
elem, width, height, and data are the core parameters: which element to attach the chart to, the size of the chart, and the data for the chart (in the JSON object format).
This function would generate all necessary items for the chart and add the chart to the provided element.
Then you want to bind to mouseover of your main chart, and in that function you'll have to do a bit of data modification to re-organize the two arrays into the JSON object structure.
function mainMouseover(d){
var newData = [];
for (var i = 0; i < d["scatter.x"].length; i++){
var t = {x: [0], y: [0]};
t.x[0] = d["scatter.x"][i];
t.y[0] = d["scatter.y"][i];
newData.push(t);
}
var newG = mainG.append("g").attr("transform", "translate(200,200)");
makeScatterPlot(newG, 100,100, newData, "red");
}
Of course, you would modify the translate to match wherever you want your tooltip to be.
Putting this all together you get the following (very crude) fiddle. Hover over either of the black dots to see the sub-chart. Obviously this needs quite a bit of work to be a solid example (i.e. remove the sub-chart on mouseout), but hopefully it will set you in the right direction.
If the tooltip chart is significantly different styling-wise compared to your main chart it may not be the best idea to use an extensible function, and you could just create another custom function instead.

D3.geo.bounds does not return bounding box?

I am having a problem that I have traced to unexpected behavior in the d3.geo.bounds function.
var bounds = d3.geo.bounds(data);
For a geoJSON FeatureCollection containing only point features, a proper bounding box isn't returned: specifically, the x-values of the first and last points in the collection appear to used instead of the min and max x-values for the group of points. This can be seen in action at http://jsbin.com/icosof/4/edit.
The bounding-box coordinates returned thus includes the min and max y-values, but not the largest and smallest x-values. Instead, these seemed to be grabbed from the first and last features in the set:
[[6113.30166221, -6663.98951731], [5153.32052977, -77.3529517971]]
Generating a bounds object by manipulating the coordinates directly
xvalues = [];
$.each(data.features, function(i,el){
xvalues.push(el.geometry.coordinates[0]);
});
yvalues = [];
$.each(data.features, function(i,el){
yvalues.push(el.geometry.coordinates[1]);
});
console.log([[Math.min.apply(null,xvalues),Math.min.apply(null,yvalues)],
[Math.max.apply(null,xvalues),Math.max.apply(null,yvalues)]]);
produces the desired result:
[[3397.33954824, -6663.98951731], [6504.18296202, -77.3529517971]]
Does d3.geo.boundsexpect a FeatureCollection sorted by x-coordinates (and if so how would I work around this), or is this a bug?
I think the confusion here is that d3.geo.bounds expects features to have latitude/longitude values, not x/y values. So your input is taken as % 360, and you won't get the max/min you expect.
You may need to convert your coordinates to lat/lon values to get this to work - left as an exercise for the reader, as I don't know what your coordinate system is.

Categories