Rotate object and fit to screen - aframe

I have raw obj and mtl files from photogrammetry.
They have different sizes and orientation.
The goal is to change the size and orientation for it to fill the screen.
Orientation is to be calculated assuming that the flattest area is defined as ground and anomalies from there, ie bumps, which are likely the desired objects, are to be aligned with the Y-axis point up.
The first approach was to use a bounding box
var el = document.querySelector('#aentity');
var object = el.getObject3D('tree-obj');
// compute bounding box
var bbox = new THREE.Box3().setFromObject(object);
console.log(bbox.min, bbox.max)
to get the size and scale it accordingly.
This already fails with
three.js:3819
Uncaught TypeError: Cannot read properties of undefined (reading 'updateWorldMatrix')
at Box3.expandByObject (three.js:3819:1)
at Box3.setFromObject (three.js:3766:1)
at file.html:25:29
line 25:
var bbox = new THREE.Box3().setFromObject(object);

Related

image.filter is not a function in google earth engine

As a newbie to the google earth engine, I have been trying something (https://code.earthengine.google.com/6f45059a59b75757c88ce2d3869fc9fd) following a NASA tutorial (https://www.youtube.com/watch?v=JFvxudueT_k&ab_channel=NASAVideo). My last line (line 60) shows image.filter is not a function, while the one in the tutorial (line 34) is working. I am not sure what happened and how to sort this out?
//creating a new variable 'image' from the L8 collection data imported
var image = ee.Image (L8_tier1 //the details in the data will represent that the band resolution is 30m
//the details in the data will represent that the band resolution is 30m
//.filterDate ("2019-07-01","2021-10-03") //for a specific date range. maybe good to remove it for the function.
//the details in the data will represent that the band resolution is 30m
//the details in the data will represent that the band resolution is 30m
//.filterDate ("2019-07-01","2021-10-03") //for a specific date range. maybe good to remove it for the function.
.filterBounds (ROI) //for the region of interest we are interested in
//.sort ("COLUD_COVER") //for sorting the data between the range with a cloud cover, the metadata property we are interested in. Other way to do this is using the function below.
//.first() //this will make the image choose the first image with the least amount of cloud cover for the area. Other way to do this is using the function below.
);
//print ("Hague and Rotterdam", image); //printing the image in the console
//console on the right hand side will explain everything from the data
//id will show the image deatils and date of the image, for this case 29th July 2019
//under the properties tab cloud cover can be found, this is the least we can get for this area during this period
// //vizualisation of the data in the map with true color rendering
// var trueColour = {
// bands:["SR_B4","SR_B3","SR_B2"],
// min: 5000,
// max: 12000
// };
// Map.centerObject (ROI, 12); //for the centering the area in the center of the map with required zoom level
// Map.addLayer (image, trueColour, "Hague and Rotterdam"); //for adding the image with the variable of bands we made and naming the image
//Alternate way
//Function to cloud mask from the qa_pixel band of Landsat 8 SR data. In this case bits 3 and 4 are clouds and cloud shadow respectively. This can be different for different image sets.
function maskL8sr(image) {
var cloudsBitMask = 1 << 3; //remember to check this with the source
var cloudshadowBitMask = 1 << 4; //remember to check this with the source
var qa = image.select ('qa_pixel'); //creating the new variable from the band of the source image
var mask = qa.bitwiseAnd(cloudsBitMask).eq(0) //making the cloud equal to zero to mask them out
.and(qa.bitwiseAnd(cloudshadowBitMask).eq(0)); //making the cloud shadow equal to zero to mask them out
return image.updateMask(mask).divide(10000)
.select("SR_B[0-9]*")
.copyProperties(image, ["system:time_start"]);
}
// print ("Hague and Rotterdam", image);// look into the console now. How many images the code have downloaded!!!
//filtering imagery for 2015 to 2021 summer date ranges
//creating joint filter and applying to image collection
var sum21 = ee.Filter.date ('2021-06-01','2021-09-30');
var sum20 = ee.Filter.date ('2020-06-01','2020-09-30');
var sum19 = ee.Filter.date ('2019-06-01','2019-09-30');
var sum18 = ee.Filter.date ('2018-06-01','2018-09-30');
var sum17 = ee.Filter.date ('2017-06-01','2017-09-30');
var sum16 = ee.Filter.date ('2016-06-01','2016-09-30');
var sum15 = ee.Filter.date ('2015-06-01','2015-09-30');
var SumFilter = ee.Filter.or(sum21, sum20, sum19, sum18, sum17, sum16, sum15);
var allsum = image.filter(SumFilter);
Filtering is an operation you can do on ImageCollections, not individual Images, because all filtering does is choose a subset of the images. Then, in your script, you have (with the comments removed):
var image = ee.Image (L8_tier1
.filterBounds (ROI)
);
The result of l8_tier1.filterBounds(ROI) is indeed an ImageCollection. But in this case, you have told the Earth Engine client that it should be treated as an Image, and it believed you. So, then, the last line
var allsum = image.filter(SumFilter);
fails with the error you saw because there is no filter() on ee.Image.
The script will successfully run if you change ee.Image(...) to ee.ImageCollection(...), or even better, remove the cast because it's not necessary — that is,
var image = L8_tier1.filterBounds(ROI);
You should probably also change the name of var image too, since it is confusing to call an ImageCollection by the name image. Naming things accurately helps avoid mistakes, while you are working on the code and also when others try to read it or build on it.

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:

how to generate a map based on a given scale [Bing Map]?

I recently started working with [Bing Api] in my webService [wcf] in c #.
I would like to recover a satellite image of a given scale with Bing!
for example
Scale 1:200 (1 centimeter on the map equal 200 centimeters on the world)
Of course I found this function that explains how to calculate the image resolution satellite bing but this is not what I'm looking for ..
Map resolution = 156543.04 meters/pixel * cos(latitude) / (2 ^ zoomlevel)
Here is my function used to generate my bing map, but I do not know what to send parameter to retrieve an image scale of 1:200.
I need :
Scale = 1:200
I search :
int mapSizeHeight = ?
int mapSizeWidth = ?
int zoomLevel = ?
public string GetImageMap(double latitude,double longitude,int mapSizeHeight, int mapSizeWidth, int zoomLevel)
{
string key = "ddsaAaasm5vwsdfsfd2ySYBxfEFsdfsdfcFh6iUO5GI4v";
MapUriRequest mapUriRequest = new MapUriRequest();
// Set credentials using a valid Bing Maps key
mapUriRequest.Credentials = new ImageryService.Credentials();
mapUriRequest.Credentials.ApplicationId = key;
// Set the location of the requested image
mapUriRequest.Center = new ImageryService.Location();
mapUriRequest.Center.Latitude = latitude;
mapUriRequest.Center.Longitude = longitude;
// Set the map style and zoom level
MapUriOptions mapUriOptions = new MapUriOptions();
mapUriOptions.Style = MapStyle.Aerial;
mapUriOptions.ZoomLevel = zoomLevel;
mapUriOptions.PreventIconCollision = true;
// Set the size of the requested image in pixels
mapUriOptions.ImageSize = new ImageryService.SizeOfint();
mapUriOptions.ImageSize.Height = mapSizeHeight;
mapUriOptions.ImageSize.Width = mapSizeWidth;
mapUriRequest.Options = mapUriOptions;
//Make the request and return the URI
ImageryServiceClient imageryService = new ImageryServiceClient();
MapUriResponse mapUriResponse = imageryService.GetMapUri(mapUriRequest);
return mapUriResponse.Uri;
}
If you haven't already, you might want to check out this article on the Bing Maps tile system calculations, within you will find a section discussing ground resolution and map scale. From that article:
map scale = 1 : ground resolution * screen dpi / 0.0254 meters/inch
Depending on which implementation of Bing Maps you use, specifying the view via a precise map scale might not be possible. I think this is due to the fact that you don't have precise control over the zoom level. For example, in the javascript ajax version, you can only specify zoom levels in integer values, so the ground resolution part of the above equation will jump in discreet steps. At the equator, using a zoom level of 21 will give you a scale of 1: 282, and a zoom level of 22 will give you 1:141. Since you can't specify a decimal value for zoom level, it is not possible to get an exact 1:200 scale using the ajax control. I don't have extensive experience with the .net Bing Maps control, so you might want to investigate that API to see if you can specify an arbitrary zoom level.
If you can precisely control the zoom level and know the dpi value, then the 1:200 scale is achievable using the equation described in the above linked article.

Getting the global coordinate of a Node in JavaFX

How can I get the actual position of a node in the scene. The absolute position, regardless of any containers/transforms.
For example, I want to translate a certain node a so that it would temporarily overlap another node b. So I wish to set his translateX property to b.globalX-a.globalX.
The documentation says:
Defines the X coordinate of the
translation that is added to the
transformed coordinates of this Node
for the purpose of layout. Containers
or Groups performing layout will set
this variable relative to
layoutBounds.minX in order to position
the node at the desired layout
location.
For example, if child should have a
final location of finalX:
child.layoutX = finalX - child.layoutBounds.minX;
That is, the final coordinates of any node should be
finalX = node.layoutX + node.layoutBounds.minX
However running the following code:
var rect;
Stage {
title: "Application title"
width: 250
height:250
scene: Scene {
content: [
Stack{content:[rect = Rectangle { width:10 height:10}] layoutX:10}
]
}
}
println("finalX = {rect.layoutX+rect.layoutBounds.minX}");
gives me finalX = 0.0 instead of finalX = 10.0 as the docs seemingly state.
Is there a clear method to get the absolutely final positioning coordinates in JavaFX?
For bounds:
bounds = rect.localToScene(rect.getBoundsInLocal());
Work for JavaFx 1 and 2.
The only solution I found so far is
rect.localToScene(rect.layoutBounds.minX, rect.layoutBounds.minY) // a Point2D{x:Float y:Float} object
Which doesn't seem to me as the "best" way to do that (note that this function is not bound). Still it works for JavaFX 1.2.
Since JavaFX 8, there are additional methods converting local coordinates to screen coordinates. Their names start with "localToScreen"
You can check following link
http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html#localToScreen-double-double-

Resources