how to use computeArea to calculate the area of a circle? - google-maps-api-3

google maps geometry library provides a function:
computeArea(loop:Array.|MVCArray., radius?:number)
which seems can calculate the area of a circle by providing the radius, but no matter how I tried, it didn't seem to work. Any help of how I can use the function?
BTW, fowllowing is a sample of calculating the area of a polygon:
var nyc = new google.maps.LatLng(40.715, -74.002);
var london = new google.maps.LatLng(51.506, -0.119);
var rio = new google.maps.LatLng(-22.916, -43.251);
var area = google.maps.geometry.spherical.computeArea([nyc, london, rio]);

That is not the radius to calculate the area of a circle. This function only computes the area of a polygon. The radius parameter is the radius of the earth. The default value is 6378137 meters. If you want the area returned in km, ft, miles, etc you provide the earths radius in the desired unit.

The formula for a circle doesn't require the Google Maps API, you can simply calculate it using Math.PI in JavaScript:
function area (radius){
return radius*radius*Math.PI
}
Math.PI is built into JavaScript.

Related

How to cover the US map with minimum number of 30 mile radius circles?

I have a big data set of coordinates and would like to place them into a groups falling under 30 mile radius circles. And I need these circles to cover entire US land area. Overlapping circles are allowed. Is there a way to do this? Any help would be much appreciated. Thank you.
I wrote an npm package a while back that will help you work with locations on earth.
You can see a jsfiddle I made that makes random points on a circle centered at some location. The code below is pasted from the jsfiddle because SO wants code when you include a fiddle link, but you are better off to go experiment with the fiddle. The function pointAtDistance() implements the Haversine formula.
For the packing, I'd attempt a hexagon formation - make a grid and eliminate those that don't intersect land. As the earth is a sphere, you should probably find the number of degrees longitude closest to the equator that represents your offset so that 30 mile circles still overlap. Then using that angle, the circles further north will overlap more than needed, but at least there won't be gaps, and the structure is easy to reason about.
function pointAtDistance(inputCoords, distance) {
const result = {}
const coords = toRadians(inputCoords)
const sinLat = Math.sin(coords.latitude)
const cosLat = Math.cos(coords.latitude)
const bearing = Math.random() * TWO_PI
const theta = distance/EARTH_RADIUS
const sinBearing = Math.sin(bearing)
const cosBearing = Math.cos(bearing)
const sinTheta = Math.sin(theta)
const cosTheta = Math.cos(theta)
result.latitude = Math.asin(sinLat*cosTheta+cosLat*sinTheta*cosBearing);
result.longitude = coords.longitude +
Math.atan2( sinBearing*sinTheta*cosLat, cosTheta-sinLat*Math.sin(result.latitude )
);
result.longitude = ((result.longitude+THREE_PI)%TWO_PI)-Math.PI
return toDegrees(result)
}

Calculate empty space of a polygon

I'm currently working on a project in Openlayers where we allow the users to draw polygon-shapes. These shapes are only allowed to be drawn inside another polygon which for clarity i will call the Trackable-Area. To meet one of the requirements of the customer, i need to find the empty space of the Trackable-Area. I've already achieved finding the area size of the empty space, but i am lost on how to calculate the empty space as a polygon.
Please see the following picture as an example. The "rectangle" is the Trackable-Area polygon, and the colorful shapes are the drawn polygons made by the user. The white space is what i aim to calculate as another polygon.
I found a solution to this by creating a multipolygon containing all drawn polygons, and then utilizing the JSTS-library to calculate the difference between the multipolygon and trackable-area polygon:
// map JSTS GeoJSON-readers
const jstsGeoJSONReader = new jsts.io.GeoJSONReader();
const jstsGeoJSONWriter = new jsts.io.GeoJSONWriter();
// ol GeoJSON-format
const geoJSONFormat = new GeoJSON();
let trackableAreaFeature;
let trackableAreaGeomJSTS;
// trackable area geometry parsed to JSTS
const TrackableAreaLayer = this.mapService.getLayerByName(LAYERS.TRACKABLE_AREA);
trackableAreaFeature = TrackableAreaLayer.getSource().getFeatureById('Trackable Area');
trackableAreaGeomJSTS = jstsGeoJSONReader.read(geoJSONFormat.writeFeatureObject(trackableAreaFeature)).geometry;
// create multiPolygon consisting of drawn zones
const multiPolygon = new MultiPolygon([]);
const zoneSource = drawnAreaLayer.getSource();
const zoneFeatures = drawnAreaLayer.getSource().getFeatures();
zoneFeatures.forEach(zone => {
const zoneGeometry = zone.getGeometry();
multiPolygon.appendPolygon(zoneGeometry);
});
// parse multipolygon to JSTS
const multiPolygonJSTS = jstsGeoJSONReader.read(geoJSONFormat.writeGeometry(multiPolygon));
// calculate difference between trackable area and multipolygon
const unmappedAreaJSTS = trackableAreaGeomJSTS.difference(multiPolygonJSTS);
const unmappedAreaGeometry = jstsGeoJSONWriter.write(unmappedAreaJSTS);
// parse multipolygon from GeoJSON to ol geometry
const unmappedAreaMultiPolygonGeometry = geoJSONFormat.readGeometry(unmappedAreaGeometry);
// create ol feature based on parsed geometry
const unmappedAreaFeature = new Feature({
geometry: unmappedAreaMultiPolygonGeometry
});
// add Feature to source of layer
zoneSource.addFeature(unmappedAreaFeature);
One possibility would be to delete de area of the trackable area (T) with the summed area of all the polygons drawn by the user inside the trackable area (S).
E = T - S, where E is the empty area.
En the newest version fo the library, you just need to use the function getArea (OL API Docs - Polygon getArea).

