OpenLayers - Draw polygon with exact number of points - javascript

I have a UI where I give the user the ability to draw an area on the map, and I want him to draw a polygon with EXACTLY 4 points, how do I do that ?

This is done in this example here
The code they use to draw the bow is:
var boxLayer = new OpenLayers.Layer.Vector("Box layer");
map.addLayer(boxLayer);
drawControls = {
box: new OpenLayers.Control.DrawFeature(boxLayer,
OpenLayers.Handler.RegularPolygon, {
handlerOptions: {
sides: 4,
irregular: true
}
}
}

Use a polygon handler:
Handler to draw a polygon on the map. Polygon is displayed on mouse down, moves on mouse move, and is finished on mouse up.
To limit to 4 points use the sides property:
sides {Integer} Number of sides for the regular polygon.

Related

Populating markers inside rectangle, circle and polygon

My requirement is to populate markers inside a user drawn area ,which can be either circle, rectangle ,polygon.
This is what I am trying currently :-
map.on('draw:created', function(e) {
var type = e.layerType, layer = e.layer;
var bounds = layer.getBounds();
});
Now I am using these bounds(southWest, northEast) latlongs to virtually create a row column spacing and then populate markers accordingly.
Problem :-
The above approach works fine for rectangle and all markers are populated inside rectangle.
Doesn't work for circle and polygon. Markers are populated outside (nearby) the circle and polygon also.
I guess the getBounds() method is giving the bounds or calculating the area by creating a box that touches circle and all corner of polygon.
Any suggestions that how can I populate markers strictly inside or on boundary of circle and polygon?
Thanks in advance.
Resolved for point inside polygon by PIP as suggested by #kmandov and also resolved for circle by the below process :-
Get latitude and longitude of the point.
Get the latitude and longitude of circle center.
Run distanceTo() method on any of the above two latlongs and pass the second latlong as parameter.
Check if the distance is greater than the radius of circle.
If it's greater than the radius then the point is outside circle else inside circle.
Here is the condition that I used :
if (customMarker.getLatLng().distanceTo(myCircle.getLatLng()) <= myCircle.getRadius()) {
console.log("Marker is inside circle");
}else{
console.log("Marker is outside circle");
}
You can probably use the PointInLayer leaflet plug-in to check if a point is inside your area.
You can then add markers only for grid points that are actually within the polygon.
Something like that:
// the user area:
var areaLayer = L.geoJson(userArea);
// iterate over your grid of points
for (var i = 0; i < gridPoints.length; i++) {
// add marker only if the point is within the area
var results = leafletPip.pointInLayer(gridPoints[i], areaLayer, true);
if (results.length > 0) {
L.marker(gridPoints[i]).addTo(map);
}
}

change color of a circle if the user position is within its range

I have a map on which there are some circles, each one with a certain radius, and on the page load, I get the position of the user and show it on the map.
At first all the circles are red, so I want to check if the current position of the user happens to be in any of there circles, that particular circle should get green instead of red.
what is the best way to do that?
With Google Maps API, you may use the geometry library to calculate distance between circle's center and the lat/lng representing the position of your user. Then compare it with your radius.
You can do something like this :
var pointIsInsideCircle = google.maps.geometry.spherical.computeDistanceBetween(circle.getCenter(), point) <= circle.getRadius();
Then change the color of your circle if pointIsInsideCircle is true

Fabric.js group coordinates with panned canvas

I have a canvas that's initially panned so that the 0,0 point is in the middle of the screen. I'm trying to move a programmatically created group, but for some reason the group moves relative to the upper left corner of the visible canvas instead of the 0,0 point of the canvas. After that first movement the panning works correctly and the group moves around that position, until I discard it and create it again, and then it's relative to the upper left corner again, without taking the pan into account. If I create a group selection using the selection tool, it works correctly every time.
I pan the canvas with this:
var offsetX = -canvas.getWidth()/2;
var offsetY = -canvas.getHeight()/2;
canvas.absolutePan(new fabric.Point(offsetX, offsetY));
This is how I create the group:
var group = new fabric.Group();
objects.forEach(function (o) {
group.addWithUpdate(o);
canvas.remove(o);
});
canvas.add(group);
Then I try to move it with this:
group.set("left", 0);
canvas.renderAll();
And then the group is right at the left edge of the canvas element. But if I select the group with my mouse and use this instead, it appears right where it should be - in the center:
canvas.getActiveGroup().set("left", 0);
canvas.renderAll();
So, how do I get this to work properly? I know I could just calculate an offset from the canvas transformations, but I feel like this should be compensated for in the library itself and I'm either somehow using it wrong or it's a bug.

Moving a vector "straight out" along a fixed angle

I've searched for the answer to this and have tried many proposed solutions, but none seem to work. I've been struggling with this forever so any insight is greatly appreciated.
I have 3 shapes (vectors I suppose) on a JS canvas, each with an orientation represented as degrees off of 0 and a width. I need to drag one of these shapes "straight out" from its orientation. This is difficult to explain in words so please view the graphic I created:
The middle (diagonal) shape is at 45 degrees. It's origin is the red dot, (x1,y1). The user drags the shape and their mouse lies at the green dot, (x2,y2). Since the shape's origin is in the lower left, I need to position the shape at the position of the lighter blue shape as if the user has dragged straight outward from the shape's origin.
I don't think it matters, but the library I'm using to do this is KineticJS. Here's the code and some information I have available which may help solve the problem. This code positions the shape on top of the mouse, which isn't what I want:
var rotationDeg = this.model.get("DisplayOri"), // rotation in degrees
rotationRadians = rotationDeg * Math.PI / 180, // rotation in rads
unchanged = this.content.getAbsolutePosition(), // {x,y} of the shape before any dragging
dragBoundFunc = function (changed) {
// called on a mouseMove event, so changed is always different and is the x,y of mouse on stage
var delta = {
x: changed.x - unchanged.x,
y: changed.y - unchanged.y
};
return changed; // go to the mouse position
};
[edit] I should mention that the obvious of "return delta" doesn't work.
It sounds like you want to constrain the movement of the object.
Determine the vector representing the constraint axis : that is, we only want motion to occur along this line. It appears from your drawing that this is in the direction of the short line from the red dot out to the left. That vector has a direction of -1/m where m is the slope of the line we are moving.
Constrain the movement. The movement is represented by the mouse move delta - but we only want the portion of that movement in the direction of the constraint axis. This is done with a dot product of the two vectors.
So in pseudo code
m = (line.y2 - line.y1)/(line.x2 - line.x1)
constraintSlope = -1/m
contraintVector = {1, constraintSlope} //unit vector in that direction
userMove = {x2-x1, y2-y1} //vector of mouse move direction
projection = userMove.x * constraintVector.x + userMove.y * constraintVector.y
translation = projection * constraintVector //scaled vector

google map api v3 : update rectangle bounds when the shape is dragged or resized

I'm trying to draw a rectangle on google map api v3 using the draw tool. I want the user to be able to :
get the rectangle bounds when the shape is complete.
update the bounds when the rectangle is dragged or re-seized.
The (1) worked fine but i need some help on (2).
This is the code i used for (1) :
//----------on rectangle complete event
google.maps.event.addDomListener(drawingManager, 'rectanglecomplete', function(rectangle) {
//get the rectangle bounds
document.getElementById("savedata").value =rectangle.getBounds();
//hide draw tool
drawingManager.setOptions({
drawingControl: false
});
//disable draw tool
drawingManager.setDrawingMode(null);
});
Add an event listener to the rectangle for bounds_changed, capture the new coordinates in that. Code:
google.maps.event.addListener(rectangle, "bounds_changed", function() {
document.getElementById("savedata").value =rectangle.getBounds();
});
Here is an example using the DrawingManager that allows you to draw rectangles, change them and capture the changed value. The only thing missing from it is the change event (bounds_changed on the rectangle).

Categories