Is It possible to move the avatar programmatically or specify position in Autodesk.AEC.Minimap3DExtension - autodesk-forge

Autodesk.AEC.Minimap3DExtension provides a 3d and 2d sync forge viewer where a user can use 2d viewer and move the avatar to navigate. In order to navigate user has to move the avatar or a dot icon in 2d viewer to navigate in 3d model.
My question is where is there any possibility where I can send the set of coordinates which are with me and can I move the avatar programmatically so that user don't have to do so.
here is any example why I am asking so,
I have a geometry on my forge viewer which is on 2D and I am looking to make a first person view over that geometry.
So If I have all the points of geometry I want to make it use with Autodesk.AEC.Minimap3DExtension so that I can move first person to different views
here is the sample I am rereferring to link
I had been following this wonderful blog link
with the help of this I am aware little bit aware how to work with 2dto3d
here in above link
const worldPos = sheetToWorld(intersection.intersectPoint, viewer2D.model,
viewer3D.model);
the above line of code gives me worldPos with which a geometric point is
created in the 3d viewer in spite of creating a geometry how can I use to
show view of that particular place
basically in this below line of code which transits camera from one position to another
viewer.navigation.setRequestTransition(true, newPos, newTarget,
viewer.navigation.getHorizontalFov());

I'm glad you like the blog post :)
After reading the question I have the impression that you have already answered it yourself. If you have some kind of a geometry, let's say a polyline, overlaid on top of the 2D drawing, you can use the same logic explained in the blog post, but when calling viewer.hitTest, instead of passing in some mouse coordinates, you would just supply one of the points of your polyline.
Instead of:
viewer2D.container.addEventListener('click', function (ev) {
const intersection = viewer2D.hitTest(ev.clientX, ev.clientY);
viewer3D.isolate([]);
if (intersection) {
viewer3D.isolate(intersection.dbId);
const worldPos = sheetToWorld(intersection.intersectPoint, viewer2D.model, viewer3D.model);
if (worldPos) {
let mesh = new THREE.Mesh(geometry, material);
mesh.position.set(worldPos.x, worldPos.y, worldPos.z);
viewer3D.overlays.addMesh(mesh, 'indicator-scene');
}
}
});
It could look something like this:
function moveCameraToPointOnSheet(x, y) {
const intersection = viewer2D.hitTest(x, y);
if (intersection) {
const worldPos = sheetToWorld(intersection.intersectPoint, viewer2D.model, viewer3D.model);
if (worldPos) {
const eyeVec = viewer3D.navigation.getEyeVector();
const newPos = worldPos;
const newTarget = newPos.clone().add(eyeVec);
const fov = viewer3D.navigation.getHorizontalFov();
viewer3D.navigation.setRequestTransition(true, newPos, newTarget, fov);
}
}
});

Related

Adding scene lights to Forge Viewer

