I am wanting to limit the users ability to create more than 2 polygons and more than 1 path. I can programmatically add or remove specific drawing tools, but what I can't seem to find any documentation on is counting the number of polylines or polygons that exist on a map.
Here is some pseudo code to demonstrate the intended use:
If exists > 2 polygons and exists < 2 polylines then
disable polygon drawing tool
else if exists < 3 polygons and exists > 1 polylines then
disable polyline drawing tool
else if exists > 2 polygons and exists > 1 polylines then
disable entire drawing tool
end if
Again, my question is specific to counting polygons and polylines on a map. Does the Google API have this capability?
Firstly: your if-elseif is more complicated than is required. If the limit is strictly 1 polyline at most, and strictly 2 polygons at most
if (n == 2) {
//switch off polygon drawing tool
}
if (m == 1) {
//switch off polyline drawing tool
}
if (n == 2 and m == 1) {
//switch off drawing tool
}
where
n is the count of polygons and
m is the count of polylines,
In other words, turning off the polyline drawing is independent of how many polygons there are, and vice versa.
As to keeping track of n and m...
Probably best to create an object - let's call it cf - and push each user-created object to it (if the user-created object is the type of object you want to count), and then switch off the drawing tool if the length of cf exceeds the limit you want to impose.
So
var cf=[];
/* stuff to draw things on the map, resulting in a new object called kk */
cf.push(kk);
if (cf.length>3){
// switch off the drawing tool
}
Since you want to impose different restrictions based on whether the object created is a polyline or a polygon, create 2 objects (say, cf1 and cf2) and push kk to cf1 if it's a polygon, and to cf2 if it's a polyline... and change the if statement to reflect the different tests.
Why not just iterate a counter rather than creating an object?
I'm assuming that there's a point to the drawing of the polygons and polylines, and that you want to use/save/export them.
With the approach I've outlined, cf1 and cf2 can contain everything about each polygon, not just their geometry - the user who generated them, summary information about them, and all the other things you might like to store/export/display.
If none of that is required, then a counter would work just fine.
inb4 'using cf.length is kinda non-canonical in the JS world'. Too bad. It works (except in corner cases that don't apply here) and it's parsimonious.
Related
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
I come back for a problem. I'm still learning d3js for 5 days and I have a problem about the border rendering.
Why I have that ?
The problem occurs when I add region borders.
svgMap.append("path")
.attr("class", "reg_contour")
.datum(topojson.mesh(fr[0], fr[0].objects.reg_GEN_WGS84_UTF8, function(a, b) { return a !== b; }))
.attr("d", path);
Here is my code : https://plnkr.co/edit/mD1PzxtedWGrZd5ave28?p=preview
Just for the record, the json file combines two layers (departments and regions) created with the same shp and compiled by QGIS for geojson output. After I convert this to topojson by mapshapper.
The error lies in your topojson - the two different feature types, departments and regions do not share the same coordinates along their common boundaries.
First, in this sort of situation it is desirable to check to make sure there is no layering issue (often other features are drawn ontop of others, hiding them or portions of them), we can do this by just showing the regional boundaries:
(plunkr)
So the problem can't be layering, if we look at a particular feature in the topojson, say the department of Creuse:
{"arcs":[[-29,-28,-27,-26,202,-297,-296,205,-295,-410,419]],"type":"Polygon","properties":{"codgeo":"23","pop":120581,"libgeo":"Creuse","libgeo_m":"CREUSE","codreg":"75","libreg":"Nouvelle Aquitaine"}}
We see that the department is drawn using 11 arcs representing each portion of the boundary based on shared boundaries between multiple features so that shared boundaries are only represented once in the data.
If we zoom in on Creuse we can see those 11 arc segments shared between either other departments, regions, or with nothing at all:
The thick portions of the boundary correspond to the thick white boundaries in the image in the question, I've only changed the styling and zoom from the original plunkr
This looks problematic, the department should only have 6 arcs:
Why are there additional arcs? Because the boundaries of the departments are not aligned properly - the shared boundaries between departments do not always share the same arcs in your topojson. Chances are the departments might use a different scale than the regions, a different precision or projection, or were made somehow differently. This has resulted in minute nearly imperceptible differences that have resulted in boundaries that share coordinates in reality not sharing the same coordinates in the data, and thus the shared arcs are going unrecognized.
Since you are generating the mesh like this:
topojson.mesh(fr[0], fr[0].objects.reg_GEN_WGS84_UTF8, function(a, b) { return a !== b; })
Only shared boundaries are drawn, which explains the gaps.
We can rectify this a few ways, the easiest way would be to remove the regions altogether. The departments record which region they are in, we can check to see if a boundary should be drawn if the departments on each side of that boundary are in different regions:
.datum(topojson.mesh(fr[0], fr[0].objects.dep_GEN_WGS84_UTF8, function(a, b) { return a.properties.libreg !== b.properties.libreg; }))
Which gives us:
(plunkr)
Alternatively, we can re-habilitate the regional boundaries by importing them into a GIS platform such as ArcGIS and repairing the geometry. We could also import the departments and make a new layer based on region properties in a dissolve. Using the repair geometry tool in Arc, I get a nice boundary (when shown with the same code as the first image here):
There are other methods, such as including a tolerance in aligning arcs, but these might be more difficult than the above.
I have a map and a lot of markers are displayed on it. Sometimes markers are so close to each-other that they overlap. To remedy this, I have implemented a spiderfier library to remedy this situation.
The idea is to group the markers being close-enough upwards on the screen (downwards mathematically) in such a way that they will not intersect each-other.
Markers are displayed as rectangles.
Implementation:
traverses the markers and markers which intersect each-other are included into a group with the center of ((minX + maxX) / 2, maxY) and the radius is just large-enough to display the markers on the periphery without intersecting each-other
while there are semi-circles which intersect each-other, we merge them into a larger half-circle
we sort the markers by a comparator, placing "smaller" markers to the left on the periphery of the circle compared to their "greater" counterparts
we display the markers on the top-half circle, but we display a line from their modified location to their real location
So far, so good.
Problem: These lines are intersecting each-other too often and we need a comparator function with which the number of marker line intersection is minimalized.
Tries:
P1.x <= P2.x => P1 <= P2
arctan((P1.y - C.y) / (R * (P1.x - C.x))) <= arctan((P2.y - C.y) / (R * (P2.x - C.x))) => P1 <= P2
I had high hopes tied to the second try, but had to acknowledge that it is not a good idea, since the translation line and the line between the real location and the center of the circle are not necessarily collinear, in fact, their angle can become fairly big if there are many markers having their real location very close to each-other, whilst the half-circle's surface except this sub-region is fairly barren. So, this leads to intersections as well and it is much more complex than the first try. I believe Javascript's Math.atan is implemented either with Taylor series or Fourier series, which involves derivatives in the first case and integral in the second case. Or, there might be a third approach, which is highly complex as well. I would think about optimizations and stuff like that if this second approach would have significantly reduced the number of intersections, but since the improvement is barely observable if at all, I returned to the first approach.
I am thinking about the following approach:
calculate the locations of the marker slots on the periphery
try to translate all the markers to their closest possible slot
find the conflicting groups and solve all conflicts by finding the optimum, which is the translation-set with the smallest total translation
Is this idea leading to a state where spider line intersection number is minimalized and if not, how could I minimalize the number of such intersections?
This is a difficult problems, studied for a long time now.
It is sometimes called
automatic label placement.
The work cited below is typical of what is available in the literature.
Van Kreveld, Marc, Tycho Strijk, and Alexander Wolff. "Point set labeling with sliding labels." Proceedings of the fourteenth annual symposium on Computational geometry. ACM, 1998. ACM link.
I am new to Phaser and I am currently having a hard time in generating a tilemap with the aid of the phaser isometric plugin. I am also having trouble with understanding some of the concepts related with the Phaser world, game, and the camera which make the part of generating the tilemap correctly even harder. I have actually noticed that this problem seems to be an obstacle to Phaser newbies, like myself, and having it correctly explained would certainly help to fight this.
Getting to the matter:
I have generated a tilemap using a for loop using single grass sprites. The for loop is working correctly and I also implemented a function where I can specify the number of tiles I want to generate.
{
spawnBasicTiles: function(half_tile_width, half_tile_height, size_x, size_y) {
var tile;
for(var xx = 0; xx < size_x; xx += half_tile_width) {
for(var yy = 0; yy < size_y; yy += half_tile_height) {
tile = game.add.isoSprite(xx, yy, 0, 'tile', 0, tiles_group);
tile.checkWorldBounds = true;
tile.outOfBoundsKill = true;
tile.anchor.set(0.5, 0);
}
}
}
}
So the process of generating the static grass tiles is not a problem. The problem, and one of the reasons I am trying to getting the object pooling to work correctly is when the tiles number is superior to 80 which has a dramatic impact on the game performance. Since I aim for making HUGE, auto-generating maps that are rendered according to the player character position the object pooling is essential. I have created a group for these tiles and added the properties I thought that would be required for having the tiles that are out of bounds to not be rendered(physics, world bounds...). However, after many attempts I concluded that even the tiles that are out of bounds are still being generated. I also used another property rather than add.isoSprite to generate the tiles, which was .create but made no difference. I guess no tiles are being "killed".
Is this process correct? What do I need to do in order to ONLY generate the tiles that appear on camera (I assume the camera is the visible game rectangle) and generate the rest of them when the character moves to another area assuming the camera is already tracking the character movement?
Besides that, I am looking to generate my character in the middle of the world which is the middle of the generated grass tilemap. However, I am having a hard time doing that too. I think the following concepts are the ones I should play with in order to achieve that, despite not being able to:
.anchor.set()
game.world.setBounds(especially this one... it doesn't seem to set where I order to);
Phaser.game ( I set its size to my window.width and window.height, not having much trouble with this...)
Summing up:
Using the following for loop method of generating tiles, how can I make infinite/almost infinite maps that are generated when the camera that follows my character moves to another region? And besides that, what is the proper way of always generating my character in the middle of my generated grass map and also for the camera to start where the character is?
I will appreciate the help a lot and hope this might be valuable for people in similar situations to mine. For any extra information just ask and if you want the function for generating the tiles by a specific number I will gladly post it. Sorry for any language mistakes.
Thank you very much.
EDIT:
I was able to spawn my character always in the middle of the grass by setting its X and Y to (size/width) and (size/height). Size is the measure of X and Y in px.
I discovered that is possible to add only eight waypoints in google api directions, you know how to bypass this limitation? I've tried to display direction api, but gave up this idea. Now my solution is based on own polyline, each click adds marker that should stick to that line, next together with it should move as you drag and here occurred is that if there are more than 8 points polyline with markers is no longer compatible. Maybe my approach is completly bad? How to fix this?
Current code: jsfiddle
Markers are not on the polyline:
One way to avoid markers being placed in the middle of the block is to place one at the end of the generated polyline, for example, inside one of your loops, instead of where the click was.
for (k = 0; k < next.length; k++) {
polyline.getPath().push(next[k]);
if (z == steps.length-1 && k == next.length-1) {
var roadMarker = new google.maps.Marker( {
map: map,
position: next[k],
icon: "http://labs.google.com/ridefinder/images/mm_20_green.png"
});
}
}
You will have to also change the first marker to be placed at the start of the polyline
This applies the code above http://jsfiddle.net/T79as/3/
So, my solution is to create render DirectionRenderner between each important waypoint (with marker?):
http://jsfiddle.net/9T7Vg/
draggable markers that look exactly like original ones
draggable polyline with immediately calculation
custom markers with letters (A, B, etc.) - this was difficult
route computation in long distance is much faster
route can have more than 8 waypoints (you can improve script to automate split the route when user want to place 9th waypoint between markers)
So this solution is in fact better than original in Google Maps, especially with long routes.