cesium calculate heading and pitch from 2 cartesian3 points - cesiumjs

I'm trying to calculate heading and pitch using two cartesian3 points in Cesium as follwing:
getHeading(pointA,pointB){
const transform=Cesium.Transforms.eastNorthUpToFixedFrame(pointA);
const vector2=Cesium.Cartesian3.subtract(pointA,pointB,new Cesium.Cartesian3());
const vector=Cesium.Matrix4.multiplyByPoint(fixedTransform,vector2,new Cesium.Cartesian3());
const direction=Cesium.Cartesian3.normalize(vector,new Cesium.Cartesian3());
const heading=Math.atan2(direction.y,direction.x)-Cesium.Math.PI_OVER_TWO;
return Cesium.Math.toDegrees(Cesium.Math.TWO_PI-Cesium.Math.zeroToTwoPi(heading));
}
but it dont work,Can anyone give me some advice? Thank you!

solution:
getHeading(pointA:Cesium.Cartesian3,pointB:Cesium.Cartesian3){
const transform=Cesium.Transforms.eastNorthUpToFixedFrame(pointA);
const positionvector=Cesium.Cartesian3.subtract(pointB,pointA,new Cesium.Cartesian3());
const vector=Cesium.Matrix4.multiplyByPointAsVector(Cesium.Matrix4.inverse(transform,new Cesium.Matrix4()),positionvector,new Cesium.Cartesian3());
const direction=Cesium.Cartesian3.normalize(vector,new Cesium.Cartesian3());
//heading
const heading=Math.atan2(direction.y,direction.x)-Cesium.Math.PI_OVER_TWO;
//pitch
const pitch=Cesium.Math.PI_OVER_TWO-Cesium.Math.acosClamped(direction.z);
return Cesium.Math.toDegrees(Cesium.Math.TWO_PI-Cesium.Math.zeroToTwoPi(heading));
}

Related

Autodesk Forge - Absolute coordinates

from the Forge viewer is it possible to retrieve the absolute coordinates of the objects?
With the following code I was able to obtain the relative coordinates of the selected object:
const viewer = NOP_VIEWER;
const dbId = NOP_VIEWER.getSelection()[0];
const selSet = viewer.getSelection();
const targetElem = selSet[0];
const model = viewer.model;
const instanceTree = model.getData().instanceTree;
const fragList = model.getFragmentList();
let bounds = new THREE.Box3();
instanceTree.enumNodeFragments( dbId, ( fragId ) => {
let box = new THREE.Box3();
fragList.getWorldBounds( fragId, box );
bounds.union( box );
}, true );
const position = bounds.center();
With the getAecModelData method I was able to retrieve the refPointTransformation:
What do the values ​​in this array refer to?
TIA
Alder
I'm not sure what exactly you mean by absolute coordinates but if we're talking about geolocation, note that there's actually a Geolocation extension for the viewer:
https://forge.autodesk.com/en/docs/viewer/v6/reference/Extensions/GeolocationExtension
The extension leverages the refPointTransformation in AEC Model Data, letting you transform lat/long (WGS84) coordinates to viewer coordinates and vice versa.
Here's a related blog post that might also help: https://forge.autodesk.com/blog/mini-map-geolocation-extension.

SyntaxError when trying to change files (JSON)

This code has suddenly stopped working in Visio Studio Code. it is suppose to change the JSON file text I got this code from https://www.youtube.com/watch?v=OWdyi5EGxq4. here's the code below. Help would be appreciated thanks.
const fs = require("fs");
const { json } = require("stream/consumers");
const args = process.argv.slice(2);
const inputFolder = args[0];
const dir = `${__dirname}/${inputFolder}/`;
const inputFiles = fs.readdirSync(dir).sort();
inputFiles.forEach((file) => {
let id = file.split(".").shift();
let data = JSON.parse(fs.readFileSync(`${dir}/${file}`));
data.name = `ipfwork/${id}`;
fs.writeFileSync(`${dir}/${file}`, JSON.stringify(data, null, 2));
console.log(data);
});

Google Place Autocomplete - geometry bounds properties