How to determine if point is inside box (three.js)?

If we have NON-axis-aligned box, how can we best check if a point lies inside it? (I'm using three.js, so any utility from there can be of help. Three.js contains bounding box concept, but that is axis-aligned bounding box)
If your box is a THREE.BoxGeometry that is rotated, translated and scaled, then you can use its transformation matrix m to find if it intersects your point v:
transform v and the box by the inverse of m
check if transformed v is inside the transformed box (which is now axis aligned)
Here is the code:
var box = <Your non-aligned box>
var point = <Your point>
box.geometry.computeBoundingBox(); // This is only necessary if not allready computed
box.updateMatrixWorld(true); // This might be necessary if box is moved
var boxMatrixInverse = new THREE.Matrix4().getInverse(box.matrixWorld);
var inverseBox = box.clone();
var inversePoint = point.clone();
inverseBox.applyMatrix(boxMatrixInverse);
inversePoint.applyMatrix4(boxMatrixInverse);
var bb = new THREE.Box3().setFromObject(inverseBox);
var isInside = bb.containsPoint(inversePoint);
And here is a running demonstration: https://jsfiddle.net/holgerl/q0z979uy/

Getting the bounding box or centers of models

I was wondering if there was a way to obtain the bounding box for the models that are inserted via 3dio.js, or otherwise calculate their center points? I'm looking to center them on the origin.
The images below show two models relative to the scene origin indicated by the red box.
You can access the three.js object of the 3d.io entity like this:
var threeElem = document.getElementById("custom-id").components['io3d-data3d'].data3dView.threeParent
Then you can use the native bounding box from three.js:
var bbox = new THREE.Box3().setFromObject(threeElem)
Like that you get the min/max bounds which you can use to determine the origin.
I hope that answers your question. Let me know!
Edit:
for furniture it would probably be
var threeElem = document.getElementById("custom-id").components['io3d-furniture'].data3dView.threeParent
Based on Madlaina's answer. I needed to ensure the model was loaded before
addModelToScene(type) {
let scene = document.querySelector('a-scene');
let model = document.createElement('a-entity');
model.setAttribute('io3d-data3d', getModelKey(type) )
model.addEventListener('model-loaded', () => {
// Access the three.js object of the 3d.io
let threeElem = model.components['io3d-data3d'].data3dView.threeParent
// create the bounding box
let bbox = new THREE.Box3().setFromObject(threeElem)
// Calculate the center-point offsets from the max and min points
const offsetX = (bbox.max.x + bbox.min.x)/2
const offsetY = (bbox.max.y + bbox.min.y)/2
const offsetZ = (bbox.max.z + bbox.min.z)/2
// apply the offset
model.setAttribute('position', {x:-offsetX,y:-offsetY, z:-offsetZ})
} );
scene.appendChild(model);
}
The result:

google maps api v3 - nearest streetview

When streetview is not available for a certain location, I would like to find the nearest possible location with streetview?
The only way I could think of is.
radius = 0;
noOfPoints = 3;
while(radius < 10 miles){
radius = radius + 0.2 miles
points = calculate 4 * noOfPoints at this radius
loop(points)
{
if(streetview visibile for point)
bingo, break;
}
break if bingo;
noOfPOints = noOfPoints+1;
}
But this is ridiculously expensive even if I want to find streetview within a 10-mile radius and I am counting on luck to find streetview at one of these points, i.e, I could just miss an actual point with streetview.
can somebody please direct me towards a better approach??
You can try to use the StreetViewService to help you find a nearest existing street view:
var astorPlace = new google.maps.LatLng(40.729884, -73.990988);
var webService = new google.maps.StreetViewService();
/**Check in a perimeter of 50 meters**/
var checkaround = 50;
/** checkNearestStreetView is a valid callback function **/
webService.getPanoramaByLocation(astorPlace,checkaround ,checkNearestStreetView);
function checkNearestStreetView(panoData){
if(panoData){
if(panoData.location){
if(panoData.location.latLng){
/**Well done you can use a nearest existing street view coordinates**/
}
}
}
/** Else do something... **/
}

Resources