Styling handles/control points on polyline in edit mode - google-maps

Is there a way to change the style of the white squares that are used as vertex handles by default when a polyline is set to editable:true?
I can see that changing the stroke of the polyline affects those handle squares, but I'd like to either change the shape of handle (e.g. to a circle), or substitute an image.

The only way I've managed to found is a direct manipulation of DOM elements corresponding to those markers. For instance, they may be selected using
$('div').filter(function() {
return $(this).css('width') == '11px';
})
Probably, more reliable approach is a DOM tree traverse starting from $('.gm-style') element.

Related

Find elements with opacity==0 elements and make them visible with Forge

We're trying to visualize an IFC model with forge that contains a lot of invisible elements.
One problem we're facing is that the elements that is invisible does not fall under the normal category of hidden elements. E.g. model.setAllVisibility(true) does not make them appear. Also, model.visibilityManager.hiddenNodes is empty and model.visibilityManager.setVisibilityOnNode(dbId, true) does nothing to make them appear.
What seems to be the case with these elements is that their material.opacity is 0.
We tried setting the opacity to 1, and also tried using a different material, with no luck.
The only thing we have managed to do so far is to highlight the element's corresponding fragment:
model.setHighlighted(fragId, true)
however, this does not really cut it (unless it's possible to highlight many elements, and make them transparent?).
It's also worth mentioning that:
The elements comes from a IfcBuildingElementProxy IFC type
Calling viewer.setDisplayEdges(true) makes it possible to see the wireframe of the invisible elements
It's possible to click on the elements even though they are invisible.
So, my questions:
Is there any good way to find all the invisible elements in a model?
Is it possible to change them to be visible without highlighting them?
The viewer doesn't provide any solution for this out-of-the-box but it should be quite straightforward by putting together some of the viewer's features:
To check the opacity of all objects, you can just get the list of all fragments, and check the opacity of each material:
const frags = viewer.model.getFragmentList();
for (let i = 0; i < frags.getCount(); i++) {
const mat = frags.getMaterial(i);
console.log(mat.opacity);
}
And then, when you find materials you would like to change, you can do that, too. Here's some resources that might help:
how to add custom material to a fragment in forge viewer
https://forge.autodesk.com/blog/material-swatches-forge-viewer
https://forge.autodesk.com/blog/custom-shader-materials-forge-viewer

Mapbox GL JS: Stacking order of features in layer – what determines it? Can you change it?

I have a vector tile layer with about ~120 features ranging in size from over a million acres down to less than 20. I am having issues with mouseover whereby the large features are occluding the small ones, which are behind them.
I assume this has to do with the source data, which was sorted alphabetically by location name. As it happens, "Carson National Forest," which is big, is on top of "Valle Vidal" which is much smaller. So I can't select the latter with mouse interaction.
Is the solution to sort the features in ascending order by acreage and reimport the dataset, or is there something I can do within the Mapbox GL JS API to swap their positions?
Thanks!
There are two solutions to your problem.
I'll assume that your polygons have an area attribute.
Find the smallest polygon in mouseover
First, big polygons don't actually block small polygons from firing a "mouseover" event. The event is fired with all the features underneath the mouse. So you could intentionally select the smallest one.
map.on('mouseover', e => {
e.features.sort((a, b) => a.properties.area - b.properties.area);
const smallestFeature = e.features[0];
});
This method also works if you don't have an area attribute - you could use Turf to calculate it dynamically, although it would be incorrect at tile boundaries.
Use fill-sort-key to sort polygons
The other method is to use the fill-sort-key attribute in the layer definition:
layout: {
'fill-sort-key': ['-', ['get', 'area']]
}

Setting cutplanes for polygon shape

I am using Autodesk.Viewing.Markupscore extension to draw a polygon in 3D view in top view (orthographic)
I want to see only those elements which are inside the polygon
For which I am using the cutplanes concept because bounding box logic is taking too long to process.
So Please suggest a way to apply cut planes along these lines.
Try programmatically cutplanes with an array of vector4s specifying the four sides say:
vectorArray.push(new THREE.Vector4 (0.9999999999999998, 0, 0, 0.06520926952362059)) //x,y,z,w
viewer.setCutPlanes(vectorArray)
See documentation here

Setting QTextDocument painter's rectangle (where to paint)

I am painting on a window simple html using QTextDocument::drawContents(painter)
I want to do the drawing inside some margins in the window but I don't see a direct way to specify the target rectangle of the painting (in the painter/window).
I guess a few ways to do it:
Using the QTextDocuments::setMargin (although this does not allow different values for left/top.
Placing the html into an styled <div>
Applying a translation transform to the painter.
But all this seems a bit too much for what I want to do and I guess if I a missing something straight (as you do with QPainter::drawText where you tell the target rectangle)
Set the textWidth property to the width of the area where the text is supposed to fit. The clipping rectangle you pass to drawContents will cut the text off vertically if there's too much of it to fit; you can't do much about that of course.
So, this would be the missing function you're after:
void drawContents(QPainter * p, QTextDocument & doc, const QRectF & rect) {
p->save();
p->translate(rect.topLeft());
doc.setTextWidth(rect.width());
doc.drawContents(p, rect);
p->restore();
}
Yes, you do need to jump through a few hoops, that's why it needs to be factored out. It's perhaps lamentable that a similar overload of drawContents doesn't exist.

Background-image opacity and :hover

Is it possible to only trigger a div's mouseover when the cursor is over an opaque part of the div's background image? Perhaps via Javascript?
All I can find with Google are old IE PNG fixes.
This looks like a similar question to this one: Hit detection on non-transparent pixel
I suppose this could also be done for background image by getting the attribute with jQuery:
$('#myDiv').css('background-image');
I haven't personally done this, but it seems like a viable solution. This will only work for modern browsers, but you should be able to make it back-compatible with excanvas.
It is possible, just not very easily. You'll have to use a lot of Javascript.
You'd want to attach to your <div>'s onmousemove event, which returns the X,Y coordinates of the cursor. Your event handler function would then test to see if the cursor is in the correct place in order to trigger an alternative onmouseover event.
Implementing the "is the cursor over an opaque pixel or not?" test can be done two ways: the first is to create a simple mathematical expression (say if the opaque parts of the image make neat rectangles, circles or polygons). The more difficult (and less browser-supported) way is to load the background image into a Canvas object and then get the current pixel value's opacity figure and take it from there, like so:
var pixel = canvas.getImageData(x, y, 1, 1).data;
var alpha = pixel[3]; // assuming RGBA
if( alpha > threshold ) onMouseOver(); // raise the event
Another alternative is to create an entirely transparent div (or some other element) positioned and sized so that it only covers the opaque part of the div below, then just test the mouseover of that element's box.
It's a bit of tweaking but why don't you add a class to your opaque div, and use JavaScript to check for it?
In jQuery:
$('div').mouseover(function(){
if ($(this).is('.opaque')) {
//Some actions
}
});