I'm working on a project using a JavaScript canvas and need to be able to snap the cursor to a certain distance from a polygon. I can already snap to the polygon itself, but I need to have the cursor farther away.
As far as I can tell the best way to go about this is to scale the polygon and snap to that, but when I scale the polygon the distance between the edges of the old polygon and the edges of the new polygon don't always match up.
here is an example of the problem:
Edit: The grey represents the original polygon, the red is what I am getting if I scale the polygon normally, and the green is what I'm trying to accomplish
I've already tried translating the polygon to the origin and multiplying by a scale factor, but can't seem to scale each edge by a specific distance.
I can offer a solution using JSTS library (JavaScript port of JTS). The library has methods for inflating/deflating (offsetting) of polygons.
You can set the cap and join styles if you want to get the inflated polygon with different type of edges. The only thing you have to do is to convert you polygon coordinates to a JSTS coordinate which is really simple:
function vectorCoordinates2JTS (polygon) {
var coordinates = [];
for (var i = 0; i < polygon.length; i++) {
coordinates.push(new jsts.geom.Coordinate(polygon[i].x, polygon[i].y));
}
return coordinates;
}
Once you have converted the coordinates you can inflate your polygon:
function inflatePolygon(poly, spacing) {
var geoInput = vectorCoordinates2JTS(poly);
geoInput.push(geoInput[0]);
var geometryFactory = new jsts.geom.GeometryFactory();
var shell = geometryFactory.createPolygon(geoInput);
var polygon = shell.buffer(spacing);
//try with different cap style
//var polygon = shell.buffer(spacing, jsts.operation.buffer.BufferParameters.CAP_FLAT);
var inflatedCoordinates = [];
var oCoordinates;
oCoordinates = polygon.shell.points.coordinates;
for (i = 0; i < oCoordinates.length; i++) {
var oItem;
oItem = oCoordinates[i];
inflatedCoordinates.push(new Vector2(Math.ceil(oItem.x), Math.ceil(oItem.y)));
}
return inflatedCoordinates;
}
With code I've posted on jsFiddle you will get something like this:
Additional info: I usually use this type of inflating/deflating (a little changed) for setting boundaries with radius on polygons that are drawn on a map (with Leaflet or Google maps). You just convert lat,lng pairs to JSTS coordinates and everything else is the same. Example: