Merge pull request #124 from mayorovad/issue-96

development
Thomas Bouffard 2022-10-09 22:32:39 +02:00 committed by GitHub
commit 4622527af8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 128 additions and 88 deletions

View File

@ -70,9 +70,6 @@ For more details, have a look at the [storybook stories](packages/html/stories).
maxGraph is written in TypeScript and provides type definitions so maxGraph can be easily integrated into TypeScript projects.
**WARN**: some definitions are currently buggy, so please set `skipLibCheck` to `true` in the `tsconfig.json` file of your project.
For more details, see issues [#96](https://github.com/maxGraph/maxGraph/issues/96) and [#105](https://github.com/maxGraph/maxGraph/issues/105#issuecomment-1240640369).
## Support

View File

@ -22,6 +22,7 @@ import Geometry from '../geometry/Geometry';
import Point from '../geometry/Point';
import { Graph } from '../Graph';
import Cell from '../cell/Cell';
import { GraphLayoutTraverseArgs } from './types';
/**
* @class GraphLayout
@ -141,13 +142,7 @@ class GraphLayout {
* null for the first step of the traversal.
* @param visited Optional {@link Dictionary} of cell paths for the visited cells.
*/
traverse(
vertex: Cell,
directed?: boolean,
func?: Function,
edge?: Cell,
visited?: Dictionary<Cell, boolean>
): void {
traverse({vertex, directed, func, edge, visited}: GraphLayoutTraverseArgs): void {
if (func != null && vertex != null) {
directed = directed != null ? directed : true;
visited = visited || new Dictionary();
@ -161,12 +156,18 @@ class GraphLayout {
if (edgeCount > 0) {
for (let i = 0; i < edgeCount; i += 1) {
const e = vertex.getEdgeAt(i);
const e: Cell = vertex.getEdgeAt(i);
const isSource = e.getTerminal(true) === vertex;
if (!directed || isSource) {
const next = this.graph.view.getVisibleTerminal(e, !isSource);
this.traverse(<Cell>next, directed, func, e, visited);
this.traverse({
vertex: next,
directed,
func,
edge: e,
visited
});
}
}
}

View File

@ -27,7 +27,7 @@ import MedianHybridCrossingReduction from './hierarchical/MedianHybridCrossingRe
import CoordinateAssignment from './hierarchical/CoordinateAssignment';
import { Graph } from '../../view/Graph';
import Cell from '../../view/cell/Cell';
import GraphHierarchyNode from './datatypes/GraphHierarchyNode';
import { HierarchicalGraphLayoutTraverseArgs } from './types';
/**
* A hierarchical layout algorithm.
@ -444,15 +444,17 @@ class HierarchicalLayout extends GraphLayout {
const vertexSet = Object();
hierarchyVertices.push(vertexSet);
this.traverse(
candidateRoots[i],
true,
null,
allVertexSet,
vertexSet,
hierarchyVertices,
filledVertexSet
);
this.traverse({
vertex: candidateRoots[i],
directed: true,
edge: null,
allVertices: allVertexSet,
currentComp: vertexSet,
hierarchyVertices: hierarchyVertices,
filledVertexSet: filledVertexSet,
func: null,
visited: null
});
}
for (let i = 0; i < candidateRoots.length; i += 1) {
@ -477,15 +479,17 @@ class HierarchicalLayout extends GraphLayout {
const vertexSet = Object();
hierarchyVertices.push(vertexSet);
this.traverse(
roots[i],
true,
null,
allVertexSet,
vertexSet,
hierarchyVertices,
null
);
this.traverse({
vertex: roots[i],
directed: true,
edge: null,
allVertices: allVertexSet,
currentComp: vertexSet,
hierarchyVertices: hierarchyVertices,
filledVertexSet: null,
func: null,
visited: null
});
}
}
@ -600,16 +604,14 @@ class HierarchicalLayout extends GraphLayout {
* null for the first step of the traversal.
* @param allVertices Array of cell paths for the visited cells.
*/
// @ts-ignore
traverse(
vertex: Cell,
directed: boolean = false,
edge: Cell | null = null,
allVertices: { [key: string]: Cell } | null = null,
currentComp: { [key: string]: Cell | null },
hierarchyVertices: GraphHierarchyNode[],
filledVertexSet: { [key: string]: Cell } | null = null
) {
traverse({
vertex,
directed,
allVertices,
currentComp,
hierarchyVertices,
filledVertexSet
}: HierarchicalGraphLayoutTraverseArgs) {
if (vertex != null && allVertices != null) {
// Has this vertex been seen before in any traversal
// And if the filled vertex set is populated, only
@ -666,15 +668,17 @@ class HierarchicalLayout extends GraphLayout {
}
if (netCount >= 0) {
currentComp = this.traverse(
<Cell>next,
currentComp = this.traverse({
vertex: next,
directed,
edges[i],
edge: edges[i],
allVertices,
currentComp,
hierarchyVertices,
filledVertexSet
);
filledVertexSet,
func: null,
visited: null
});
}
}
}

View File

@ -29,7 +29,7 @@ import CoordinateAssignment from './hierarchical/CoordinateAssignment';
import { Graph } from '../Graph';
import Cell from '../cell/Cell';
import Geometry from '../../view/geometry/Geometry';
import GraphHierarchyNode from './datatypes/GraphHierarchyNode';
import { SwimlaneGraphLayoutTraverseArgs } from './types';
/**
* A hierarchical layout algorithm.
@ -579,16 +579,18 @@ class SwimlaneLayout extends GraphLayout {
const vertexSet = Object();
hierarchyVertices.push(vertexSet);
this.traverse(
candidateRoots[i],
true,
null,
allVertexSet,
vertexSet,
this.traverse({
vertex: candidateRoots[i],
directed: true,
edge: null,
allVertices: allVertexSet,
currentComp: vertexSet,
hierarchyVertices,
filledVertexSet,
laneCounter
);
swimlaneIndex: laneCounter,
func: null,
visited: null
});
}
for (let i = 0; i < candidateRoots.length; i += 1) {
@ -612,16 +614,18 @@ class SwimlaneLayout extends GraphLayout {
for (let i = 0; i < roots.length; i += 1) {
const vertexSet = Object();
hierarchyVertices.push(vertexSet);
this.traverse(
roots[i],
true,
null,
allVertexSet,
vertexSet,
this.traverse({
vertex: roots[i],
directed: true,
edge: null,
allVertices: allVertexSet,
currentComp: vertexSet,
hierarchyVertices,
null,
i
); // CHECK THIS PARAM!! ====================
filledVertexSet: null,
swimlaneIndex: i,
func: null,
visited: null
}); // CHECK THIS PARAM!! ====================
}
}
@ -731,17 +735,15 @@ class SwimlaneLayout extends GraphLayout {
* @param allVertices Array of cell paths for the visited cells.
* @param swimlaneIndex the laid out order index of the swimlane vertex is contained in
*/
// @ts-ignore
traverse(
vertex: Cell | null = null,
directed: boolean,
edge: Cell | null,
allVertices: { [key: string]: Cell } | null = null,
currentComp: { [key: string]: Cell },
hierarchyVertices: GraphHierarchyNode[],
filledVertexSet: { [key: string]: Cell } | null = null,
swimlaneIndex: number
) {
traverse({
vertex,
directed,
allVertices,
currentComp,
hierarchyVertices,
filledVertexSet,
swimlaneIndex
}: SwimlaneGraphLayoutTraverseArgs) {
if (vertex != null && allVertices != null) {
// Has this vertex been seen before in any traversal
// And if the filled vertex set is populated, only
@ -764,7 +766,6 @@ class SwimlaneLayout extends GraphLayout {
}
const edges = this.getEdges(vertex);
const { model } = this.graph;
for (let i = 0; i < edges.length; i += 1) {
let otherVertex = this.getVisibleTerminal(edges[i], true);
@ -775,16 +776,15 @@ class SwimlaneLayout extends GraphLayout {
}
let otherIndex = 0;
const swimlanes = this.swimlanes as Cell[];
// Get the swimlane index of the other terminal
for (otherIndex = 0; otherIndex < swimlanes.length; otherIndex++) {
if (swimlanes[otherIndex].isAncestor(otherVertex)) {
for (otherIndex = 0; otherIndex < this.swimlanes!.length; otherIndex++) {
if (this.swimlanes![otherIndex].isAncestor(otherVertex)) {
break;
}
}
if (otherIndex >= swimlanes.length) {
if (otherIndex >= this.swimlanes!.length) {
continue;
}
@ -795,16 +795,18 @@ class SwimlaneLayout extends GraphLayout {
otherIndex > swimlaneIndex ||
((!directed || isSource) && otherIndex === swimlaneIndex)
) {
currentComp = this.traverse(
<Cell>otherVertex,
currentComp = this.traverse({
vertex: otherVertex,
directed,
edges[i],
edge: edges[i],
allVertices,
currentComp,
hierarchyVertices,
filledVertexSet,
otherIndex
);
swimlaneIndex: otherIndex,
func: null,
visited: null
});
}
}
} else if (currentComp[vertexID] == null) {

View File

@ -0,0 +1,38 @@
/*
Copyright 2022-present The maxGraph project Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import type Cell from '../cell/Cell';
import type Dictionary from '../../util/Dictionary';
import type GraphHierarchyNode from './datatypes/GraphHierarchyNode';
export interface GraphLayoutTraverseArgs {
vertex: Cell | null;
directed: boolean | null;
func: Function | null;
edge: Cell | null;
visited: Dictionary<Cell, boolean> | null;
}
export interface HierarchicalGraphLayoutTraverseArgs extends GraphLayoutTraverseArgs {
allVertices: { [key: string]: Cell } | null;
currentComp: { [key: string]: Cell | null };
hierarchyVertices: GraphHierarchyNode[];
filledVertexSet: { [key: string]: Cell } | null;
}
export interface SwimlaneGraphLayoutTraverseArgs extends HierarchicalGraphLayoutTraverseArgs {
swimlaneIndex: number;
}

View File

@ -13,9 +13,7 @@
"noEmit": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
// TODO required because some type definitions in the @maxgraph/core package generate errors: https://github.com/maxGraph/maxGraph/issues/96
"skipLibCheck": true
"noImplicitReturns": true
},
"include": ["src"]
}