diff --git a/src/mol-data/int/impl/sorted-array.ts b/src/mol-data/int/impl/sorted-array.ts index 8c81e7940adde281f8950fdd78c71bbbb233cee0..839c20292c85dc576847c857a19c9ee474e22269 100644 --- a/src/mol-data/int/impl/sorted-array.ts +++ b/src/mol-data/int/impl/sorted-array.ts @@ -47,8 +47,10 @@ export function indexOf(xs: Nums, v: number) { return l === 0 ? -1 : xs[0] <= v && v <= xs[l - 1] ? binarySearchRange(xs, v, 0, l) : -1; } export function indexOfInInterval(xs: Nums, v: number, bounds: Interval) { + return indexOfInRange(xs, v, Interval.start(bounds), Interval.end(bounds)) +} +export function indexOfInRange(xs: Nums, v: number, s: number, e: number) { const l = xs.length; - const s = Interval.start(bounds), e = Interval.end(bounds); return l === 0 || e <= s ? -1 : xs[s] <= v && v <= xs[e - 1] ? binarySearchRange(xs, v, s, e) : -1; } export function has(xs: Nums, v: number) { return indexOf(xs, v) >= 0; } diff --git a/src/mol-data/int/sorted-array.ts b/src/mol-data/int/sorted-array.ts index 8858aed3d910954cb293796d4dac557f445d9f84..1f33a78370419fa6978d2485a48a6f6d7fc4bbde 100644 --- a/src/mol-data/int/sorted-array.ts +++ b/src/mol-data/int/sorted-array.ts @@ -22,6 +22,7 @@ namespace SortedArray { /** Returns the index of `x` in `set` or -1 if not found. */ export const indexOf: <T extends number = number>(array: SortedArray<T>, x: T) => number = Impl.indexOf as any; export const indexOfInInterval: <T extends number = number>(array: SortedArray<T>, x: number, bounds: Interval) => number = Impl.indexOfInInterval as any; + export const indexOfInRange: <T extends number = number>(array: SortedArray<T>, x: number, start: number, end: number) => number = Impl.indexOfInRange as any; /** Returns `array[0]` */ export const start: <T extends number = number>(array: SortedArray<T>) => T = Impl.start as any; diff --git a/src/mol-model/structure/structure/element.ts b/src/mol-model/structure/structure/element.ts index a7036691c294ae6c34c98523b5d6a9adb2cf2ed2..c6dd8c365b271077be8f1f35855b7478541f0a6d 100644 --- a/src/mol-model/structure/structure/element.ts +++ b/src/mol-model/structure/structure/element.ts @@ -137,23 +137,33 @@ namespace StructureElement { const elements: Loci['elements'][0][] = []; loci.elements.forEach(e => { + if (!structure.unitMap.has(e.unit.id)) return const unit = structure.unitMap.get(e.unit.id) - if (!unit) return if (SortedArray.areEqual(e.unit.elements, unit.elements)) { elements.push({ unit, indices: e.indices }) } else { - // TODO optimize - const indices: UnitIndex[] = [] - OrderedSet.forEach(e.indices, (v) => { + const _indices: UnitIndex[] = [] + const end = unit.elements.length + let start = 0 + for (let i = 0; i < OrderedSet.size(e.indices); ++i) { + const v = OrderedSet.getAt(e.indices, i) const eI = e.unit.elements[v] - const uI = SortedArray.indexOf(unit.elements, eI) as UnitIndex | -1 - if (uI !== -1) indices.push(uI) - }) - elements.push({ - unit, - indices: SortedArray.ofSortedArray(indices) - }) + const uI = SortedArray.indexOfInRange(unit.elements, eI, start, end) as UnitIndex | -1 + if (uI !== -1) { + _indices.push(uI) + start = uI + } + } + + let indices: OrderedSet<UnitIndex> + if (_indices.length > 12 && _indices[_indices.length - 1] - _indices[0] === _indices.length - 1) { + indices = Interval.ofRange(_indices[0], _indices[_indices.length - 1]) + } else { + indices = SortedArray.ofSortedArray(_indices) + } + + elements.push({ unit, indices }) } });