How to click 'through' an entity to the ground underneath?

I have a dynamic polyline that I’m creating that increases and decreases in length with a mouse cursor movement. I want to do something when I click on the map, but often the line (and its corresponding billboard/label) will be under the cursor, which makes Cesium think I’m clicking on the entity rather than the world underneath it.

How can I tell Cesium to ignore an entity being clicked on, or set up the entity such that it cannot be selected at all (such that clicking on it goes through to the world underneath)?

Depends on your picking function. When you click on the map, what function do you use?

Cheers,

Alex

@Alexander_Johannesen When clicking on the map itself, I use const cartesian = viewer.scene.pickPosition(event.position);.

However I also want to be able to click on entities underneath the line, which wouldn’t use event.position (and would instead rely on there being a selected entity when I click)

Yeah, that one by itself isn’t useful for what you need, but depending on how you string your logic together I’d look at sampleHeight() where you can inject objects to ignore, or more specifically - the way I’d do it;

Use drillPick() to look for the stack of objects in my path (it returns an array, so check the array.length), and then choose to use pickPosition() if no objects are in my path, or sampleHeight() if there are. Using the right picking method in Cesium can be a bit hit and miss, because some pickers change the underlying data, so you may need to experiment with in which order you do the picking.

Cheers,

Alex

@Alexander_Johannesen I’m a little confused into how sampleHeight() operates here - I see that I can tell it to ignore an entity, but how would i use the height to get the position underneath the entity?

And - in light of we are discussing - I’m guessing there is no way to create an entity such that no clicks can be made upon it, only through it?

I only used it as an example, I don’t know what you’re trying to do at that point. Basically, if drillPick().length == 0, you can safely use pickPosition(), otherwise do what other thing you want to do with the entity you clicked on. If you need to click through them all if there are entities in the way, you could;

  1. Hide all the objects
  2. subscribe to preRender()
  3. Wait one render cycle
  4. Use pickPosition()
  5. Show all hidden objects
  6. unsubscribe from preRender()

Cheers,

Alex

@Alexander_Johannesen I think i see what you mean, although my question was about how to use sampleHeight to pick a position.

Additionally, what I’m running into is slightly different IMO, as the dynamic polyline is getting in the way of terrain and other entities beneath it. For example:


An example of a circle entity I would like to draw a polyline to.


I click on the map and the polyline automatically begins to follow the cursor until I reach the entity (the cursor is inside the circle in this image).


But when I click, the mouse thinks it’s over the top of the line first and instead clicks on the line instead, rather than the entity. This prevents me from selecting the circle entity, which is set up to snap the line to the point in the centre.

I’d like to be able to click on either the entity there or the ground and have cesium not think i clicked on the line instead.

Well, sampleHeight() is just one of many, you might also look into globe.pickEllipsoid() and match the returned height with pickPosition(), get the coordinate of what you clicked on through that, and then use sampleHeight() to find out if you hit the terrain or something else, or on a path between the two. This is not an easy thing to do, especially as pickPosition() can’t ignore anything.

As to your images, after the last one you say “But when I click”, what are you clicking on? What are you meaning to happen? Where do you click, and what should happen? The cursor are on the line at some position, and you click away (for example on the terrain) to unselect it, is that what you mean?

I have to admit not using the cursor at all, so there might be some technical stuff around it that I can’t help you with.

Cheers,

Alex

@Alexander_Johannesen In that image, I’m clicking on the red circle. What’s supposed to happen is that cesium is supposed to recognise that I’m click on the red circle, snap the polyline to the center of the red circle and then ‘bake’ the line into place such that it doesn’t follow the mouse cursor anymore.

However, cesium instead thinks I want to click on the polyline, because it lies over top the red circle and the polyline follows the mouse cursor (and thus is ‘beneath’ the cursor). As such it doesn’t snap to the red circle’s center and keeps following the mouse cursor.

That, to me, sounds like what you use drillPick() for; iterate over the result till you get a circle.

So, a lot of this kinda stuff comes down to how you’ve put your application together, and how you work with entities and the mouse. To me, it sounds like you’re making a draw-line-tool; click the map, a line now follow around from the initial point to the cursor, and a second click on something is the line done.

But the question then is, with your second click, do you want to draw a line from the initial point to the second point you clicked (exactly), or to the circle (either at the edge, or the center) more abstractly?

If the latter, here’s what I would do. When you create an entity it’s often helpful to add a property to it that you can recognise, and then look for this property when you do a drillPick(). For example;

viewer.entities.add({
   // other stuff here, and then ...
   name: 'My red circle',
   myCircle: true,
   // and the rest
});

In drillPick() you get back entities, just do a find on any entity that has that property. If you find it, use the center point (or center point plus the diameter offset to the edge) directly instead of trying to trick pickPosition() into things it can’t do.

Cheers,

Alex

@Alexander_Johannesen The second click is supposed to be used to draw a line to whatever’s at the second position exactly. If it’s a position on the map, it will stop at that position; if it’s on an entity, it will snap to the middle of that entity.

With the current problem, the polyline can get in the way and prevent clicking on the entity (or the world, although this occurs more randomly) as the click is registered on the polyline instead. It’s less about using drillpick to select an entity and more about knowing what I’m clicking on.

EDIT: Doing some checking - confirming that the entity that I would like to click on never gets registered as a click in those circumstances; instead what is happening is that it’s taking the click as a world position and using that to finish the line.

I do this quite a lot, and I iterate through the return of drillPick() to see what I bump into. The immediate pickPosition() is on the first element in the array, unless length == 0, then the position is terrain / ellipsoid. With that info you can do what you want, as described in earlier replies.

You can easily create a loop that does drillPick() in a loop and display to the screen what it finds, including your polyline and red circle.

Cheers,

Alex

I used sort of this method in the end - essentially, I used drillPick to see what entities are being clicked by going through the resulting array. It goes through until I either find an entity that’s not the polyline (which would then start the normal entity selection process) or I run out of entities.

Thanks!

1 Like