-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added terrain drawing sandcastle example #6692
Conversation
@OmarShehata, thanks for the pull request! Maintainers, we have a signed CLA from @OmarShehata, so you can review this at any time.
I am a bot who helps you make Cesium awesome! Contributions to my configuration are welcome. 🌍 🌎 🌏 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job @OmarShehata! A very helpful (and fun!) example.
Some suggestions:
- It would be nice if we could add minimal onscreen instructions for using the demo. We can just add this in the HTML, and maybe consider removing the instructions in the comments.
- To avoid the infobox showing up when you click on an entity, I think we should disable it entirely.
- Double-clicking to place a point sets the viewer's target entity, which causes some unexpected camera movement.
var dynamicPositions = new Cesium.CallbackProperty(function () { | ||
// This is a work-around since polylines when `clampToGround` is true will | ||
// crash if you try to draw a zero length line | ||
if (activeShapePoints.length === 2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this fixed by the latest polyline on terrain PR? If not, can we open an issue if there isn't already one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just tested it with the fix in #6693 and it looks like we don't need this workaround anymore! I'll remove it.
} | ||
}); | ||
} | ||
if (drawingMode === 'polygon') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This structure of two independent if
statements seem odd to me, even though only one will be exected-- We should use one behavior or the other
Since we only have two drawing modes, do you think a boolean would be a better way than a string to keep track of which mode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved this into a function as per @hpinkos 's suggestion, but I don't think we should make it just a boolean. If it were just something like drawingLines
, then to me it's not obvious that when that's false then it draws polygons as opposed to something else. I think it makes more sense for it to be an explicit mode.
I did make it an else if
since you are right that there's no scenario where you want both to run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I see your point. In that case, maybe it's worth renaming the mode and label from "line" to "polyline" to match the entity type used?
<style> | ||
@import url(../templates/bucket.css); | ||
|
||
#viewChanged, #cameraChanged { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless I missed something, I don't think these styles are used anywhere.
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND | ||
} | ||
}); | ||
viewer.entities.add(point); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be consistent with the rest of our sandcastle examples, use
var point = viewer.entities.add({
...
});
selectionIndicator : false, | ||
terrainProvider : Cesium.createWorldTerrain() | ||
}); | ||
// Create a function to place a point given a world position. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We try to avoid cluttering up sandcastle examples with inline comments unless there is something truly non-obvious. I think most if not all of these comments can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point - I just noticed most of the other Sandcastle examples don't have comments. I was treating it more as a tutorial, but perhaps I could write up an actual tutorial for that later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, a tutorial would be the way to go with all that extra information
// `earthPosition` will be undefined if our mouse is not over the globe. | ||
if (Cesium.defined(earthPosition)) { | ||
// If this is the first point, we need to initialize the shape. | ||
if (activeShapePoints.length === 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be combined with the above if statement.
if (Cesium.defined(earthPosition) && activeShapePoints.length === 0)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's actually a couple of things that happen even if activeShapePoints.length != 0
that's why it's 2 statements.
// On right click, terminate active shape and redraw it as a new entity without the `CallbackProperty`. | ||
function terminateShape() { | ||
activeShapePoints.pop(); | ||
if (drawingMode === 'line') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks duplicated with L88-105. Maybe make a function to handle this like you did for createPoint
@hpinkos I didn't realize View As Thumbnail was a feature! That looks super useful. I'm having trouble with that though - it scales it down to what looks like the right aspect ratio but not the right dimensions. The correct size for thumbnails seems to be 225x150 (based on what most of the other ones are), does that sound right? |
Once the tests run, this should be ready for review again @ggetz ! |
Yes, it should be 225x150px. I've always used the thumbnail button, taken a screenshot, and cropped it using a paint program and it's turned out correctly. |
activeShapePoints.pop(); | ||
drawShape(activeShapePoints); | ||
viewer.entities.remove(floatingPoint); | ||
viewer.entities.remove(activeShape); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The shapes flash when you terminate the shape. Is it possible to re-use the same entity and create the position property, or do we have to delete the old one and create a new dynamic one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tested that out, and it'll still take a few seconds to render when you switch the CallbackProperty
with just an array of points.
I talked briefly with @mramato about this. We could do any of the following to remove that flicker:
- Keep all the shapes with
isConstant : false
- Don't remove the dynamic shape right away, keep it there for a few seconds to hide the gap until the new one renders.
But none of those seem like good practices we want to encourage in an official Sandcastle example.
It might be nice to have a "flush" command that would try to immediately render an entity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a long standing issue in "sometimes changing" geometry data in Cesium. I recommend this PR keeps whatever is cleanest for example code. I would love to see us improve interactive geometry like this, but it's probably going to result in a request-render style method for entities that needs to be thought through.
@OmarShehata Thanks for the updates! Have you merged |
Sorry about that @ggetz , just pushed the merge! |
A very nice Sandcastle example, @OmarShehata ! And useful- I've already linked to it from a forum question. Thanks! |
This adds a Sandcastle example of how to dynamically draw lines and polygons over terrain. Click to add a vertex, right click to terminate current shape and start a new one.
The polygons are clamped to the terrain. The lines are clamped once #6689 is merged. You can test it in the mean time by commenting out
clampToGround : true,
in the two locations (but you won't see the lines if you're zoomed in because they'll be under the terrain).The only issue is that there seems to be a bit of a lag when you terminate the shape. @mramato do you know a way to fix this? The relevant function is here.