Get intersection element in BabylonJS - intersection

Is there a way to get the actual intersection of to geometries with BabylonJS?
E.g. the intersection point of a line and a plane, the line intersection of two planes, the arc intersection of a sphere and a plane, etc...
Thanks!

I believe what you are looking for is the CSG (Constructive Solid Geometry) tools in Babylon.js. To use it you can reference this tutorial here.
Essentially what you want to do is the following:
CSG intersect (modified code from the link)
// a and b can be any mesh you define
var a = BABYLON.Mesh.CreateBox("box", 500, scene);
var b = BABYLON.Mesh.CreateBox("box", 500, scene);
// Convert to CSG meshes
var aCSG = BABYLON.CSG.FromMesh(a);
var bCSG = BABYLON.CSG.FromMesh(b);
var subCSG = bCSG.intersect(aCSG);
// Disposing original meshes since we don't want to see them on the scene
a.dispose();
b.dispose();
// Convert back to regular mesh from CSG mesh
subCSG.toMesh("csg", new BABYLON.StandardMaterial("mat", scene), scene);
For more uses of CSG you should check out the documentation.

Related

Cesium convert lat lon to x and y

I am looking to turn 2 lat/lon positions into an x and y distance of the canvas, then apply the distance formula to it.
Right now I have:
const leftPoint = new LatLon(center.lat, center.lon).destinationPoint(semiMajorAxis, 270);
const rightPoint = new LatLon(center.lat, center.lon).destinationPoint(semiMajorAxis, 90);
const leftXY = Cartographic.toCartesian(Cartographic.fromDegrees(leftPoint.lon, leftPoint.lat));
const rightXY = Cartographic.toCartesian(Cartographic.fromDegrees(rightPoint.lon, rightPoint.lat));
const diameter = distanceFormula(leftXY.x, leftXY.y, rightXY.x, rightXY.y);
But the result of diameter is 18,000, even though both points are on my screen!
Cesium's Cartographic.toCartesian function converts a Cartographic (lon/lat/alt) type of coordinate to a full 3D Cartesian position. Imagine X, Y, Z with zero being the center of the Earth itself, with the Earth's surface being approximately 6.3 million meters in any direction.
If you're looking for 2D canvas / screen coordinates, you must follow this call with another function, Cesium.SceneTransforms.wgs84ToWindowCoordinates. That function converts the 3D WGS84 (Cartesian3) Earth position into a 2D (Cartesian2) screen position. There's a demo of wgs84ToWindowCoordinates being used in the Sandcastle Star Burst Example around line 287.
Also it looks like you've rolled your own LatLon class, not specified above, that appears to have similar functions to Cesium's Cartographic class. You might be able to make the code a little cleaner by using Cartographic directly instead of a homebrew class there. Likewise you don't need to roll your own distanceFormula on the last line. Once you have 2D Cartesian2 window coordinates, call Cesium.Cartesian2.distance to get the distance.
I can't understand your saying 'x and y distance of the canvas'.
Generally, for calculate distance between two point on CesiumJS follow below steps.
1.Define two points
//Define x,y coordinate and convert to radian
const longitudeRadian_1 = Cesium.Math.toRadians(longitudeDegree_1)
const latitudeRadian_1 = Cesium.Math.toRadians(latitudeDegree_1)
const longitudeRadian_2 = Cesium.Math.toRadians(longitudeDegree_2)
const latitudeRadian_2 = Cesium.Math.toRadians(latitudeDegree_2)
//Get cartographic from degrees
const Carto_Point_1 = new Cesium.Cartographic(longitudeRadian_1 , latitudeRadian_1 )
const Carto_Point_2 = new Cesium.Cartographic(longitudeRadian_2 , latitudeRadian_2)
//Get cartesian from cartographic
const Cartesian_Point_1 = Cesium.Cartographic.toCartesian(Carto_Point_1)
const Cartesian_Point_2 = Cesium.Cartographic.toCartesian(Carto_Point_2)
2.Calculate distance between two points
const distance = Cesium.Cartesian3.distance(Cartesian_Point_1, Cartesian_Point_2)
console.log(distance)
I hope this would help

How can I scale my map to fit my svg size with d3 and geojson path data

