BIMsurfer-before2019 icon indicating copy to clipboard operation
BIMsurfer-before2019 copied to clipboard

How to access object coordinates

Open walterogrady opened this issue 9 years ago • 9 comments

Does BIMsurfer translate the object's relative coordinates stored in BIMserver into global coordinates in order to display them? If that is the case where in the BIMsurfer or BIMviews code would be a good place to access these coordinates? Or is there a better way to get the global coordinates from BIMserver?

For example, I would like to create an option to display the global coordinates of an object when it is selected in BIMviews/BIMsurfer and it seems BIMsurfer has calculated these coordinates.

Note: My understanding is that BIMViews uses BIMsurfer for the 3D view. Is that correct?

walterogrady avatar Nov 22 '16 17:11 walterogrady

Yes BIMvie.ws uses BIMsurfer (V1).

Just hacked together a way to get both the non-transformed object-center as the transformed object-center (see below). A note, the object-center is defined to be the center of the axis-aligned bounding box of the object.

	this.nodeSelected = function(groupId, node){
		o.selected = node.data.object;
		var object = node.data.object;
		object.getGeometry(function(geometryInfo){
			geometryInfo.getTransformation(function(transformation){
				var rawLength = 16 * 8;
				var binary_string =  atob(transformation);
				var array = new Uint8Array(new ArrayBuffer(rawLength));
				for(i = 0; i < rawLength; i++) {
					array[i] = binary_string.charCodeAt(i);
			  	}
				var inputStream = new BIMSURFER.DataInputStreamReader(null, array.buffer);
				var matrix = inputStream.readDoubleArray(16);
				var min = geometryInfo.getMinBounds(function(min){
					var max = geometryInfo.getMaxBounds(function(max){
						var center = {
							x: (max.x - min.x) / 2,
							y: (max.y - min.y) / 2,
							z: (max.z - min.z) / 2
						}
//						console.log("center", center);
						var centerTransformed = SceneJS_math_transformVector4(matrix, [center.x, center.y, center.z, 1]);
						centerTransformed = {
							x: centerTransformed[0],
							y: centerTransformed[1],
							z: centerTransformed[2]
						}
						console.log("center transformed", centerTransformed);
					});
				});
			});
		})
		parent.selected(o, groupId, node.data.object);
	};

You need to replace the nodeSelected method in 3dview.html with this. I'll try and find a more permanent location for this code in the future.

rubendel avatar Nov 23 '16 07:11 rubendel

Thank you Ruben. That's great.

walterogrady avatar Nov 24 '16 18:11 walterogrady

I also require to have access to the selected objects' coordinates in V2.

That would require to change the data returned by xeoViewer's selection-changed event to something like that:

{
    ids: selectedObjectList,
    boundingBox: ...,
    centerCoordinates: ...
}

@rubendel @aothms If you agree with this I am happy to submit a PR implementing this change.

bastienmenis avatar Dec 09 '16 11:12 bastienmenis

@bastienmenis would be a nice addition, but maybe separate it from the selection event and have a e.g. getObjectCoordinates(). That way users can decide themselves how to handle things in case of a multi selection, i.e. get separate coords for selected elements individually or aggregate into single boundary. Perhaps return something like a http://xeogl.org/docs/classes/Boundary3D.html ?

aothms avatar Dec 09 '16 11:12 aothms

@aothms @bastienmenis sounds like a flexible solution - means exposing xeogl bits through the BIMSurfer API though, which are so far encapsulated - if that's OK with everyone, that would be a good solution IMO.

xeolabs avatar Dec 09 '16 12:12 xeolabs

@xeolabs that's true, but seems to me that encapsulation for this particular case is too much effort

aothms avatar Dec 09 '16 12:12 aothms

@aothms - (just a general thought on extensibility in future) we could think of the viewer as being a container of xeogl components, that internally creates and manages their lifecycles, and allows you to get references to some of them. The contract being that app code is not allowed to destroy or modify those components. And when apps want to add new components, for whatever reason in future, like installing new camera controls or whatever, they would pass into the viewer the JSON configurations for those components, for the viewer to instantiate, eg, a hypothetical case:

var control = viewer.createCameraControl({
    type: "xeogl.MyNewCameraControl",
    //...
});

and

var boundary = viewer.getBoundary3D("myObject");
boundary.on("updated", function() {
    //...
}));

So the viewer is the "factory".

xeolabs avatar Dec 09 '16 12:12 xeolabs

@xeolabs while I like the idea, I think installing components is a bit ahead of what I think our end users will need to accomplish. Also I am not too worried, if users want to blow their foot off, there are plenty of ways in javascript. As long as the basic api is feature complete, stable and predictable I am very happy. For BimSurfer the api does need to be as general as e.g. xeogl. My guess is that connecting some events to integrate the viewer in end user platforms should be sufficient as long as the viewer provides reasonable and configurable defaults.

Ideally the API would be general enough to control other visualisation platforms as well. In that sense we are mostly thinking about a thin wrapper around an SVG dom for example for 2d views. Not that everything needs to be completely encapsulated, as you also don't want to artificially remove functionality for advanced users to directly manipulate xeogl/svg elements.

aothms avatar Dec 12 '16 09:12 aothms

Hi,everyone Could you look at this? https://github.com/opensourceBIM/bimvie.ws/issues/75

I call nodeSelected function like o.nodeSelected(groupId, node) in 3dview.html,but it doesn`t work. And the console does not have error messages.

RicoLiu avatar Feb 08 '17 01:02 RicoLiu