Retrieve coordinates from snapped points in Forge viewer - autodesk-forge

I want to snapp points in the model and retrieve their coordinates. I found the below code in Forge blog
this.points = [];
const result = this.snapper.getSnapResult();
const { SnapType } = Autodesk.Viewing.MeasureCommon;
switch (result.geomType) {
case SnapType.SNAP_VERTEX:
case SnapType.SNAP_MIDPOINT:
case SnapType.SNAP_INTERSECTION:
this.points.push(result.getGeometry());
Now Im able to get the coordinates of vertex and midpoints, but I want to actully get the coordinates of any snapped point of a Brep-line for instance. How is this possible ?

You're probably referring to this blog post, right? The SnapType enumeration used in the blog lists all the types of snapping types the tool can detect. Other types you would probably have to detect yourself, for example, by shooting a ray to the scene based on the camera position and mouse cursor position, and finding whatever object of interest are nearby.

Related

How do I convert between 2D paper space coordinates world 3D coordinates for AEC models in a forge viewer?

I'm following a blog post by Petr Broz with my published views from a Revit project in BIM 360, but I was wondering how I would convert between 2D coordinates and 3D world coordinates if my published 2D view is actually just a stand-alone floor plan view without being placed on any sheet.
I was trying to get the viewport but I realized the published view doesn't have any viewport in the model. So I cannot actually use those functions in the extension for viewports. Any advise would be greatly appreciated.
Unfortunately, it doesn't support floor plan view without placing the sheet, since there is some required information missing at this moment. We are still discussing this with our engineering team.
The current working path is creating a Revit Sheet view and placing the floor plan inside, see https://www.youtube.com/watch?v=smMap86YZUY
My mistake was manually trying to convert x,y,z coordinates by dividing them with the viewport scale, thus they couldn't align with 3D world coordinates.
By providing the correct model unitscale, I could get the transform with get3DTo2DMatrix().
viewport = viewportExt.getViewports(viewer.model)[0];
viewportXform viewport.get3DTo2DMatrix(viewer.model.getUnitScale());
// From foot to millimeters
x = x* 0.00328084;
y = y* 0.00328084;
z = z* 0.00328084;
var worldPt = new THREE.Vector3(x,y,z);
worldPt.applyMatrix4(viewportXform);

Drawing svg shapes on top of autodesk viewer, viewer's center coordinate moves when new versions of the same drawing are uploaded

We have a web application where we let the users draw SVG shapes on top of the Autodesk Viewer. We can translate the on-screen coordinates to the drawing using the worldToClient and the clientToWorld functions and it works beautifully, the shapes scale and move around with the drawing.
We also let the users update update the drawing by uploading new versions of it, and this has turned into a problem where the center coordinate (0,0) will change when the drawing has changed. That means that the SVG shapes will have the wrong positions when used with the new version of the drawing. It seems to me like somewhere in the translation the original positions of the .dwg files are ignored and a new center coordinate is computed from the content.
Our current workaround is for the users to draw a square frame around the drawings that they wish to use in this way. If all changes happen within that square the center will not move with new versions.
Does anyone have any thoughts, ideas, or experiences on how to solve this without the users needing to edit the drawings?
When using viewer.clientToWorld and viewer.worldToClient with 2D drawings, the "world" typically means page dimensions. In your case, the two DXF files you provided had the same page dimensions, and the content in each DXF file was scaled to fit the entire page. That's why the "world" coordinates between the two DXF files didn't match.
Luckily, when converting DXF files, the Forge Model Derivative service also exports the "source to logical" transformation which I believe defines the conversion from the original coordinates to the page coordinates. When you compute the inverse of that transformation, you should be able to convert from page coordinates back to the source coordinates, and those are the ones you should store with your markups. The conversion into the source coordinates might look something like this:
const res = viewer.clientToWorld(ev.clientX, ev.clientY);
if (res && res.point) {
console.log('page coords', res.point);
const sourceToLogicalXform = viewer.model.getData().metadata?.page_dimensions?.source_to_logical_xform;
if (sourceToLogicalXform) {
const sourceToLogical = new THREE.Matrix4().fromArray(sourceToLogicalXform).transpose();
const logicalToSource = new THREE.Matrix4().getInverse(sourceToLogical);
console.log('source coords', res.point.clone().applyMatrix4(logicalToSource));
}
}

Get all Google Map v3 markers loaded from GeoJSON

I load data for my Google Maps v3 with GeoJSON:
that.map = new google.maps.Map($('#map')[0], mapOptions);
that.map.data.loadGeoJson('http://localhost/geoserver/...');
Now, at some point on some user event I need to get one marker and paint it blue.
I can set different color with setIcon.
My idea is to get all features, then iterate through them, find the right feature (based on UNIQUE feature data field) and find marker behind that feature and change icon. I found some approaches that store all markers in array, but don't know why I need another array. Computer resources are important and I don't want to duplicate things.
I need help with, how to get features and how to get Marker object associated with selected feature. If there is a better way to do it, please...
UPDATE
I found this:
var feature = this.map.data.getFeatureById(ID);
I just need to get feature Marker. How? Doesn't look that Feature class has method for that?
There is no method/property that gives you access to the shape(marker,polygon,etc.) that has been created by the API.
To set a new icon-property for a particular feature use overrideStyle:
map.data.overrideStyle(feature, {icon: newIconSettings});
Another option is:
that.map.data.setStyle(function(feature)
{
var color = 'red';
if (feature.getProperty('color'))
{
color = feature.getProperty('color');
}
return ({ // #type {google.maps.Data.StyleOptions}
icon: 'http://maps.google.com/mapfiles/ms/icons/' + color + '-dot.png',
});
});
But it is not as good as Dr. Molle solution, because it needs to iterate through entire features set. I found it on google api documentation (look for title Change Appearance Dynamically).

HTML5 Canvas Placemark for Google Maps API v3

I'm looking for a way to generate complex Placemarks (or overlays that are "attached" to placemarks).
Is there a way (I haven't found it) with the Map v3 api to attach/overlay a on placemark?
Or, will I need to draw outside of the Google api and then have listener/s that trigger redrawing when the user pans the map?
You extend google.maps.OverlayView with an object that override onAdd(), draw(), and onRemove()
In onAdd you'll probably want to set up a reference to a pane in google.maps.MapPanes to put your markup into. Then you'll have to handle the pan and zoom events. You do that like so:
CustomOverlayView.prototype.initPanes = function() {
var panes = this.getPanes(); //object of type google.maps.MapPanes
this.drawPane = jQuery(panes.floatPane); //we will initialize our stuff in this div element
this.drawPane.attr("id", "map-draw-pane"); //conceivable to want to reference this, usefull for debugging
this.drawPane.css("background-color", "transparent"); //DONT COVER THE GOOGLE COPYRIGHT
};
In order for your canvas to be useful for drawing, you need a way to convert your google.maps.LatLng objects into Point objects with x and y variables. The answer is in google.maps.MapCanvasProjection which has various methods that compute location objects encoded as google.maps.LatLng objects into useful pixel coordinates (and back again).
var projection = this.getProjection();//google.maps.MapCanvasProjection
var drawingLocationPoint = projection.fromLatLngToContainerPixel(markerData.location);
Some details of how to put a canvas in google maps here: http://www.samedwards.net
This is easily done, so I'm sorry an answer didn't appear sooner. Hopefully this is still useful to you.
See:
http://code.google.com/apis/maps/documentation/javascript/overlays.html#CustomOverlays
And here's an example:
http://code.google.com/apis/maps/documentation/javascript/examples/overlay-simple.html
You need to implement a Javascript class which extends OverlayView. Specifically, you will write a draw() method that the Maps API will call whenever the state of the map has been changed (e.g. it has been dragged or zoomed).
In that method you can create a HTML5 canvas (or anything really) and draw whatever you need. You get access to the underlying map projection, which lets you reliably convert LatLngs to pixels for the current zoom level and projection type.
I would recommend looking at this semi official extension library for creating a canvas overlay:
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/canvaslayer/
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/canvaslayer/examples/hello2d.html
as well as this sample, which uses raphael instead, but shows how you might associate your additional objects with markers:
http://gmaps-samples-v3.googlecode.com/svn/trunk/cloud/cloud.html

Marking streets in Google Maps

I want to create an overlay on top of Google Maps that displays different streets in different colors.
In the Google Maps API it is possible to create markers and polygons that cover certain areas.
Is there a way to somehow mark different streets?
It sounds to me like you are interested in showing some application specific coloring for your Google maps display (rather than traffic maps).
If so , then you should check out custom overlays. You can create your own transparent background overlay tiles (with your colored streets), match them up with the Google maps tiles and then overlay them on the map. You can find a description of this stuff in the Maps API reference - Overlays.
I have actually been interested in trying this out, and this question might be a good excuse. I'll let you know how I go.
Edit: Ok, I tried this and it was pretty straightforward. You just need to grab the tiles images when the google maps page load (for the area you would like to overlay). Make sure you keep track of the origional urls, because these have the x,y coordinates that you will need to write your tile overlay method.
Edit the tiles with your colored roads then upload them to your web server. Add the following code to use your overlay on the regular map:
var myCopyright = new GCopyrightCollection("© ");
myCopyright.addCopyright(new GCopyright('Demo',
new GLatLngBounds(new GLatLng(-90,-180), new GLatLng(90,180)),
0,'©2007 Google'));
// Create the tile layer overlay and
// implement the three abstract methods
var tilelayer = new GTileLayer(myCopyright);
// properties of the tile I based my tile on
// v=w2.97&hl=en&x=38598&s=&y=49259&z=17&s=Galil.png
tilelayer.getTileUrl = function(point, zoom) {
if (zoom == 17 && point.x == 38598 && point.y == 49259)
return "../pics/times_square.png";
};
tilelayer.isPng = function() { return true;};
tilelayer.getOpacity = function() { return 1.0; }
var myTileLayer = new GTileLayerOverlay(tilelayer);
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(40.75740, -73.98590), 17);
map.addOverlay(myTileLayer)
This code overlays my Thing eats NY tile:
at x = 38598 and y = 49259 at zoom level 17.
It is possible to create markers and polygons in the Google Maps API. You need to create GPolygon and/or GPolyline objects
Have a look to these tutorials
And if you want to obtain the coordinate (latitude, longitude) of certain streets, you may have a look to the source code of this page
I am not sure to fully understand your question: do you want to mark some given streets ?
in that case, a quick-and-dirty way could be to get the coordinates of all the addresses of the street and build a GPolygon according to them...
Have you concidered using OpenStreeMaps?
Try digging into the code used to show the traffic overlay on the normal Google Maps site.
Edit: I just looked at the code, and it appears that even Google decided it was easier to implement this by just generating the traffic lines on the server and pulling them down as transparent PNG overlays.
I just found this link, and I think this could interest you. It is a JavaScript package that provides functionality for displaying multiple routes on Google Maps.
Is it what you were looking for ??