I am trying to create a d3 SVG that draws a map of New York State and scale it so that it fits the size of my SVG, the issue I am having is that when I use .fitSize([height, width], mapObject) it only returns a NaN error in the console.
the topoJSON file of NYS I am using
I am able to get the map to display without scaling but of course, it is not optimized and needs to be scaled
I have attempted what is said in this post but I have not figured out the correct solution
var map = d3.json('./ny.json')
Promise.all([map]).then(data => {
var height = 800;
var width = 800;
var mapData = data[0]
// original geoJSON to that works without scaling
// var geoData = topojson.feature(mapData, mapData.objects["cb_2015_new_york_county_20m"]).features
//
var geoData = topojson.feature(mapData, {
type:"GeometryCollection",
geometries: mapData.objects["cb_2015_new_york_county_20m"].geometries,
})
var projection = d3.geoMercator()
.fitSize([width, height], geoData)
var path = d3.geoPath()
.projection(projection)
d3.select('svg')
.attr('height', height)
.attr('width', width)
.selectAll('.county')
.data(geoData)
.enter()
.append('path')
.classed('.county', true)
.attr('d', path)
})
I am pretty sure this is a formatting error on my part, but I am unsure of what data .fitSize() or .fitExtent() is trying to compare against.
right now the way the code site I receive no error outputted to the console but I also have no data append to the SVG
The issue is that fitSize takes a geojson object while selectAll.data() takes an array, you are using one of these two for both in geoData. This leaves two solutions:
Solution 1:
If we use
var geoData = topojson.feature(mapData, mapData.objects["cb_2015_new_york_county_20m"]).features
var projection = d3.geoMercator()
.fitSize([width, height], geoData)
We get NaN errors because the projection is not set properly as we aren't passing a geojson object, just an array of geojson objects. We could solve this by making a feature collection with geoData and passing that to fitSize:
var geoData = topojson.feature(mapData, mapData.objects["cb_2015_new_york_county_20m"]).features
var projection = d3.geoMercator()
.fitSize([width, height], {type:"FeatureCollection", features: geoData})
Now we are passing a geojson feature collection to fitSize, we're all go on the projection, and since geoData is still an array, we can pass that to selectAll.data() unchanged.
Here's a block.
Solution 2:
If we use:
var geoData = topojson.feature(mapData, {
type:"GeometryCollection",
geometries: mapData.objects["cb_2015_new_york_county_20m"].geometries,
})
We get a geojson object, projection.fitSize works, but selectAll().data(geoData) doesn't add any features as it isn't an array - the enter selection is empty. We can substitute in selectAll().data(geoData.features) to solve this and enter one path per feature (alternatively we could use .data([geoData]) to enter one feature for all the paths).
Here's a block.
Both blocks are drawn at the correct scale - the map exceeds the block bounds as I didn't alter your 800x800 dimensions

Drawing multiple things in webGl

