three.js - cannot read property "y" of undefined - three.js

thank you for your help, dumb newbie question…
Working with a proven example - after dragging a cube - getting this error when trying to log the position.y value of an item in an array.
At line 88:
console.log("position.y = " + this.objects.position.y);
I’ve tried many variants on this of course - thank you in advance
EDIT (working link):
https://codepen.io/ken-thomas/pen/rQayYg

this.objects is an array of 200 or so meshes.
You need to pick which one you actually want to log the position of.
e.g:
this.objects[0].position.y
However, the dragend function gives you event data, one of the keys being the mesh you moved (event.object). So your code should look like this:
dragControls.addEventListener('dragend', (event) => {
console.log('position.y = ', event.object.position.y);
});
Working codepen - https://codepen.io/danlong/pen/EOaRBw

Related

Plottable.js entityNearest not giving me the nearest entity

Im implementing the code below in a React, Typescript project.
When hovering over my graph I don't get the nearest entity its roughly 5 years off, on my x-axis(time).
I've tried switching out entityNearest for entityNearestXThenY but it yielded similar results.
Below is my pointer interaction function:
new Plottable.Interactions.Pointer()
.attachTo(Chart)
.onPointerMove(function(p) {
var entity = hiddenGraph.entityNearest(p);
var date = parseTime(entity.datum.x);
var value = currencySymbolNoPrecision(entity.datum.y);
var displayValue = (value + " • " + date);
guideline.value(entity.datum.x);
xAxis.annotatedTicks([entity.datum.x]);
title.text(displayValue).yAlignment();
})
.onPointerExit(function() {
guideline.pixelPosition(-10);
xAxis.annotatedTicks([]);
});
Pointer tracking is also very jumpy. My dataset is the gold price per month since 1950. I've checked the dataset to ensure that there are no problems there.
In the image below my mouse is hovering roughly where the red circle is.
Please let me know if I can provide any further information.
I eventually reached a solution by directly editing the coordinates of the mouse after it had bean calculated:
.onPointerMove(p){
p={x: p.x-(compensationValue), y:p.y}
...
...
...
}
While I understand this is by far not the best solution to the problem I had, it has managed to resolve the problem and seemingly with no adverse effects on different screen sizes or when nesting components.

Getting global normal from hitTest.face.normal

I am doing a hitTest to create a section plane on a face normal. To get the global normal I have to do some reworking of the hitTest.face.normal. It seems to almost work, but my result seems to be slightly off from the actual normal, so I am thinking I am doing something wrong:
const normalMatrix = new THREE.Matrix3().getNormalMatrix( this.hitTest.object.matrixWorld );
const normal = this.hitTest.face.normal.clone().applyMatrix3( normalMatrix )
this.SectionExtension.tool.setSectionPlane(normal, this.hitTest.point)
As seen on the picture, my ending cut plane is slightly off the actual plane
Can anyone see what might be off in that way of getting the plane, or do anyone have a better way of finding the global normal?
Thank you in advance!
Could you share more details on what the face normal should be? Here is the code snippet how the viewer's context menu Section Plane creates the section plane based on the face hit point. It might help.
const selected = viewer.getSelection();
const intersection = viewer.impl.hitTest(status.canvasX, status.canvasY, false, selected);
// Ensure that the selected object is the on that recieved the context click.
if (intersection && intersection.face && selected.indexOf(intersection.dbId) !== -1) {
sectionExtension.tool.setSectionPlane(section, intersection.face.normal, intersection.point);
}
If anyone should be interested, then i found a solution to my problem
For some reason, when running
const currentFragId = this.hitTest.fragId;
const renderProxy = this.viewer.impl.getRenderProxy(this.viewer.model,currentFragId);
Before using the normal helped me to get the correct normal. I do not use the 'renderProxy' for anything - but i assume that it helps the viewer in some way. Anyway - this works for me!

Manipulate gltf model children

