/**
* Created by Alex Bol on 3/12/2017.
*/
"use strict";
import Flatten from '../flatten';
import IntervalTree from '@flatten-js/interval-tree';
/**
* Class representing a planar set - a generic container with ability to keep and retrieve shapes and
* perform spatial queries. Planar set is an extension of Set container, so it supports
* Set properties and methods
*/
export class PlanarSet extends Set {
/**
* Create new instance of PlanarSet
* @param shapes - array or set of geometric objects to store in planar set
* Each object should have a <b>box</b> property
*/
constructor(shapes) {
super(shapes);
this.index = new IntervalTree();
this.forEach(shape => this.index.insert(shape))
}
/**
* Add new shape to planar set and to its spatial index.<br/>
* If shape already exist, it will not be added again.
* This happens with no error, it is possible to use <i>size</i> property to check if
* a shape was actually added.<br/>
* Method returns planar set object updated and may be chained
* @param {AnyShape | {Box, AnyShape}} entry - shape to be added, should have valid <i>box</i> property
* Another option to transfer as an object {key: Box, value: AnyShape}
* @returns {PlanarSet}
*/
add(entry) {
let size = this.size;
const {key, value} = entry
const box = key || entry.box
const shape = value || entry
super.add(shape);
// size not changed - item not added, probably trying to add same item twice
if (this.size > size) {
let node = this.index.insert(box, shape);
}
return this; // in accordance to Set.add interface
}
/**
* Delete shape from planar set. Returns true if shape was actually deleted, false otherwise
* @param {AnyShape | {Box, AnyShape}} entry - shape to be deleted
* @returns {boolean}
*/
delete(entry) {
const {key, value} = entry
const box = key || entry.box
const shape = value || entry
let deleted = super.delete(shape);
if (deleted) {
this.index.remove(box, shape);
}
return deleted;
}
/**
* Clear planar set
*/
clear() {
super.clear();
this.index = new IntervalTree();
}
/**
* 2d range search in planar set.<br/>
* Returns array of all shapes in planar set which bounding box is intersected with query box
* @param {Box} box - query box
* @returns {AnyShape[]}
*/
search(box) {
let resp = this.index.search(box);
return resp;
}
/**
* Point location test. Returns array of shapes which contains given point
* @param {Point} point - query point
* @returns {AnyShape[]}
*/
hit(point) {
let box = new Flatten.Box(point.x - 1, point.y - 1, point.x + 1, point.y + 1);
let resp = this.index.search(box);
return resp.filter((shape) => point.on(shape));
}
/**
* Returns svg string to draw all shapes in planar set
* @returns {String}
*/
svg() {
let svgcontent = [...this].reduce((acc, shape) => acc + shape.svg(), "");
return svgcontent;
}
}
Flatten.PlanarSet = PlanarSet;