I would like to add several extra lights to my Forge Viewer scene but I cannot find any sample on how to achieve this, my attempts have been unsuccessful so far.
I am aware of this article: Add Custom Light for the View and Data API Viewer. This is not what I'm looking for, I do not want to create a new light preset, I want to keep the selected light preset and add extra lights around my model to make it more illuminated.
Digging the viewer3D.js code I found the following function:
this.initLights = function ()
{
this.dir_light1 = new three__WEBPACK_IMPORTED_MODULE_30__["DirectionalLight"](_defaultDirLightColor, _defaultLightIntensity);
this.dir_light1.position.copy(_lightDirDefault);
this.highlight_dir_light1 = new three__WEBPACK_IMPORTED_MODULE_30__["DirectionalLight"](_defaultDirLightColor, _defaultLightIntensity);
this.highlight_dir_light1.intensity = 1;
this.highlight_dir_light1.position.copy(_lightDirDefault);
//Note this color will be overridden by various light presets
this.amb_light = new three__WEBPACK_IMPORTED_MODULE_30__["AmbientLight"](_defaultAmbientColor);
this.highlight_amb_light = new three__WEBPACK_IMPORTED_MODULE_30__["AmbientLight"](_defaultAmbientColor);
// Set this list only once, so that we're not constantly creating and deleting arrays each frame.
// See https://www.scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript for why.
// use this.no_lights empty array if no lights are needed.
this.lights = [this.dir_light1, this.amb_light];
this.highlight_lights = [this.highlight_dir_light1, this.highlight_amb_light];
//We do not add the lights to any scene, because we need to use them
//in multiple scenes during progressive render.
//this.scene.add(this.amb_light);
// Attach the light to the camera, so that the light direction is applied in view-space.
// Note:
//
// 1. For directional lights, the direction where the light comes from is determined by
// lightPosition - targetPosition, both in in world-space.
// 2. The default target of dir lights is the world origin.
// 3. Transforming the light object only affects the light position, but has no effect on the target.
//
// The goal is to rotate the lightDir with the camera, but keep it independent
// of the camera position. Due to 3. above, we must also attach the light's target object to the camera.
// Otherwise, the camera position would incorrectly be added to the light direction.
this.camera.add(this.dir_light1);
this.camera.add(this.dir_light1.target);
this.camera.add(this.highlight_dir_light1);
this.camera.add(this.highlight_dir_light1.target);
_lightsInitialized = true;
};
So I attempted to create my lights as follow to no success :(
const camera = this.viewer.navigation.getCamera()
positions.forEach(pos => {
const light = new THREE.DirectionalLight(0xFF0000, 1.0)
light.target.position.copy(target)
light.position.copy(pos)
camera.add(light)
camera.add(light.target)
})
// no effect ...
LMV uses custom lights so any extra light sources would need to be added to viewer.impl.lights to take effect:
const myExtraLight = new THREE.DirectionalLight(0xFF0000, 1.0);
viewer.impl.lights.push(myExtraLight)
Note in the Viewer’s source code you posted the light sources are also added to the the render’s light array:
this.lights = [this.dir_light1, this.amb_light];

Transform point from DWG model coordinates to autodesk forge viewer coordinates

I am trying to display a point on model displayed in the Autodesk forge viewer. However I am unable to figure out how to transform the point.
The answer Aligning Coordinate Systems in Autodesk Forge Viewer doesn't work for me because viewer.model.getData() doesn't have a globalOffset property.
I have uploaded some example code along with the original dwg file here https://github.com/umarmohammed/forgeviewerdemo
Sorry, I haven't received any responses from our engineering team. There seems not to have another way to obtain viewportId of current 2d view, and might have floating precision issue here, this is the issue I mentioned above. I will keep asking for them. So, here is the way I found to do point transformation from DWG coordinate system to the Viewers'.
Obtain current viewport id via VertexBufferReader, but you have to specify a 2d item(dbId) in the loaded view to read viewportId from it.
var viewportId = null;
function GeometryCallback(viewer) {
this.viewer = viewer;
}
GeometryCallback.prototype.onLineSegment = function(x1, y1, x2, y2, vpId) {
viewportId = vpId;
}
var fragId = 0;
var m = viewer.impl.getRenderProxy(viewer.model, fragId);
var vbr = new Autodesk.Viewing.Private.VertexBufferReader(m.geometry, viewer.impl.use2dInstancing);
vbr.enumGeomsForObject(dbId, new GeometryCallback());
Project DWG point back to Viewer coordinate system.
var vpXform = viewer.model.getPageToModelTransform(viewportId).clone();
var invVpXform = new WGS.LmvMatrix4(true);
invVpXform.getInverse(vpXform, true);
var ptInCadX = ...;
var ptInCadY = ...;
var verticesInViewer = new THREE.Vector3().set(ptInCadX, ptInCadY, 0).applyMatrix4(invVpXform);
Hope it helps.

Select multiple entities in a datasource with Cesium

I am trying to write a function where I can select multiple buildings of GeoJSON and/or CZML in Cesium
for example with the ctrl button held down, I will be able to create a list to select several buildings, and also change the color of the selected building as well.
I can change the color of one selected building now, and was told I should use the (entity.push) to add to the a list. but I'm still stuck!
Here is my initial code
*var scene = viewer.scene;
var handler = viewer.screenSpaceEventHandler;
handler.setInputAction(function(click) {
var pickedObject = scene.pick(click.position);
if (Cesium.defined(pickedObject) ) {
highlightedEntity= pickedObject.id;
// console.log (pickedObject.id);
} else{
highlightedEntity = undefined;
}
},Cesium.ScreenSpaceEventType.LEFT_CLICK);*
can someone help me out in completing it?
Here you can find a sample of the geojson

Get features present in map viewport from geoJSON

I need to add markers on the map for the data that I have.
Out of the thought process, I went through map.data.loadGeoJson('google.json'); with which I will be able to have custom data attached to the map. Now, there is a requirement that I need to show properties of the features present in the map viewport. I cannot loop through all the items and check for .contains(), I have a huge data. Is there default google way to get the properties of the features present in the map viewport?
I like using TurfJS for tasks like these. I've tested it w/ 1M points and it works more quickly than one'd expect.
Pseudocode
load your GeoJSON once and initialize it as a turf feature collection
transform your map viewport's bounds into a GeoJSON polygon
run the pointsWithinPolygon function
pass the resulting feature collection onto the map data layer using addGeoJson
rinse & repeat within a throttled bounds_changed event
Actual Code
/*
You'd load your own geojson like so:
const points = turf.featureCollection(geojsonObject.features)
*/
// random 1M points as a demo
const points = turf.randomPoint(1e6, {
bbox: [-180, -90, 180, 90]
});
const {
west,
south,
east,
north
} = map.getBounds().toJSON();
// extent in minX, minY, maxX, maxY order
const viewport_as_polygon = turf.bboxPolygon([west, south, east, north])
const points_within = turf.pointsWithinPolygon(points, viewport_as_polygon)
Note: Since none of this interacts with the DOM until you call addGeoJSON, it's gonna be faster than for instance generating markers for each feature and then hiding/modifying the transparency of those that are outside of the viewport.

How do I change the color of a GMarker in Google Maps?

Pretty simple request, but there doesn't seem to be a way to do it. I just want my GMarkers to be green instead of red.
Do I really have to make my own icons?
This is the simplest method:
var greenIcon = new GIcon(G_DEFAULT_ICON);
greenIcon.image = "http://www.google.com/intl/en_us/mapfiles/ms/micons/green-dot.png";
var markerOptions = { icon:greenIcon };
var marker = new GMarker(point, markerOptions);
That marker image is Google's, but you could also use your own.
MapIconMaker is great if you need to generate unique markers on the fly.
The best way I have found is with the following scripts...
labeledmarker.js
mapiconmaker.js
you then need the following code snippet:
var iconOptions = {};
iconOptions.width = 32;
iconOptions.height = 32;
iconOptions.primaryColor = "#66CC6600";
iconOptions.cornerColor = "#66CC6600";
iconOptions.strokeColor = "#000000FF";
var iconSeller = MapIconMaker.createMarkerIcon(iconOptions);
function createMarker(icon, point,html,label)
{
opts =
{
"icon": icon,
"labelText": label,
"labelClass": "markerLabel",
"labelOffset": new GSize(-4, -31)
};
var marker = new LabeledMarker(point, opts);
GEvent.addListener(marker, "click",
function()
{
marker.openInfoWindowHtml(html);
});
return marker;
}
Make sure you have a class in your stylesheet called markerLabel so you can style the div which contains the label. I pinched most of this code from the excellent econym tutorial site where there are many clear examples and code samples.
See this: Map Overlays > Markers > Icons
Icons
Markers may define an icon to show in
place of the default icon. Defining an
icon is complex because of the number
of different images that make up a
single icon in the Maps API. At a
minimum, an icon must define the
foreground image, the size of type
GSize, and an icon offset to
position the icon.
The simplest icons are based on the
G_DEFAULT_ICON type. Creating an
icon based on this type allows you to
quickly change the default icon by
modifying only a few properties.
It looks like this is the simplest case. You use G_DEFAULT_ICON as the base GIcon, then extend it by altering the .image property of that new object. The simple example is pretty simple.
I need project for add gmarker in map and getting data from web services