Merged PR 212: Optimize FindChildrenById from O(n) to O(1)
Optimize FindChildrenById from O(n) to O(1): - Deprecate FindContainerByIdDFS - Container: Replace Children to string[] - Add HashMap to IHistoryState that contains all containers To access a container by id now cost O(1) without any additional cost + Implement CICD for SVGLibs
This commit is contained in:
parent
466ef2b08b
commit
c256a76e01
45 changed files with 775 additions and 450 deletions
|
@ -4,8 +4,10 @@ import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
|||
import { IContainerProperties } from '../../../Interfaces/IContainerProperties';
|
||||
import { Camelize } from '../../../utils/stringtools';
|
||||
import { SHOW_TEXT } from '../../../utils/default';
|
||||
import { FindContainerById } from '../../../utils/itertools';
|
||||
|
||||
interface IContainerProps {
|
||||
containers: Map<string, IContainerModel>
|
||||
model: IContainerModel
|
||||
depth: number
|
||||
scale: number
|
||||
|
@ -18,13 +20,22 @@ interface IContainerProps {
|
|||
*/
|
||||
export function Container(props: IContainerProps): JSX.Element {
|
||||
const containersElements = props.model.children.map(
|
||||
child => <Container
|
||||
key={`container-${child.properties.id}`}
|
||||
model={child}
|
||||
depth={props.depth + 1}
|
||||
scale={props.scale}
|
||||
selectContainer={props.selectContainer}
|
||||
/>);
|
||||
childId => {
|
||||
const child = FindContainerById(props.containers, childId);
|
||||
|
||||
if (child === undefined) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return <Container
|
||||
key={`container-${child.properties.id}`}
|
||||
containers={props.containers}
|
||||
model={child}
|
||||
depth={props.depth + 1}
|
||||
scale={props.scale}
|
||||
selectContainer={props.selectContainer}
|
||||
/>;
|
||||
});
|
||||
|
||||
const width: number = props.model.properties.width;
|
||||
const height: number = props.model.properties.height;
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
import * as React from 'react';
|
||||
import { ContainerModel } from '../../../Interfaces/IContainerModel';
|
||||
import { ContainerModel, IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||
import { DIMENSION_MARGIN } from '../../../utils/default';
|
||||
import { GetAbsolutePosition, MakeBFSIterator } from '../../../utils/itertools';
|
||||
import { TransformX } from '../../../utils/svg';
|
||||
import { Dimension } from './Dimension';
|
||||
|
||||
interface IDimensionLayerProps {
|
||||
containers: Map<string, IContainerModel>
|
||||
roots: ContainerModel | ContainerModel[] | null
|
||||
scale?: number
|
||||
}
|
||||
|
||||
function GetDimensionsNodes(root: ContainerModel, scale: number): React.ReactNode[] {
|
||||
const it = MakeBFSIterator(root);
|
||||
function GetDimensionsNodes(
|
||||
containers: Map<string, IContainerModel>,
|
||||
root: ContainerModel,
|
||||
scale: number
|
||||
): React.ReactNode[] {
|
||||
const it = MakeBFSIterator(root, containers);
|
||||
const dimensions: React.ReactNode[] = [];
|
||||
let currentDepth = 0;
|
||||
let min = Infinity;
|
||||
|
@ -53,10 +58,10 @@ export function DepthDimensionLayer(props: IDimensionLayerProps): JSX.Element {
|
|||
const scale = props.scale ?? 1;
|
||||
if (Array.isArray(props.roots)) {
|
||||
props.roots.forEach(child => {
|
||||
dimensions.concat(GetDimensionsNodes(child, scale));
|
||||
dimensions.concat(GetDimensionsNodes(props.containers, child, scale));
|
||||
});
|
||||
} else if (props.roots !== null) {
|
||||
dimensions = GetDimensionsNodes(props.roots, scale);
|
||||
dimensions = GetDimensionsNodes(props.containers, props.roots, scale);
|
||||
}
|
||||
return (
|
||||
<g>
|
||||
|
|
|
@ -3,11 +3,12 @@ import { Orientation } from '../../../Enums/Orientation';
|
|||
import { Position } from '../../../Enums/Position';
|
||||
import { ContainerModel, IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||
import { DIMENSION_MARGIN, SHOW_BORROWER_DIMENSIONS, SHOW_CHILDREN_DIMENSIONS, SHOW_SELF_DIMENSIONS } from '../../../utils/default';
|
||||
import { MakeRecursionDFSIterator, Pairwise } from '../../../utils/itertools';
|
||||
import { FindContainerById, MakeRecursionDFSIterator, Pairwise } from '../../../utils/itertools';
|
||||
import { TransformX, TransformY } from '../../../utils/svg';
|
||||
import { Dimension } from './Dimension';
|
||||
|
||||
interface IDimensionLayerProps {
|
||||
containers: Map<string, IContainerModel>
|
||||
root: ContainerModel
|
||||
scale: number
|
||||
}
|
||||
|
@ -51,8 +52,8 @@ function ActionByPosition(
|
|||
* @param param0 Object with the root container and the scale of the svg
|
||||
* @returns A list of dimensions
|
||||
*/
|
||||
function Dimensions({ root, scale }: IDimensionLayerProps): React.ReactNode[] {
|
||||
const it = MakeRecursionDFSIterator(root, 0, [0, 0]);
|
||||
function Dimensions({ containers, root, scale }: IDimensionLayerProps): React.ReactNode[] {
|
||||
const it = MakeRecursionDFSIterator(root, containers, 0, [0, 0]);
|
||||
const dimensions: React.ReactNode[] = [];
|
||||
const topDim = root.properties.y;
|
||||
const leftDim = root.properties.x;
|
||||
|
@ -75,7 +76,8 @@ function Dimensions({ root, scale }: IDimensionLayerProps): React.ReactNode[] {
|
|||
container.properties.showSelfDimensions,
|
||||
AddHorizontalSelfDimension,
|
||||
AddVerticalSelfDimension,
|
||||
[container,
|
||||
[
|
||||
container,
|
||||
currentTransform,
|
||||
dimensions,
|
||||
scale]
|
||||
|
@ -88,7 +90,9 @@ function Dimensions({ root, scale }: IDimensionLayerProps): React.ReactNode[] {
|
|||
container.properties.showDimensionWithMarks,
|
||||
AddHorizontalBorrowerDimension,
|
||||
AddVerticalBorrowerDimension,
|
||||
[container,
|
||||
[
|
||||
containers,
|
||||
container,
|
||||
depth,
|
||||
currentTransform,
|
||||
dimensions,
|
||||
|
@ -102,7 +106,9 @@ function Dimensions({ root, scale }: IDimensionLayerProps): React.ReactNode[] {
|
|||
container.properties.showChildrenDimensions,
|
||||
AddHorizontalChildrenDimension,
|
||||
AddVerticalChildrenDimension,
|
||||
[container,
|
||||
[
|
||||
containers,
|
||||
container,
|
||||
currentTransform,
|
||||
dimensions,
|
||||
scale]
|
||||
|
@ -130,6 +136,7 @@ export function DimensionLayer(props: IDimensionLayerProps): JSX.Element {
|
|||
|
||||
function AddHorizontalChildrenDimension(
|
||||
yDim: number,
|
||||
containers: Map<string, IContainerModel>,
|
||||
container: IContainerModel,
|
||||
currentTransform: [number, number],
|
||||
dimensions: React.ReactNode[],
|
||||
|
@ -137,13 +144,25 @@ function AddHorizontalChildrenDimension(
|
|||
): void {
|
||||
const childrenId = `dim-y${yDim.toFixed(0)}-children-${container.properties.id}`;
|
||||
|
||||
const lastChild = container.children[container.children.length - 1];
|
||||
const lastChildId = container.children[container.children.length - 1];
|
||||
const lastChild = FindContainerById(containers, lastChildId);
|
||||
|
||||
if (lastChild === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
let xChildrenStart = TransformX(lastChild.properties.x, lastChild.properties.width, lastChild.properties.positionReference);
|
||||
let xChildrenEnd = TransformX(lastChild.properties.x, lastChild.properties.width, lastChild.properties.positionReference);
|
||||
|
||||
// Find the min and max
|
||||
for (let i = container.children.length - 2; i >= 0; i--) {
|
||||
const child = container.children[i];
|
||||
const childId = container.children[i];
|
||||
const child = FindContainerById(containers, childId);
|
||||
|
||||
if (child === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const left = TransformX(child.properties.x, child.properties.width, child.properties.positionReference);
|
||||
if (left < xChildrenStart) {
|
||||
xChildrenStart = left;
|
||||
|
@ -178,6 +197,7 @@ function AddHorizontalChildrenDimension(
|
|||
|
||||
function AddVerticalChildrenDimension(
|
||||
xDim: number,
|
||||
containers: Map<string, IContainerModel>,
|
||||
container: IContainerModel,
|
||||
currentTransform: [number, number],
|
||||
dimensions: React.ReactNode[],
|
||||
|
@ -185,13 +205,25 @@ function AddVerticalChildrenDimension(
|
|||
): void {
|
||||
const childrenId = `dim-x${xDim.toFixed(0)}-children-${container.properties.id}`;
|
||||
|
||||
const lastChild = container.children[container.children.length - 1];
|
||||
const lastChildId = container.children[container.children.length - 1];
|
||||
const lastChild = FindContainerById(containers, lastChildId);
|
||||
|
||||
if (lastChild === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
let yChildrenStart = TransformY(lastChild.properties.y, lastChild.properties.height, lastChild.properties.positionReference);
|
||||
let yChildrenEnd = TransformY(lastChild.properties.y, lastChild.properties.height, lastChild.properties.positionReference);
|
||||
|
||||
// Find the min and max
|
||||
for (let i = container.children.length - 2; i >= 0; i--) {
|
||||
const child = container.children[i];
|
||||
const childId = container.children[i];
|
||||
const child = FindContainerById(containers, childId);
|
||||
|
||||
if (child === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const top = TransformY(child.properties.y, child.properties.height, child.properties.positionReference);
|
||||
if (top < yChildrenStart) {
|
||||
yChildrenStart = top;
|
||||
|
@ -227,13 +259,14 @@ function AddVerticalChildrenDimension(
|
|||
|
||||
function AddHorizontalBorrowerDimension(
|
||||
yDim: number,
|
||||
containers: Map<string, IContainerModel>,
|
||||
container: IContainerModel,
|
||||
depth: number,
|
||||
currentTransform: [number, number],
|
||||
dimensions: React.ReactNode[],
|
||||
scale: number
|
||||
): void {
|
||||
const it = MakeRecursionDFSIterator(container, depth, currentTransform);
|
||||
const it = MakeRecursionDFSIterator(container, containers, depth, currentTransform);
|
||||
const marks = []; // list of vertical lines for the dimension
|
||||
for (const {
|
||||
container: childContainer, currentTransform: childCurrentTransform
|
||||
|
@ -279,13 +312,14 @@ function AddHorizontalBorrowerDimension(
|
|||
|
||||
function AddVerticalBorrowerDimension(
|
||||
xDim: number,
|
||||
containers: Map<string, IContainerModel>,
|
||||
container: IContainerModel,
|
||||
depth: number,
|
||||
currentTransform: [number, number],
|
||||
dimensions: React.ReactNode[],
|
||||
scale: number
|
||||
): void {
|
||||
const it = MakeRecursionDFSIterator(container, depth, currentTransform);
|
||||
const it = MakeRecursionDFSIterator(container, containers, depth, currentTransform);
|
||||
const marks = []; // list of vertical lines for the dimension
|
||||
for (const {
|
||||
container: childContainer, currentTransform: childCurrentTransform
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react';
|
||||
import { ReactSVGPanZoom, Tool, TOOL_PAN, Value } from 'react-svg-pan-zoom';
|
||||
import { Container } from './Elements/Container';
|
||||
import { ContainerModel } from '../../Interfaces/IContainerModel';
|
||||
import { ContainerModel, IContainerModel } from '../../Interfaces/IContainerModel';
|
||||
import { Selector } from './Elements/Selector/Selector';
|
||||
import { DepthDimensionLayer } from './Elements/DepthDimensionLayer';
|
||||
import { MAX_FRAMERATE, SHOW_DIMENSIONS_PER_DEPTH } from '../../utils/default';
|
||||
|
@ -15,17 +15,13 @@ interface ISVGProps {
|
|||
viewerHeight: number
|
||||
width: number
|
||||
height: number
|
||||
containers: Map<string, IContainerModel>
|
||||
children: ContainerModel
|
||||
selected?: ContainerModel
|
||||
symbols: Map<string, ISymbolModel>
|
||||
selectContainer: (containerId: string) => void
|
||||
}
|
||||
|
||||
interface Viewer {
|
||||
viewerWidth: number
|
||||
viewerHeight: number
|
||||
}
|
||||
|
||||
export const ID = 'svg';
|
||||
|
||||
export function SVG(props: ISVGProps): JSX.Element {
|
||||
|
@ -55,6 +51,7 @@ export function SVG(props: ISVGProps): JSX.Element {
|
|||
let children: React.ReactNode | React.ReactNode[] = [];
|
||||
children = <Container
|
||||
key={`container-${props.children.properties.id}`}
|
||||
containers={props.containers}
|
||||
model={props.children}
|
||||
depth={0}
|
||||
scale={scale}
|
||||
|
@ -97,9 +94,9 @@ export function SVG(props: ISVGProps): JSX.Element {
|
|||
<svg {...properties}>
|
||||
{children}
|
||||
{SHOW_DIMENSIONS_PER_DEPTH
|
||||
? <DepthDimensionLayer scale={scale} roots={props.children} />
|
||||
? <DepthDimensionLayer containers={props.containers} scale={scale} roots={props.children} />
|
||||
: null}
|
||||
<DimensionLayer scale={scale} root={props.children} />
|
||||
<DimensionLayer containers={props.containers} scale={scale} root={props.children} />
|
||||
<SymbolLayer scale={scale} symbols={props.symbols} />
|
||||
<Selector scale={scale} selected={props.selected} /> {/* leave this at the end so it can be removed during the svg export */}
|
||||
</svg>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue