gabzim / circle-to-polygon Goto Github PK
View Code? Open in Web Editor NEWReceives a Coordinate, a Radius and a Number of edges and aproximates a circle by creating a polygon that fills its area
License: ISC License
Receives a Coordinate, a Radius and a Number of edges and aproximates a circle by creating a polygon that fills its area
License: ISC License
The use of ES6 syntax let
here:
https://github.com/arg20/circle-to-radius/blob/master/index.js#L27
and here:
https://github.com/arg20/circle-to-radius/blob/master/index.js#L32
breaks uglify. You are careful to use var and ES5 syntax throughout the rest of the file. I suspect this was an oversight.
Hi, I noticed that if the center of the circle is located up north (e.g. [24, 60]) and the radius is a big number like 5000000( 5000 KM) the output includes out of range values for longitude and latitude.
I resolved it by adding the following part before returning the result but wondering if there are cleaner ways of doing it?
for (let i = 0; i < coordinates.length; i++) {
if (coordinates[i][0] > 180) coordinates[i][0] = 180;
if (coordinates[i][0] < -180) coordinates[i][0] = -180;
if (coordinates[i][1] < -90) coordinates[i][1] = -90;
if (coordinates[i][1] > 90) coordinates[i][1] = 90;
// console.log(coordinates[i][0], coordinates[i][1]);
}
@johachi How do you feel about us either:
a. Porting this to typescript
b. Adding a typings file for people consuming this from typescript?
Right now we're limited to using var
etc on our source. If we don't want to add typing to the module maybe we could at least at a transpilation step via babel?
What are your thoughts on this?
Hi,
I would need a new release of the current version of circle-to-polygon. You've merged my pull request but I would need it available via npm.
Could you please make a new release please?! :)
Best regards,
Jan
I used following code to return a polygon which is approximately like a circle.
let coordinates = [28.612484207825005, 77.23574939044147];
let radius = 311;
let numberOfEdges = 32;
let polygon = circleToPolygon(coordinates, radius, numberOfEdges);
var coords = polygon.coordinates;
When I used coords and created a polygon shape using Google Maps JS API, it showed a shape like oval (2 ends were very far from each other, two very near, hope you understand).
In fact, the different in distances is approx. 4:1 ratio. So it's never a shape closer to circle.
Is there any issue, or is it supposed to do this intentionally?
There has been several issues where the user has passed the longitude
and latitude
in opposite order in the array passed as the center
argument. This has been a cause that users has gotten "incorrect" circles.
The problem might already have been mitigated some since circleToPolygon
since version 2.0.0 reject latitude values larger than ±90, but can still occur when a longitude smaller than ±90 is passed as the latitude value.
The problem could be further mitigated by letting the user pass the coordinates as an object (in addition to passing it as an array).
Expand the function to allow the parameter center
to be an Object of any of the following compositions.
center = { latitude: latValue, longitude: lngValue }
OR
center = { lat: latValue, lon: lngValue }
OR
center = { lat: latValue, lng: lngValue }
where latValue
and lngValue
are valid latitude and longitude values as stated earlier.
Hi!
I need to be able to convert semi circles and quarter circles to geojson. I wonder if there’s any way to modify this script easily to accommodate for that.
Thanks
I'm currently working on fixing the problem regarding out of range values (see #4 and #6 ). Out of range problem occur when the edge of the circle cross the longitude value 180 or when the circle include any of the polar circles.
When doing this I started to think about the functions signature, or more specific, it's arguments
circleToPolygon(center, radius, numberOfSegments)
Solving the problem with too large positive or negative lat
and lng
values has to be solved by creating a MultiPolygon
instead of the regular Polygon
. I realize that this would also change the output object as well.
However, some implementations prefer to large lat
/lng
values over MultiPolygon. Because of that, I wanted to make using MultiPolygon to be an option. At the same time, we don't want to keep on increasing arguments. One solution could be to replace either numberOfSegments
or both radius
and numberOfSegemnts
with an object called config
.
The new arguments would then be just center
and config
and the function call would be circleToPolygon(center, config)
where config could look something like this:
// example is with default values
const config = {
radius: 1500,
numberOfSegments: 32,
useRightHandRule: true,
MultiPolygon: true
}
I could make the function backwards compatible by checking variable type and for a third argument, but maybe a version bump and having breaking changes in the readme would give more clean code. What do you think? @gabzim
Currently the only possible optional configuration of circleToPolygon
is numberOfSegments
. We want to expand the functionality of circleToPolygon
to allow for more optional configurations like creating MultiPolygon (if needed) and to not follow the right-hand rule. We want to do this without increasing the number of parameters for circleToPlygon
numberOfSegements
to options
options
is a Numberkey
named numberOfSegemnts
, then the value of that key should be used as the value for numberOfSegments
options
is an Object but does not have the key numberOfSegements
, then then numberOfSegments
should default to 32
.The reason that there should not be any error thrown if options
is an object without the key numberOfSegements
is that all options should be optional. The user might set different options depending on different conditions. We do not want the code to throw an error if one or both of x
and y
are false.
const options = {}
if (x) {
options.numberOfSegments = 12;
}
if (y) {
options.futureOption = futureOptionValue;
}
const polygonCircle = circleToPolygon(center, radius, options)
Today I found myself looking for a GoLang library that can do what your JS one does - converting circles into polygons. I couldn't find anything, so I wrote this: https://github.com/chrusty/go-circle-to-polygon. I've completely copied your math, and am very grateful for your work!
This is not an "issue" as such - just wanted to let you know, and to say thanks.
It would be very useful if the numberOfEdges
option could accept a callback which would calculate the number of edges based on the size/radius/circumference of the circle.
The new usage might look something like this:
const circleToPolygon = require("circle-to-polygon");
const coordinates = [-27.4575887, -58.99029];
const radius = 100;
const numberOfEdges = ({ c }) => c / 4;
let polygon = circleToPolygon(coordinates, radius, { numberOfEdges });
And the definition for getNumberOfEdges
could be adjusted to this:
const DEFAULT_NUMBER_OF_EDGES = 32;
function getNumberOfEdges(radius, options) {
if (!options) return DEFAULT_NUMBER_OF_EDGES;
if (!isObjectNotArray(options)) return options;
if (typeof options.numberOfEdges === "function") {
const circumference = 2 * Math.PI * radius;
const numberOfEdges = options.numberOfEdges({ c: circumference, r: radius });
if (Number.isFinite(numberOfEdges)) return Math.round(numberOfEdges);
return DEFAULT_NUMBER_OF_EDGES;
}
return options.numberOfEdges ?? DEFAULT_NUMBER_OF_EDGES;
}
Still points to radius
instead of polygon
( see https://github.com/gabzim/circle-to-polygon/blob/master/package.json#L23 )
I am getting incorrect areas of the polygons, thus probably wrong coordinates as well. I can demonstrate the result and reproduce the error by using the Turfjs library. Beside this, I have got same result while working with Google Earth engine. (...the number of pixels showed similar deviation and magnitude of error in an image classification within this computed polygon)
const circleToPolygon = require('circle-to-polygon');
const turf = require('@turf/turf');
const coordinates = [10.278653,59.8947275]; //[lon, lat]
const radius = 1610; // in meters
const numberOfEdges =32; //optional that defaults to 32
let polygon = circleToPolygon(coordinates, radius, numberOfEdges);
let areaOfPolygon = turf.area(polygon)
let areaMath = radius * radius * Math.PI / 2
console.log(JSON.stringify(polygon))
console.log('Area by Turf: ', areaOfPolygon)
console.log('Area by math: ', areaMath)
Result:
~/projects/circle_to_polygon (master) $ node to_polygon.js
{"type":"Polygon","coordinates":[[[10.278653,59.90919037607431],[10.284280645205657,59.908912356083924],[10.28969174946274,59.90808899392172],[10.294678135098811,59.90675196982125],[10.299048023224346,59.904952723057185],[10.302633427274063,59.90276046629221],[10.30529661686024,59.90025951531567],[10.306935402293933,59.897546038387084],[10.30748703798763,59.89472435169742],[10.306930598361534,59.89190290465795],[10.305287740350176,59.889190110195436],[10.302621829553926,59.8866901806016],[10.299035469941463,59.884499128639774],[10.294666537376706,59.88270108667902],[10.2896828729499,59.881365083961555],[10.284275841271294,59.88054240426573],[10.278653,59.88026462392567],[10.273030158728705,59.88054240426573],[10.2676231270501,59.881365083961555],[10.262639462623294,59.88270108667902],[10.258270530058537,59.884499128639774],[10.254684170446074,59.8866901806016],[10.252018259649825,59.889190110195436],[10.250375401638466,59.89190290465795],[10.249818962012368,59.89472435169742],[10.250370597706066,59.897546038387084],[10.25200938313976,59.90025951531567],[10.254672572725935,59.90276046629221],[10.258257976775651,59.904952723057185],[10.26262786490119,59.90675196982125],[10.267614250537259,59.90808899392172],[10.273025354794344,59.908912356083924],[10.278653,59.90919037607431]]]}
Area by Turf: 8091097.936206874
Area by math: 4071661.1586850514
I understand that the polygon shape has a different area than a perfect circle, but the error shows approx. double area than a mathematically computed one.
Right now, the polygon returned always has its coordinates ordered counter-clockwise. It is currently not possible to get the coordinates ordered clockwise. Examples when the user might want to have the coordinates clockwise:
Add option to allow coordinates to be arranged clockwise.
This should be done after #13 has been solved.
Proposed argument:
option = { useLeftHandRule: false }
option = { useLeftHandRule: true }
Default value should default to false
when missing.
In version 2.0.0
, the validateCenter
function fails when passing a 3rd element (altitude/elevation) as the center point:
if (!Array.isArray(center) || center.length !== 2) {
throw new Error("ERROR! Center has to be an array of length two");
}
From RFC 7946
A position is an array of numbers. There MUST be two or more
elements. The first two elements are longitude and latitude, or
easting and northing, precisely in that order and using decimal
numbers. Altitude or elevation MAY be included as an optional third
element.
From @types/geojson
/**
* A Position is an array of coordinates.
* https://tools.ietf.org/html/rfc7946#section-3.1.1
* Array should contain between two and three elements.
* The previous GeoJSON specification allowed more elements (e.g., which could be used to represent M values),
* but the current specification only allows X, Y, and (optionally) Z to be defined.
*/
export type Position = number[]; // [number, number] | [number, number, number];
The center validation check should be something similar to this:
if (!Array.isArray(center) || ![2,3].includes(center.length)) {
throw new Error("ERROR! Center has to be an array of length two or three");
}
We should pick a license and add it to the project files
Is there a way to rotate the output? Currently the output results in a diamond. Ideally I'd like to rotate it 45 degrees so that it represents a square as opposed to a diamond. The bearing
option doesn't seem to do anything when I try to set that to 45.
If we call this package with the below values, it's is giving some point which cannot be plotted in the google map.
var circleToPolygon = require("circle-to-polygon")
const coordinates = [ -179.9745, -22.3023]; //[lon, lat]
const radius = 50000; // in meters
const numberOfEdges = 500; //optional that defaults to 32
let polygon = circleToPolygon(coordinates, radius, numberOfEdges);
In the result, there are some point like:
[-180.02911542185794, -21.856002776317947] (long lat format) which cannot be plotted in the google map.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.