my task is to draw multiple circle at different points on the canvas. I have the circles vertices, but i can't seem to figure out how to draw all of them at the same time. I can draw each one separately, but not all five that I need.
My code looks like this
var vertices = [];
var blueCircle = drawCircle(-50,-50,200);
var yellowCircle= drawCircle(50,50,200);
var blackCircle= drawCircle(50,50,200);
var greenCircle= drawCircle(50,50,200);
var redCircle= drawCircle(50,50,200);
vertices.push(blueCircle);
vertices.push((yellowCircle);
vertices.push(blackCircle);
vertices.push(greenCircle);
vertices.push(redCircle);
This gives me a Vertices array that is made up of each circle array, as in
vertices:(5) [Array(2272), Array(2272), Array(2272), Array(2272), Array(2272)]
Is there a way for me to add each array in its components? As in have a vertices array that is made up of all 11360 elements?
If not, how could I possibly loop through the multidimensional array and draw each point using
gl.DrawArrays(GL_POINTS, number, number);

Projection drift when rendering in WebGL over Google Map

I am trying to implement a WebGL-based rendering on Google Map (api3) as I want to render a massive amount of dynamic geometries.
Basically, I create a google.maps.OverlayView attached with a WebGL canvas into the map.
However, I encountered some problem with the mapping of the projection. Basically, I extracted the "fromLatLngToPoint" function from the googlemap api as follows:
function fromLatLngToPoint(a){
var c={x:0,y:0},
d=this.j;
c.x=d.x+a.lng*this.B;
var e=oe(m.sin(re(a.lat)),-(1-1E-15),1-1E-15);
c.y=d.y+.5*m.log((1+e)/(1-e))*-this.F;
return c
}
function oe(a,b,c){null!=b&&(a=m.max(a,b));null!=c&&(a=m.min(a,c));return a}
function re(a){return m.PI/180*a}
Then I implemented it in my vertex shader based on the documentation in Google Map Coordinates.
Basically, I have a event listener to send the updated projection constants, the viewport bounds, and the zoom level to my shader.
Then my shader will calculate the new screen coordinates based on these inputs.
highp float e, x, y, offsetY, offsetX;
// projection transformation for target points
e = sin(p.y* PI/180.0);
y = prj_y + 0.5 * log((1.0+e)/(1.0-e))*(-F);
x = prj_x + p.x*B;
// projection transformation for offset (bounds)
e = sin(bound_y*PI/180.0);
offsetY = prj_y + 0.5 * log((1.0+e)/(1.0-e))*(-F);
offsetX = prj_x + bound_x*B;
// calculate actual pixel coord wrt zoom/numTiles
x = (x* numTiles - offsetX* numTiles);
y = (y* numTiles - offsetY* numTiles);
gl_PointSize = 5.0;
gl_Position = projectionMatrix * modelViewMatrix * vec4(x,y,0.0,1.0);
However, as shown in the screenshot below, it seems there are some errors? The rendered geometries are distorted. (I used the google map polygon api to render some of the geometries as comparison)
Screenshot Here
I am totally at a loss, what might be the reason for this distortion?
I am suspecting that the single precision in the shader is giving rise to the error. So I am wondering if there is any workaround?
It is hard to debug this piece of code and diagnose the cause of the issue. I would suggest you using the CanvasLayer library that hides all these concrete details of specifying the coordinates you want to draw the polygon. Rather you would be able to focus on your app code and functionality. The performance will be better in terms of projected image.

AS3 drawing lines, making shorter after that

i have a little math/coding problem witch i don`t have any idea how could i do it work in a simple way, so the problem is is need to make a line shorter, with 15
in my program i have :
http://gyazo.com/aff5ff61fb9ad3ecedde3118d9c0895e
the line takes the center coordinates of both circles and draws from one to another, but i need it to be from the circumference of the circles, so it wont get inside
the code im using is :
var line:Shape = new Shape();
line.graphics.lineStyle(3,0xFF0000,2);
line.graphics.moveTo(sx,sy);
line.graphics.lineTo(fx,fy);
this.addChild(line);
arrow2(sx,sy,fx,fy);
var rline:Shape = new Shape();
rline.graphics.lineStyle(3,0xFF0000,2);
rline.graphics.moveTo(fx,fy);
rline.graphics.lineTo(xa,ya);
this.addChild(rline);
var rline2:Shape = new Shape();
rline2.graphics.lineStyle(3,0xFF0000,2);
rline2.graphics.moveTo(fx,fy);
rline2.graphics.lineTo(xb,yb);
this.addChild(rline2);
the rline and rline2 function is for the arrow lines, now my question is how do i make it shorter not depending on it direction so it will not overlap the circle
You can use vectors to solve your problem; they're pretty easy to get the hang of, and pretty much indispensable for things like game dev or what you're trying to do. You can get an overview here: http://www.mathsisfun.com/algebra/vectors.html or by searching "vector math" in google
So first step is to get a vector from one circle to another (pretty much what you've done):
var vector:Point = new Point( circle2.x - circle1.x, circle2.y - circle1.y );
var length:Number = vector.length; // store the length of the vector for later
This is the equivalent of saying "if you start at circle1 and move along vector, you'll arrive at circle2"
Next thing we're going to do is normalise it; all this does is set the length to 1 - the direction is unchanged - this makes it easier to work with for what you're looking to do. A vector with length 1.0 is called a unit vector:
vector.normalize( 1.0 ); // you can pass any length you like, but for this example, we'll stick with 1.0
Now, to draw a line from one circle to another, but starting from the outside, we simply find the start and the end points. The starting point is simple the position of circle1 plus vector (normalised to unit length) multiplied by the radius of circle1:
var sx:Number = circle1.x + vector.x * circle1.radius; // or circle1.width * 0.5 if you don't store the radius
var sy:Number = circle1.y + vector.y * circle1.radius;
The ending point can be found by starting at our start point, and continuing along our vector for a distance equal to the distance between the two circles (minus their radii). The length value that we created earlier is the distance between your two circles, from one center point to another, so we can use that to get the distance minus the radii:
var dist:Number = length - ( circle1.radius + circle2.radius ); // or circle1.width * 0.5 etc
And so the end point:
var ex:Number = sx + vector.x * dist;
var ey:Number = sy + vector.y * dist;
And to draw the line between them:
var line:Shape = new Shape;
line.graphics.lineStyle( 1.0, 0x000000 );
line.graphics.moveTo( sx, sy );
line.graphics.lineTo( ex, ey );
this.addChild( line )