Skip to content
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

CoplanarPolygonGeometry and CoplanarPolygonOutlineGeometry #6769

Merged
merged 6 commits into from
Jul 10, 2018
Merged

Conversation

hpinkos
Copy link
Contributor

@hpinkos hpinkos commented Jul 3, 2018

Adds support for drawing polygons composed of arbitrary coplanar positions. (It doesn't crash if the positions are not coplanar, but the resulting triangulation is unpredictable and probably won't work as desired)

poly

Related #3349 (adds support for vertical polygons but doesn't fix that KML file)

Test code:

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;

var polygonGeometry = new Cesium.CoplanarPolygonGeometry({
    vertexFormat : Cesium.VertexFormat.ALL,
    positions : Cesium.Cartesian3.fromDegreesArrayHeights([
       -91.0, 50.0, 0.0,
       -90.0, 50.0, 200000.0,
       -89.0, 50.0, 200000.0,
       -88.0, 50.0, 0.0
    ])
});

var polygonInstance = new Cesium.GeometryInstance({
    geometry : polygonGeometry,
    attributes : {
        color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE)
    }
});

scene.primitives.add(new Cesium.Primitive({
    geometryInstances : polygonInstance,
    appearance : new Cesium.MaterialAppearance({
        material : Cesium.Material.fromType('Checkerboard'),
        materialSupport : Cesium.MaterialAppearance.MaterialSupport.TEXTURED
    })
}));

scene.primitives.add(Cesium.createTangentSpaceDebugPrimitive({
	geometry : polygonGeometry,
	length : 100000.0
}));

@cesium-concierge
Copy link

Signed CLA is on file.

@hpinkos, thanks for the pull request! Maintainers, we have a signed CLA from @hpinkos, so you can review this at any time.


I am a bot who helps you make Cesium awesome! Contributions to my configuration are welcome.

🌍 🌎 🌏

@hpinkos
Copy link
Contributor Author

hpinkos commented Jul 3, 2018

This doesn't connect anything to the Entity API layer. I was planning to figure out if and how we want to do that in a separate PR.

@hpinkos
Copy link
Contributor Author

hpinkos commented Jul 6, 2018

@ggetz can you review?

@ggetz ggetz self-assigned this Jul 6, 2018
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Draw the outline of a cylinder.">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update description.

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Draw an ellipsoid.">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update description.


var i;
// If all the points are on a line, just remove one of the zero dimensions
if ((xMag === 0 && (yMag === 0 || zMag === 0)) || (yMag === 0 && zMag === 0)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be some sort of error or warning rather than the geometry just not being created?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess to answer my own question, that is the behavior when less than 3 positions are supplied.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, we decided a while ago to just return undefined and not render invalid geometry instead of throwing an error. This is mostly because there's a lot of garbage data in KML and GeoJSON files that are automatically generated and we don't want to crash the whole file because we don't know how to render one of the polygons

var zMag = Cartesian3.magnitude(zAxis);
var min = Math.min(xMag, yMag, zMag);

var i;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declare i down where it's being used.


/**
* A description of a polygon composed of arbitrary coplanar positions.
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we mention in the docs that if the positions are not coplanar, it will re-project them to a plane?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't. It will attempt to draw whatever positions are passed in, but for best results the positions should be coplanar

*
* @param {Object} options Object with the following properties:
* @param {Cartesian3[]} options.positions The positions of the polygon
* @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also have stRotation as an option? PolygonGeometry has this as an option. Besides the polygon hierarchy, all the other options aren't applicable here AFAIK.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, trying to keep the options as minimal as possible for this one. We can expand it later if someone asks or it.

if (positions.length < 3) {
return;
}
var bs = BoundingSphere.fromPoints(positions);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the coding guide, I believe we avoid abbreviations.


var attributes = new GeometryAttributes();

if (vertexFormat.position) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we always have position?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theoretically yes, but someone could technically define whatever they want for vertexFormat

Check.defined('positionsResult', positionsResult);
//>>includeEnd('debug');

var obb = OrientedBoundingBox.fromPoints(positions, obbScratch);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here about abbreviations.

var obbScratch = new OrientedBoundingBox();

// call after removeDuplicates
PolygonGeometryLibrary.projectTo2D = function(positions, positionsResult, normalResult, tangentResult, bitangentResult) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a spec for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's covered between CoplanarPolygonGeometry and CoplanarPolygonOutlineGeometry. We don't have specs for any of the other *GeometryLibrary static classes.

@ggetz
Copy link
Contributor

ggetz commented Jul 6, 2018

@hpinkos Can you clarify what projectTo2D is doing in cases where the geometry is not coplanar, like in this case?

image

@hpinkos
Copy link
Contributor Author

hpinkos commented Jul 6, 2018

Can you clarify what projectTo2D is doing in cases where the geometry is not coplanar, like in this case?

projectTo2D is just an private helper function. We need to project the points to 2D for the polygon triangulation, but it does not alter the positions that are passed into the geometry

var planeYAxis;
var origin = Cartesian3.clone(center, scratchOrigin);
var normal;
if (min === xMag) {
Copy link
Contributor

@bagnell bagnell Jul 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can probably be more simple. Once you find the vectors with the minimum and maximum length:

z = cross(x, y); // normal
y = cross(z, x);
// normalize x, y, and z

It doesn't matter if you use z or -z for the normal. It also doesn't matter if you use +/-x or +/-y as long as they are orthogonal in the plane.

var normal;
if (min === xMag) {
if (min !== 0) {
origin = Cartesian3.add(origin, xAxis, origin);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why move the origin from the bounding box center?

Copy link
Contributor Author

@hpinkos hpinkos Jul 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's because all the points are already in a plane and I need a new plane to project them onto =P
There's definitely a better way to do this. I hadn't given this logic any thought since I wrote it at our first code sprint down the shore. Thanks for pointing that out!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh no wait! It's because I want the intersection plane to be where the OBB box face is instead of at the center of the box.

for (i = 0; i < positions.length; i++) {
ray.origin = Cartesian3.clone(positions[i], ray.origin);

var intersectionPoint = IntersectionTests.rayPlane(ray, plane, scratchIntersectionPoint);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to intersect the ray with the plane. You just need this:

v = subtract(positions[i], origin);
x = dot(xAxis, v);
y = dot(yAxis, v);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that's the case when the positions are actually coplanar. But I need it to work with positions that are mostly coplanar and to "try it's best" for a set of arbitrary points so I think I still need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I guess you're right though, the results come out the same for both. Thanks!

@hpinkos
Copy link
Contributor Author

hpinkos commented Jul 6, 2018

Thanks @ggetz, @bagnell! Anything else?

return;
}
var center = orientedBoundingBox.center;
var origin = Cartesian3.clone(center, scratchOrigin);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need this anymore. Just subtract from center below.

@bagnell
Copy link
Contributor

bagnell commented Jul 6, 2018

👍 Looks good to me, just that one last comment. @ggetz can merge when ready.

@hpinkos
Copy link
Contributor Author

hpinkos commented Jul 10, 2018

@ggetz ready

@ggetz
Copy link
Contributor

ggetz commented Jul 10, 2018

👍 Thanks @hpinkos!

@ggetz ggetz merged commit 7151a21 into master Jul 10, 2018
@ggetz ggetz deleted the space-polygon branch July 10, 2018 15:41
@bmckilligan
Copy link

@hpinkos
Copy link
Contributor Author

hpinkos commented Jul 24, 2018

@bmckilligan all fixed!

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants