Draw Polygons on a map using WebGL's drawArrays - javascript

I am trying to draw polygons on a map, using OSM data downloaded. I have written a query that returns a list of polygons from the planet_osm_polygon table. It resturns the list as JSON objects. I am using gl.drawArrays(gl.LINESTRIP, 0, json_data_length) to draw the polygons. I have done the same for points- I have a list of points returned and I have been able to plot them using gl.POINTS.
The problem is, I want each of the polygons to be drawn separately, but I guess using LINE_STRIP is connecting one ending point of one polygon to the starting point of another polygon.
For example, I want civic center plaza and buchanan street in SFO to be separate polygons. But the polygons, after being drawn, are still connected to each other through one point. I want these two to be drawn as separate polygons. How do I do it?
I do not want to use any libraries. Just basic WebGL. My JavaScript code takes the lat-long coordinates from my osm database and converts into pixel coordinates to help plotting- see link: WebGL shader code (http://psousa.net/demos/webgl/) I am using this example and extending it.

If i understood correctly you want to draw 'borders' of multiple polygons not the filled polygon itself.
In order to draw seperate lines in a single draw call you should use gl.LINES mode instead of gl.LINESTRIP.
Lets say you have a quad which has points A,B,C,D and a triangle which has points X Y Z. If you want to use glDrawArrays command with GL_LINES mode , your vertex data should be submitted as
{A,B, B,C, C,D, D,A, X,Y, Y,Z, Z,X}
Following lines are drawn with this vertex data
Line from A to B
Line from B to C
Line from C to D
Line from D to A
Line from X to Y
Line from Y to Z
Line from Z to X
In order to eliminate duplicate vertex data you can also use glDrawElements with a proper index .

Related

Triangulating contours into 2d mesh with color data intact

I am using a Javascript library 'Tess2' to triangulate a series of contours.
https://github.com/memononen/tess2.js/blob/master/src/tess2.js
It generates a perfect 2d mesh of any shape consisting of multiple contours:
A contour consists of a series of points (in a negative winding order for solid fills, in a positive winding order for holes)
However, the resulting triangles output by the algorithm are no longer tied to a contour and its fill color.
How would I alter Tess2 (or any other javascript library that tesselates contours) to allow for the retention of color data in the resulting triangles?
I've tried looking everywhere and I cannot find a solution.
From what I've seen in the source code, the tessalation function contains a vertex indices in an returned object:
Tess2.tesselate = function(opts) {
...
return {
vertices: tess.vertices,
vertexIndices: tess.vertexIndices,
vertexCount: tess.vertexCount,
elements: tess.elements,
elementCount: tess.elementCount,
mesh: debug ? tess.mesh : undefined
};
You can create a new array with the colors for each vertex, and then use vertexIndices from the object to get a color of the vertex.
If you would like to have a color per face, you would just need to generate an array like above, which means putting the same vertex color for each vertex in a array. You would also like to wrap all of this data in some kind of convienent object or class.
[EDIT]
It turns out that the tesselation algorithm merges vertices in the same position, meaning that it reorganizes vertex array completely. There are a solution to explicitly not merge different contours with overlapping vertices:
Tess2.tesselate({ contours: yourContours, elementType: Tess2.BOUNDARY_CONTOURS });
That should preserve the original vertices, however not in an original order, use vertexIndices to get the original position of these.
After many failed attempts I finally got there.
I've been trying all this time to try and process a huge amount of contours all at once with a single tessellation pass.
I tried editing the tessellation library to make each half edge retain it original contour ID. I had several eureka moments when it finally seemed to work, only to be disappointed when I stress tested it and found it to be less than perfect.
But it turns out I've been incredibly daft...
All I had to do was group each contour with a particular fill, and then tesselate each group independently.
I didn't understand that for every interior contour fill, there would always be an opposite contour that effectively enclosed the outer contour loop.
For instance, to represent a red box with a blue box inside there would be 2 red contours and 1 blue. I thought it could be represented with only 1 blue contour and 1 red, where the blue would also represent the red contour's hole, and so processing each colour group of contours independently didn't make sense to me.
When I finally realised this, I figured it out.
I've published a solution on github but I'm not sure how much use it is to anyone:
https://github.com/hedgehog90/triangulate-contours-colour-example
I've included a pretty comprehensive exporter script for converting contours (including curves) into polygonal paths for Adobe Flash/Animate which might be useful for someone.
I will be writing an OBJ exporter on top of this shortly, so I can represent vector graphics in a 3D engine.

When cutting a polygon with a polyline the geometry engine will group certain peices together?? Arcgis javascript api

When preforming a cut action on a polygon with a polyline, some of the returned geometries are grouped while others are not?
I have a simple program where the user can create a polygon with a SketchViewModel. Then the user creates a polyline with a SketchViewModel. I then take the geometry from each sketch and preform a cut from the geometryEngine. I get an array of geometries from the cut and add them to the layer while removing the original polygon and polyline. I would expect to get each subdivided piece individually but for some reason some get grouped together as one geometry even if they're not connected.
//polylineLayer and polygonLayer are graphiclayers
//submit is a html button to call the execution
submit.addEventListener("click", function() {
//subDivisions is an Geometry[] for the produced geometries
//ex. one line through a circle polygon would produce
// two geometries of each half. (this works)
// anything more complicated starts having grouping issues
// (see pictures)
var subDivisions =
geometryEngine.cut(polygonLayer.graphics.getItemAt(0).geometry,
polylineLayer.graphics.getItemAt(0).geometry);
polygonLayer.removeAll();
polylineLayer.removeAll();
//show the number of subdivisions
alert("size: " + subDivisions.length);
// add created geometries to the graphiclayer
for (var i = 0; i < subDivisions.length; i++){
tempGraphic = new Graphic ({
geometry: subDivisions[i]
});
polygonLayer.graphics.add(tempGraphic,i);
}
});
(sorry for the links to photos I don't have 10 reputation to post photos and this is a very visual project/issue)
Open screen:
https://ibb.co/WDcgmSn
Draw first polygon:
https://ibb.co/wd6CDbV
Draw polyline to cut polygon:
https://ibb.co/BG32863
Expected subdivisions - 10 Actual - 7:
https://ibb.co/0VMsHGg
Some are split into individual polygons:
https://ibb.co/SKXCJR8
Others are not:
https://ibb.co/7WqNB9q
All broken up pieces:
https://ibb.co/Pr0smrw
Wish I could comment instead of just answer but hard to say with out code.
Basically you are getting multipart polygons, you need to break those up.
Use a split in your array to break up the multi-part polygons split("]],[[")
Simplify Polygons using a geometry service would be worth a shot too. (before and after cutting)
https://developers.arcgis.com/rest/services-reference/geometry-service.htm

How to get L.polygon border, excluding inner points

I am working with Leaflet.js library. I have an array of geographical points, described by latitude and longitude and a polygon, based on this points. How can i remove inner points of polygon and draw only it's outer border?
Array of points
[[53, 31], [51.4, 31.2], [51.3, 32] ... etc.] //it's length ~ 500 points.
Initializing map
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(mymap);
Setting polygon
L.polygon(points, {color: 'red'}).addTo(mymap);
This is what i have right now. Here is all of 500 points is shown.
Result i am expecting. Here all internal points are removed, showing the covered area.
Sounds like you are looking for a convex hull algorithm: it would provide you with the "envelope" of your Points.
You can use e.g. Turfjs: https://turfjs.org/docs/#convex
But note that it requires working with data converted to GeoJSON objects.
You can also have a look at how Leaflet.markercluster plugin has implemented it.

Getting intersection between existing layer and drawn shape

EDIT I now get the right layer from map, so the question now sums up to knowing if a layer A which contains curves, intersectects layer B which contains a surface which can be a circle or a polygon that was just drawn. I tried turf library's turf.intersect but I get "cyclic object reference" from that library.
And I am already looping through the curves seperaterly, to the question is now "Does a curve intersect with a shape.
Also tried: ol.extent.getIntersection(...) but it work only with extents wich are rectangle and therefore give very imprecise results.
I have a map and a layer that is built and added through
var layer = new ol.layer.Vector{(...)};
map.addLayer(layer);
And I add a layer through interaction, as shown in this example: http://openlayers.org/en/v3.6.0/examples/draw-features.html?q=draw
(We use the Circle selection.)
I would like to get he intersection between the lines in the fist layer and the shape (surface) drawn through interaction.
So far, I know that I can catch the event:
var draw = new ol.interaction.Draw{(...)};
draw.on('drawend', function(event){(...)};
But so far I have no clue on what information I can get from the event and how to match it with the layer.

javascript polygon intersection

I have used the code in the following :
http://www.amphibian.com/blogstuff/collision.html. in the html test file I have changed the the first triangle to
triangle1.addPoint({"x":-20, "y":-20});
triangle1.addPoint({"x":-20, "y":20});
triangle1.addPoint({"x":20, "y":20});
triangle1.addPoint({"x":20, "y":10});
triangle1.addPoint({"x":10, "y":10});
triangle1.addPoint({"x":10, "y":-20});
now when I move the other triangle with inside this shape before crossing it gives me wrongly intersection. Any idea where could be the problem?
All right, I set up a fiddle for anyone else wanting to play with this. Here are the results:
The script makes use of the Separating Axis Theorem or (as Wikipedia calls it) Hyperplane separation theorem, as explained in the source of polygon.js:
/*
* To detect intersection with another Polygon object, this
* function uses the Separating Axis Theorem. It returns false
* if there is no intersection, or an object if there is. The object
* contains 2 fields, overlap and axis. Moving the polygon by overlap
* on axis will get the polygons out of intersection.
*/
Polygon.prototype.intersectsWith = function(other) {
This theorem only applies to convex polygons. Your shape is not convex as it has a "dent" in it. That's why the script incorrectly reports that the shapes are intersecting. If you need to make it work with concave shapes, you'll have to make it first split the concave shape up in separate convex parts and then apply the theorem to all individual parts. Obviously, this makes the script more complex as you need to iterate over the cross product of the concave parts of two shapes.
Here is my not too complicated implementation of finding the intersection polygon of two polygons.
It works for convex and concave polygons, but not for complex (self-intersecting) polygons.
Algorithm is fairly similar to the one presented in Margalit & Knott.
Its complexity is about 4*n1*n2, where n1 and n2 are numbers of vertices in polygons whose intersection is being calculated.
It is a single standalone .js file. A 'Polygon' is regarded any javascript array of 2D Points. A 'Point' is any javascript object with x and y numeric properties.
Implementing the Union functionality on top of existing one should not be a problem and I will do it probably soon.
Intersection of 2D polygons

Categories