I'VE loaded a GLTF file with 2 mesh object in it (cube1, cube2) and rendered it, looks OK.
The problem is this :
I'm trying to manipulate the opacity / scale of those objects separately.
Tried to address them with:
Var cube1 = gltf.Scene.GetObjectByName('Cube1');
But when I try to define cube1.opacity, I get an "undefined" error.
Any help is appreciated!
Thanks
Well... even tho' the question is simple, the answer not so much.
First you are using a loader, usually this implies that your cube model will be a bit more complicated. You will go something like this:
3D Object > Children > Mesh [x] > material > Opacity
I have a live example here:
https://boxelizer.com/renderer.php?mid=7740369e824e4eadbd83e6f01fa96caa
In which you can go into the console and change that property like this:
model.children[1].material.transparent = true;
model.children[1].material.opacity = .5;
model.children[1].material.needsUpdate = true;
Your model may be a bit different but I hope this example helps you figure out yours.

Manually selecting a feature in a map generated by d3.js (for the purposes of zooming in this case)

I'd like to implement a map that zooms in on an area similar to Mike's click-zoom-example http://bl.ocks.org/mbostock/2206590
In fact I have this working fine already. My problem is that I can't rely on the click event to implement the zoom — the zoom will be triggered by another event (a link). So when I get to this part of Mike's code:
function clicked(d) {
var x, y, k;
if (d && centered !== d) {
var centroid = path.centroid(d);
...
I'm a bit of a loss as I don't have 'd'. So, I'm assuming that I can instead, manually pass 'd' to my click function when I call it. But how do I actually select the feature (which is what 'd' represents) I want from the map?
To be a bit more concrete, I have a map of the world. The paths within the SVG group contain class information (e.g. the one for France looks like):
<path class="subunit FXX FRA" id="FXX" data-subunit="FXX" data-countryName="France" data-countryCode="FRA" d="M153.88838704622088,519........"></path>
How would I pass the 'France object' to the clicked(d) function? Or is there another approach altogether that I should be trying.
Any tips or help greatly appreciated.
You can use D3's select for this purpose:
d3.select(".FRA").each(function(d) {
// same code as inside clicked
});
Get the data associated with the France object:
d3.select('.FXX.FRA').datum()
And pass it to clicked:
clicked(d3.select('.FXX.FRA').datum())

changing d3.JSON in Hierarchical Bars to JSON.parse

I'm using http://bl.ocks.org/mbostock/1283663
and I'm trying to change the following code
d3.json("readme.json", function(root) {
hierarchy.nodes(root);
x.domain([0, root.value]).nice();
down(root, 0);
});
to a JSON.parse (some data). I don't have a problem pulling the JSON data but I am totally confused about what is being setup in the rest of the d3.json process with the hierarchy.node(root), x.domain and down(root)
You're probably going to have to read a little more documentation before having a working understanding of what's going in this function. This is a tricky example to start with; I'm just going to walk you through what my process of trying to understand would look like. Going line by line:
d3.json("readme.json", function(root) {
This loads the referenced json file and calls function with it. 'root' starts out equal to the json file.
hierarchy.nodes(root);
Looking through the code, we find where hierarchy is declared:
var hierarchy = d3.layout.partition()
.value(function(d) { return d.size; });
So hierarchy is some kind of layout and hierarchy.nodes will add some useful attributes to root that will make it easier to graph.
x.domain([0, root.value]).nice();
searching for "x" in the example we find x = d3.scale.linear().range([0, w]). Tt appears that x is a linear scale. Basically, the x function will transform values in the domain - [0, root.value] to the range [0, w]. w is the width of the svg. root.value is a little trickier. The node page says
value - the node value, as returned by the value accessor
But what is the value accessor? The initial declaration of indicates it has something todo with root's 'size' attribute, but what? At this point, the documentation starts to get pretty confusing so you might want to pop open the debugger and see exactly what the value attribute of root and root's children looks like.
down(root, 0);
The down function is unique to the example and well commented. Try reading through it while referencing the documentation and see if you can figure it out.

Resources