I'm using
lineLayer.events.on({
"vertexmodified": update
});
to get the line info once it's been modified. If a new point is added in between 2 existing points, is there a way to figure out the position of the new point in relation to everything else?
I'm updating a table based on the values of the line and need to know where to insert the new row.
You can figure out the position of the vertex by looking at its parent collection:
var vertex = event.vertex;
var idx = vertex.parent.components.indexOf(vertex);
You can’t (with actual OpenLayers code). I’d suggest you to get the whole geometry (you can access event.feature.geometry from your listener argument), and update the whole geometry at once rather than updating just a point.
Related
I have bulk of nodes around 500 and I want to place nodes together. To achieve this I need to set the X-axis and Y-axis positions to these nodes dynamically. How do I do that in vis.js?
You can set nodes' coordinates using VisData and update if you set them like this:
// data is your data in form of { nodes:nodes, edges:edges }
window.testNodes = new vis.DataSet(data.nodes); // make it globally available for this demo
window.testEdges = new vis.DataSet(data.edges); // if you need to change something about edges too
data = { nodes: window.testNodes, edges: window.testEdges };
network = new vis.Network(container, data, options);
and then use
window.testNodes.update({id:5,label:'wow',x:100,y:-200})
to update the node with id == 5. The x:100,y:-200 updates coordinates, of'course.
As for putting nodes together, you should clarify what does "together" mean. For instance, you can create a simple grid and put nodes into it (by setting their coordinates like shown above). What distances do you expect from "together"? What else do you need? I'd say this deserves a separate question if you have problems not only with applying coordinates dynamically.
I'm trying to clone and then scale a mesh, but scaling does not seem to be working immediately on the cloned object, for programming purposes using CSG ThreeBSP. I think I should call a function after the scaling to force the matrix or other internal variables to recalculate immediately and not to wait for the full update loop on render side.
My code looks something like this:
var someMesh2 = someMesh1.clone();
someMesh2.scale.set(2,2,2);
someProgrammingOperation(someMesh2);
//It turns out that internally, someMesh2 still has the same properties (matrix?) as someMesh1 :(
What am I missing? Suggestions are also welcomed :)
object.matrix is updated for you by the renderer whenever you call renderer.render().
If you need to update the object matrix manually, call
object.updateMatrix();
and it will update the matrix from the current values of object.position, object.quaternion, and object.scale.
(Note that object.rotation and object.quaternion remain synchronized. When you update one, the other updates automatically.)
three.js r.84
In the end, my problem was that the CSG ThreeBSP object needed to work based on the Geometry of the object, not in the Mesh itself. I applied the scaling on the Geometry and it worked as expected.
There is a caveat though, that one should be careful as with the meshes and geometries instances, therefore is needed to do some cloning in order to keep the original objects as they were, as in the following example:
var clonedMesh = original.mesh.clone()
var clonedGeometry = clonedMesh.geometry.clone()
clonedMesh.geometry = clonedGeometry
clonedMesh.geometry.scale(2,2,2)
var someBsp = new ThreeBSP( clonedMesh )
var newMesh = someBspBsp.toMesh()
someScene.add newMesh
I am testing Cesiumjs to see if it can reflect a near-real-time expreience - for example: position of airplanes.
For that, I need to draw billboards and make them move - which I know is possible with cesium, just not sure how.
The code looks like this:
var billboards = scene.primitives.add(new Cesium.BillboardCollection());
var billboard = {
image : '/path/to/logo.png',
position : Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883)
};
billboards.add(billboard);
My question is how do I change the position of the billboard. I couldn't find ant documentation that would explain.
I thought doing:
billboard.position = ... //new position
but how will cesium know that I've changed the position attribute unless it somehow turns that reference into a observable object.
So how do I update the location?
Thanks.
Cesium does indeed listen for changes to billboard.position
(source code here), so it is correct behavior for apps to simply write a new position.
Note that you must write the whole position at once, meaning you may not write to billboard.position.x. Instead, keep a "scratch" Cartesian3 around (don't create a new one every animation frame at 60fps), write to the x,y,z properties of your scratch variable, and then assign your scratch variable to billboard.position. You can see in the source that the assigned value will be cloned into another pre-existing Cartesian3, so you may immediately reuse the scratch variable.
Here's an example:
// Just once at app startup. Don't call "new" at 60fps.
var scratchCartesian3 = new Cesium.Cartesian3();
var ellipsoid = viewer.scene.mapProjection.ellipsoid;
function onTick() {
// This is safe to call at 60fps.
billboard.position = Cesium.Cartesian3.fromDegrees(
lon, lat, alt, ellipsoid, scratchCartesian3);
}
Also note that your question and the above answer are focused on the "Graphics Primitive" layer of the Cesium API. Cesium has one higher layer, called the "Entity" API, that you can use if you want Cesium to handle the concept of user-selectable objects with pop-up descriptions etc. Here's a Sandcastle demo showing how to add a billboard as a property of an entity, instead of as a primitive. This allows you to add other properties to the same entity, for example a name, description, label, 3D model, etc, and have them all be controlled from the same position property, and have Cesium take care of popup descriptions. The position property is more complex for entities than for primitives, for example it can be constant or sampled. This allows entities to change position over time when the timeline is shown.
This question is related with one I asked before here. I'm currently using KineticJS 4.0.5 and I'm using multiple layers to display some shapes with different properties. Since I need to change the layers contents frequently I'm using removeChildren to remove a layer content, but it seems that removeChildren also removes the events associated to childrens. I would like to remove the layer childrens without removing their events because I may have to add them to the layer again.
I tried to set the layer.childrens attribute equal to an empty Array instead of using the removeChildren function. At first it seemed to work but on some cases, some weird things happen :/ Some shapes disappear and the only way to get them back is by setting their Z index. I think the main problem with this approach is related with some properties that must be reseted when contents are removed from the layer, but I don't know which are they.
I also tried to set the events again on each shape before drawing them but it doesn't work... They remain static on the screen... I event tried to use the setDraggable(true) on all shapes before drawing them but no luck... Do I need to create the objects again and apply the events to them again each time I want to redraw a layer with shapes I used before? Or would it be a good approach to store layers for each screen on my application? (I can have a lot of different screens, which would result in a lot of layers and only one would be displayed at a time...)
If you know a solution for this problem please tell me. I really need to solve this problem because it is very important for my project to be able to draw and redraw :/
Thank you!
Sounds to me that what you need is a way to visually remove objects from layers, but not actually delete them. Instead of using remove, try creating a new layer specifically for storage, where your main group within that layer is hidden. You'll want this group, and its layer, to be globals for easy access. Then, when you need to remove an object from view, use moveTo to move it into storage, and moveTo again to restore it to view.
var gObj = {storage : '', storageGroup : ''};
gObj.storage = new Kinetic.Layer();
gObj.storageGroup = new Kinetic.Group({name:'storage', x:0, y:0});
gObj.storage.add(gObj.storageGroup);
// assumes stage is already built
stage.add(gObj.storage);
gObj.storageGroup.hide();
function wareHouse(obj, group, store) {
// obj is an object to store when store === true, otherwise it's a name or id when retreiving, group is the group where object either is or needs to be, store is a boolean value
if (store) {
obj.moveTo(gObj.storageGroup);
} else {
// change the dot to pound ('.' = '#') if using id's
var box = gObj.storageGroup.get('.' + obj)[0];
box.moveTo(group);
}
var parent = group.getLayer();
parent.draw();
}
So basically I have a child object3D of a group Object3D, while the child object's [x,y,z] coordinates are shown relative to the object space of the parent object, I want to change the location of the child object within the 3D space. So first I get the child object's position relative to the world space.
var wrld_pos = childobject.matrixWorld.multiplyVector3(new THREE.Vector3);
This returns a three element vector of the child's position within the world space. Now I wish to set the position my self. So I create a three element vector.
var new_pos = THREE.Vector3();
new_pos.x = 1;
new_pos.y = 2;
new_pos.z = 3;
childobject.matrixWorld.setPosition(new_pos);
Provided the function definition for setPosition, it essentially it sets the last three elements of the object's world matrix to the values of the vector passed as an argument, thus changing the location of the object in world space. And to make sure that the matrix updates after these changes, I call the following functions.
childobject.matrixWorldNeedsUpdate = true;
childobject.updateMatrixWorld();
Now upon inspecting the new world matrix of the object I noticed that the setPosition function did nothing, nothing at all.
Why? If real code examples are needed, I will provide them. But the above should represent the application domain and syntax I used very accurately.
EDIT: Answer updated.
You want to change the world position of a child object.
Assuming the scene has no transform applied, one way to do what you want is to use the following pattern:
scene.attach( child ); // detach from parent and add to scene
child.position.set( x, y, z );
parent.attach( child ); // reattach to original parent
The Object3D.attach( child ) method adds the child object, while maintaining the child's world transform.
three.js r.132
This answer might help with the case. Remove child from parent, change normal position, then attach again.
If use attach for setting position in animation loop for moving objects you can get objects shaking.
For me best solution is:
let newPosition = new THREE.Vector3(1,2,3);
let parentPosition = new THREE.Vector3();
childobject.parent.getWorldPosition(parentPosition);
childobject.position.set(
newPosition.x-parentPosition.x,
newPosition.y-parentPosition.y,
newPosition.z-parentPosition.z
);
If you need position and rotation attach is the only way.