I cannot find this answer in the Google docs so I am posting my question here.
As per the Google Places Autocomplete response docs, bounds is one of the returned fields.
However, when console logging bounds in the browser, the object has strangely named keys such as Ba, Ab, Ra and so on..
Furthermore, I have noticed that these keys change overtime.
For example, the following code might fail within a few days. In the initial search for say, New York, bounds.Ab.g may contain a number value.
however, after a few days bounds.Ab.g might become bounds.Bb.g and the original value will be undefined.
import PlacesAutocomplete, { geocodeByAddress } from 'react-places-autocomplete'
const GooglePlacesSearchBar = () => {
const handleSelect = async userInput => {
const result = await geocodeByAddress(userInput)
const { place_id, geometry, formatted_address } = result[0]
const { bounds } = geometry
const swBounds = [bounds.Ab.g, bounds.Ra.g]
const neBounds = [bounds.Ab.h, bounds.Ra.h]
...
}
This is an example of the bounds object printed in console.
bounds: _.Wf
Bb: Vf
g: 49.19817700000001
h: 49.3172939
[[Prototype]]: Object
Ra: Qf
g: -123.22474
h: -123.023068
Could anyone point to a doc or explain what these keys stand for and why they keep changing?
thanks to #geocodezip for the answers in the comments section.
here is the solution
const result = await geocodeByAddress(userInput)
const { geometry } = result[0]
const { bounds } = geometry
const NELat = bounds.getNorthEast().lat()
const NELng = bounds.getNorthEast().lng()
const SWLat = bounds.getSouthWest().lat()
const SWLng = bounds.getSouthWest().lng()
Strange decision by Google indeed.

How to change the color of sphere objects dynamically (used SceneBuilder in Autodesk forge)

I am working on the example from Custom models in Forge Viewer blog by Petr Broz. I am facing issue in updating the color of sphere objects dynamically. I am getting the value of sphere's color from a json file like this "color": "#FF0000". I have created 3 spheres and I am getting the color of first sphere for the rest also. Why the color is not updating for the other spheres? If the problem is on using same material then I tried giving the sphereMaterial in array also as shown below. Is that wrong or how can i update the color?
var spherecolor='';
var sphereMaterial = [];
const button = document.getElementById('button-geometry');
button.addEventListener('click', async function () {
const sceneBuilder = await viewer.loadExtension('Autodesk.Viewing.SceneBuilder');
const modelBuilder = await sceneBuilder.addNewModel({ conserveMemory: true, modelNameOverride: 'My Custom Model' });
for (var i = 0; i < numOfSphere;i++) {
addGeometry(modelBuilder, jsonGeomConfig.geom[i].dbId, i);
}
});
function addGeometry(modelBuilder, dbId, i) {
const sphereGeometry = new THREE.BufferGeometry().fromGeometry(new THREE.SphereGeometry(0.05, 8, 10));
//Getting spherecolor from json file
spherecolor = jsonGeomConfig.geom[i].color;
sphereMaterial[i] = new THREE.MeshPhongMaterial({ color: spherecolor });
const sphereTransform = new THREE.Matrix4().compose(
new THREE.Vector3(jsonGeomConfig.geom[i].Position.posX, jsonGeomConfig.geom[i].Position.posY, jsonGeomConfig.geom[i].Position.posZ),
new THREE.Quaternion(0, 0, 0, 1),
new THREE.Vector3(2,2,2)
);
modelBuilder.addMaterial('MyCustomMaterial', sphereMaterial[i]);
const sphereGeomId = modelBuilder.addGeometry(sphereGeometry);
const sphereFragId = modelBuilder.addFragment(sphereGeomId, 'MyCustomMaterial', sphereTransform);
modelBuilder.changeFragmentsDbId(sphereFragId, dbId);
}
Be sure to give the materials with different colors different names ... otherwise it'd get overridden - see this live environment:
modelBuilder.addMaterial('MyCustomMaterial'+i, sphereMaterial[i]);
const sphereGeomId = modelBuilder.addGeometry(sphereGeometry);
const sphereFragId = modelBuilder.addFragment(sphereGeomId, 'MyCustomMaterial'+i, sphereTransform);

How to handle circularly dependent observables in RxJS?

Let's say e.g. that somewhere on a server there is a mapping between
integers and names and a web page provides a simple input where a user
can enter a number and is given the corresponding name.
In its basic form, this problem is simple:
const input$ = Rx.Observable.fromEvent(..., "input");
const request$ = input$.map( ... );
const serverResponse$ = request$.flatMap( askServer );
Now I would like to cache the results so that a request is only
done when the number is not in the cache.
const input$ = Rx.Observable.fromEvent(..., "input");
// request$ should now also depend on cache$
const request$ = ???;
const serverResponse$ = request$.flatMap( askServer );
const cache$ = serverResponse$.scan( ... );
But now request$ depends on cache$ which depends on a serverResponse$
which in turn depends on request$.
How do I solve this problem?
Introduce a Subject as a proxy at some point in the cycle in the dependency graph, then mirror the behavior of the real Observable (cache$) onto the proxy Subject (proxyCache$).
const input$ = Rx.Observable.fromEvent(..., "input");
const proxyCache$ = new Rx.Subject();
const request$ = input$.merge(proxyCache$).map( ... );
const serverResponse$ = request$.flatMap( askServer );
const cache$ = serverResponse$.scan( ... );
cache$.subscribe(proxyCache$);