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

Fast entity bounds queries #3403

Merged
merged 6 commits into from
Sep 12, 2017
Merged

Conversation

themadcreator
Copy link
Contributor

@themadcreator themadcreator commented Sep 7, 2017

  • Add R-Tree and supporting unit tests.
  • Use rtree to efficiently test bounds for entity overlap.
  • Add API methods for entitiesInBounds and as well as x- and y- only versions.
  • Switch to using more standard IEntityBounds.
  • Add more tests.
  • Add proper bounds for scatter plot and rect plot entities.
  • Fix r-tree split strategy balancing and verify with test.
  • Comments.

Switch to using more standard `IEntityBounds`.
Add more tests.
Add proper bounds for scatter plot and rect plot entities.
Fix r-tree split strategy balancing and verify with test.
Comments.
@blueprint-bot
Copy link

Verify entitiesInBounds

Demo: quicktests | fiddle

@blueprint-bot
Copy link

Better naming for entitiesIn methods

Demo: quicktests | fiddle

Copy link
Contributor

@hellochar hellochar left a comment

Choose a reason for hiding this comment

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

Nothing blocking, nice rtree impl :)

nit: a quicktest for this would be nice!

* Returns the entites whose bounding boxes overlap the parameter on the
* x-axis.
*/
public entitiesInXRange(queryBounds: IEntityBounds): Plots.IPlotEntity[] {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd prefer not to have separate range/xRange/yRange endpoints. We can do XRange by passing in Infinity for the y/height on the generic Bounds object. Maybe it'd make more sense for Bounds to be two Range objects

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nah, that'd just add another semantically equiv interface.

I think different endpoints is really helpful. It allows the user of the API to know that it'll "do what it says on the tin" as opposed to having to think about how the same method will re-interpret their arguments at runtime.

/**
* Returns the entites whose bounding boxes overlap the parameter.
*/
public entitiesInBounds(queryBounds: IEntityBounds): Plots.IPlotEntity[] {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: to be clear - this ignores the y/height properties on IEntityBounds? This API feels inconsistent with the existing entitiesIn(xRangeOrBounds: Range | Bounds, yRange?: Range): IPlotEntity[] { that bar, scatter, line, and rectangle have.

I think part of the issue is that we have overlapping responsibilities in our interfaces:

export type Range = {
  min: number;
  max: number;
};

/**
 * A location in pixel-space.
 */
export type Point = {
  x: number;
  y: number;
};

/**
 * The corners of a box.
 */
export type Bounds = {
  topLeft: Point;
  bottomRight: Point;
};

/**
 * Client bounds
 */
export interface IEntityBounds {
  x: number;
  y: number;
  width: number;
  height: number;
}

An IEntityBounds and a Bounds are semantically equivalent to each other, as well as equivalent to two Ranges.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

very true. i'm not sure why the original bounds was structured as two points, but i've always found it awkward.

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'll take a look at replacing the existing entitiesIn methods to defer to the relevant entitystore method


constructor() {
this._entities = [];
this._rtree = new RTree<T>();
this._tree = d3.quadtree<T>()
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: we can probably implement "nearest entity to point" with the rtree and get rid of the quadtree completely

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 not exactly the same. the quadtree structure allows us to guarantee that no other point is closer based on the bounding box of the tree node. r-trees don't make the same guarantees, but they are great for querying overlapping bounds!


/**
* R-Tree is a multidimensional spatial region tree. It stores entries that have
* arbitrarily overlapping bounding boxes and supports efficient point and
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: can we document runtime and space complexity to be more precise with what "efficient" means

@themadcreator
Copy link
Contributor Author

themadcreator commented Sep 12, 2017

Now that entitiesIn uses the entitystore methods, the dragbox quicktest should demonstrate this feature. this one

@blueprint-bot
Copy link

Add panzoom update callbacks

Demo: quicktests | fiddle

@themadcreator themadcreator merged commit 1ab5618 into develop Sep 12, 2017
@themadcreator themadcreator deleted the bd/fast-entity-bounds-queries branch September 12, 2017 20:12
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