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

Added feature to modify scene pick search size #5602

Merged
merged 13 commits into from
Jul 13, 2017

Conversation

jason-crow
Copy link
Contributor

This feature adds two optional arguments to the scene pick method, width and height, which allows for modifying the bounding box used to search for matching primitives at the provided window position. If only width is provided, the height is set to the value provided for width. To verify this feature, I added two tests, one to pick a primitive at the extent of the pick size and one to fail to pick the primitive when the pick size is reduced from the same window position.

This feature makes it easier to select narrow primitives such as wireframes in a 2d scene.

… method to accomodate a feature for modifying the size of the pick aperture. This, for example, makes it easier to select wireframe elements or other similarly narrow tileset elements by providing a means to increase the box volume used to pick an intersecting primitive.
@hpinkos
Copy link
Contributor

hpinkos commented Jul 10, 2017

Thanks for the pull request @jason-crow! @bagnell, do you want to review this?

CONTRIBUTORS.md Outdated
@@ -2,6 +2,9 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu

## [Corporate CLA](Documentation/Contributors/CLAs/corporate-cla-agi-v1.0.txt)

* [Bentley Systems ](https://www.bentley.com/)
* [Jason Crow](https://github.com/jason-crow)
Copy link
Contributor

Choose a reason for hiding this comment

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

There's already a section for Bentley Systems at line 84. Add yourself under Paul Connelly instead

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, updated

@jason-crow
Copy link
Contributor Author

jason-crow commented Jul 10, 2017 via email

// override the rectangle dimensions if defined
var rectangleWidth = width || 3.0;
var rectangleHeight = height || width || 3.0;
var scratchRectangle = new BoundingRectangle(0.0, 0.0, rectangleWidth, rectangleHeight);
Copy link
Contributor

Choose a reason for hiding this comment

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

It is still worth storing the scratch rectangle in file scope so that a new rectangle isn't allocated for every pick call.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My only thought on using the scratch rectangle is that it will modify the default size for future calls to pick. So if you decided to call pick and change the size to say 10, from there on the pick routine will use 10 instead of 3 until another call to it is made that changes the size. I suppose I could reset it back to the default at the end of the routine...

Copy link
Contributor

Choose a reason for hiding this comment

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

Similar to how scratchRectangle.x and .y are set always, you could set .width and .height right below.

//>>includeStart('debug', pragmas.debug);
if(!defined(windowPosition)) {
throw new DeveloperError('windowPosition is undefined.');
}
//>>includeEnd('debug');
// override the rectangle dimensions if defined
var rectangleWidth = width || 3.0;
var rectangleHeight = height || width || 3.0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Use defaultValue here:

var rectangleWidth = defaultValue(width, 3.0);
var rectangleHeight = defaultValue(height, rectangleWidth);

Also the comment above can be removed.

@@ -2793,16 +2790,22 @@ define([
* }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
*
* @param {Cartesian2} windowPosition Window coordinates to perform picking on.
* @param {Number} [optional] width of the pick rectangle
* @param {Number} [optional] height of the pick rectangle
Copy link
Contributor

Choose a reason for hiding this comment

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

For optional arguments the name of the argument should be within the brackets, with default values shown, like:

@param {Number} [width=3] Width of the pick rectangle.
@param {Number} [height=3] Height of the pick rectangle.

var scene = actual;
var result = scene.pick(new Cartesian2(0, 0));
var result = scene.pick(new Cartesian2(x || 0, y || 0), pickWidth, pickHeight);
Copy link
Contributor

Choose a reason for hiding this comment

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

Also use defaultValue here.

camera.setView({
destination : Rectangle.fromDegrees(-10.0, -10.0, 10.0, 10.0)
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe just always construct scene with a 10x10 canvas in beforeAll and add the camera adjustment to the individual tests. This will avoid the scene creation boilerplate.

return pickPrimitiveEqualsWrapper(actual, undefined, config.x, config.y, config.size);
}
};
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of adding these two perhaps just add the functionality to toPickPrimitive and notToPick.

Copy link
Contributor

Choose a reason for hiding this comment

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

In this case it would be fine to send in the values as separate arguments instead of a config object.

@@ -94,6 +110,35 @@ defineSuite([
expect(scene).toPickPrimitive(rectangle);
});

it('picks a primitive at pickSize extent', function() {
Copy link
Contributor

Choose a reason for hiding this comment

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

pickSize isn't a name used by the API. Maybe instead picks a primitive with a given width and height.

y = y || 0;
var adjustedX = x + ((width - 1) * 0.5);
var adjustedY = -1 * (y + ((height - 1) * 0.5) - actual._context.drawingBufferHeight);
return pickPrimitiveEquals(actual, expected, adjustedX, adjustedY, width, height);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not completely following the conversion process here. Can the test be modified instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this conversion is the inverse of

scratchRectangle.x = drawingBufferPosition.x - ((rectangleWidth - 1.0) * 0.5);
scratchRectangle.y = (this.drawingBufferHeight - drawingBufferPosition.y) - ((rectangleHeight - 1.0) * 0.5);

from lines 2829 in Scene.js

Honestly, I don't understand what this logic is accomplishing, but for the test I need to set the bounding box for the pick search to be centered at a position exactly far enough from the rectangle for the increase in pick size to affect the outcome. This was just something that would never work right until I implemented this logic.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, I see now. By changing to test to pass in x and y values other than 0 should also work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

are you saying this conversion is unnecessary when the x and y values aren't 0?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I tried x = 7 and y = 7 and that seems to work.

@lilleyse
Copy link
Contributor

@jason-crow is this ready for another pass?

@jason-crow
Copy link
Contributor Author

Yes

Copy link
Contributor

@lilleyse lilleyse left a comment

Choose a reason for hiding this comment

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

Thanks for the updates @jason-crow! I also added some comments for things I missed on the first go.

// override the rectangle dimensions if defined
rectangleWidth = defaultValue(width, 3.0);
rectangleHeight = defaultValue(height, rectangleWidth);
scratchRectangle = new BoundingRectangle(0.0, 0.0, rectangleWidth, rectangleHeight);
Copy link
Contributor

Choose a reason for hiding this comment

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

Check out my latest comment here: #5602 (comment). I think we can get away without allocating the scratch rectangle in the function.

var scene = actual;
var result = scene.pick(new Cartesian2(0, 0));
var windowPosition = new Cartesian2(defaultValue(x,0), defaultValue(y,0));
Copy link
Contributor

Choose a reason for hiding this comment

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

Cartesian2 defaults to 0.0 by default when arguments are undefiend, so just new Cartesian2(x, y) should work.

@@ -20,7 +20,7 @@ define([
options = defaultValue(options, {});

// save the canvas so we don't try to clone an HTMLCanvasElement
var canvas = defined(options.canvas) ? options.canvas : createCanvas();
var canvas = defined(options.canvas) ? options.canvas : createCanvas(10,10);
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of the default of (10, 10) here, PickSpec should instead send in a 10x10 canvas.

@@ -10,7 +10,7 @@ defineSuite([
'Scene/PerspectiveFrustum',
'Scene/Primitive',
'Scene/SceneMode',
'Specs/createScene'
'Specs/createScene',
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove comma.

compare : function(actual, expected) {
return pickPrimitiveEquals(actual, undefined);
compare : function(actual, expected, x, y, size) {
return pickPrimitiveEquals(actual, undefined, x, y, size);
Copy link
Contributor

Choose a reason for hiding this comment

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

For these two send in width and height instead of just size for consistency.

expect(scene).notToPick(0,0,3);
});


Copy link
Contributor

Choose a reason for hiding this comment

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

Remove this extra line.


createRectangle();

expect(scene).notToPick(0,0,3);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm starting to think this test and the one above can be combined into a single test, with both pick checks at the bottom.

it('picks a primitive with a modified pick search area', function() {
    if (FeatureDetection.isInternetExplorer()) {
        // Workaround IE 11.0.9.  This test fails when all tests are ran without a breakpoint here.
        return;
    }

    camera.setView({
        destination : Rectangle.fromDegrees(-10.0, -10.0, 10.0, 10.0)
    });

    var rectangle = createRectangle();

    expect(scene).toPickPrimitive(rectangle, 7, 7, 5);
    expect(scene).notToPick(7, 7, 3);
});

I changed the numbers for the notToPick test also to (7, 7) for consistency.

@jason-crow
Copy link
Contributor Author

Ok ready again, thanks for help

@lilleyse
Copy link
Contributor

I seemed to have accidentally closed this while trying to push some changes to your branch, but also reset your branch to what's on master in the process... I'm not sure why it let me merge master but not push the other commits I had.

The code is safely on the pick-size branch. Could you merge that branch into your master branch and then push? I can't seem to do that, I'm getting permission denied errors.

Sorry for the hassle.

@jason-crow
Copy link
Contributor Author

ok i think ive merged everything now.

@lilleyse lilleyse reopened this Jul 13, 2017
@lilleyse
Copy link
Contributor

Thanks @jason-crow, all good now!

@lilleyse lilleyse merged commit 7498a24 into CesiumGS:master Jul 13, 2017
@jason-crow
Copy link
Contributor Author

Great! Thanks for your help in getting this merged!

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.

3 participants