临时文件

This commit is contained in:
dell
2025-02-19 16:05:53 +08:00
parent b915c54c63
commit 4071d8f337
46 changed files with 69286 additions and 0 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,705 @@
/**
* Copyright (c) 2019-2020, JGraph Ltd
*/
/**
* Class: mxOrgChartLayout
*
* Extends <mxGraphLayout> to implement organization chart layout algorithm.
* The vertices need to be connected for this layout to work, vertices
* with no connections are ignored.
*
* Example:
*
* (code)
* var layout = new mxOrgChartLayout(graph);
* layout.execute(graph.getDefaultParent());
* (end)
*
*/
function mxOrgChartLayout(graph, branchOptimizer, parentChildSpacing, siblingSpacing)
{
mxGraphLayout.call(this, graph);
this.correctY = false;
switch(parseInt(branchOptimizer))
{
case 0:
this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_LINEAR;
this.correctY = true;
break;
case 1:
this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_HANGER2;
this.correctY = true;
break;
case 3:
this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_FISHBONE1;
break;
case 4:
this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_FISHBONE2;
break;
case 5:
this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_1COLUMN_L;
break;
case 6:
this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_1COLUMN_R;
break;
case 7:
this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_SMART;
break;
default: //and case 2
this.branchOptimizer = mxOrgChartLayout.prototype.BRANCH_OPT_HANGER4;
this.correctY = true;
}
this.parentChildSpacing = parentChildSpacing > 0 ? parentChildSpacing : 20;
this.siblingSpacing = siblingSpacing > 0 ? siblingSpacing : 20;
};
/**
* Extends mxGraphLayout.
*/
mxOrgChartLayout.prototype = new mxGraphLayout();
mxOrgChartLayout.prototype.constructor = mxOrgChartLayout;
//Branch Optimizers
mxOrgChartLayout.prototype.BRANCH_OPT_LINEAR = 'branchOptimizerAllLinear';
mxOrgChartLayout.prototype.BRANCH_OPT_HANGER2 = 'branchOptimizerAllHanger2';
mxOrgChartLayout.prototype.BRANCH_OPT_HANGER4 = 'branchOptimizerAllHanger4';
mxOrgChartLayout.prototype.BRANCH_OPT_FISHBONE1 = 'branchOptimizerAllFishbone1';
mxOrgChartLayout.prototype.BRANCH_OPT_FISHBONE2 = 'branchOptimizerAllFishbone2';
mxOrgChartLayout.prototype.BRANCH_OPT_1COLUMN_L = 'branchOptimizerAllSingleColumnLeft';
mxOrgChartLayout.prototype.BRANCH_OPT_1COLUMN_R = 'branchOptimizerAllSingleColumnRight';
mxOrgChartLayout.prototype.BRANCH_OPT_SMART = 'branchOptimizerSmart';
/**
* Function: execute
*
* Implements <mxGraphLayout.execute>. This operates on all children of the
* given parent.
*/
mxOrgChartLayout.prototype.execute = function(parent)
{
this.graph.model.beginUpdate();
try
{
RPOrgChart.main(this.graph, parent, this.branchOptimizer, this.parentChildSpacing, this.siblingSpacing, this.correctY);
}
finally
{
this.graph.model.endUpdate();
}
}
Bridge.define('RPOrgChart',
{
statics: {
config: {
init: function() {
}
},
main: function (graph, parent, branchOptimizer, parentChildSpacing, siblingSpacing, correctY) {
Bridge.Console.log = console.log;
Bridge.Console.error = console.error;
Bridge.Console.debug = console.debug;
RPOrgChart.graph = graph;
RPOrgChart.parent = parent;
RPOrgChart.dx = 0;
RPOrgChart.dy = 0;
if (parent.style == 'group' && parent.geometry)
{
RPOrgChart.dx = parent.geometry.x;
RPOrgChart.dy = parent.geometry.y;
}
RPOrgChart.branchOptimizer = branchOptimizer;
RPOrgChart.correctY = correctY;
RPOrgChart.parentChildSpacing = parseInt(parentChildSpacing);
RPOrgChart.siblingSpacing = parseInt(siblingSpacing);
RPOrgChart.buildChart(true);
},
diagram: {},
dataSource: {},
buildChart: function (initData) {
if (initData) {
RPOrgChart.initDiagram();
}
RPOrgChart.positionBoxes();
},
collapseAllBoxes: function(boxContainer, isCollapsed) {
var en = boxContainer.getBoxesById().getValues().getEnumerator();
while (en.moveNext()) {
var box = en.getCurrent();
if (!box.IsSpecial) {
box.IsCollapsed = isCollapsed;
}
}
},
generateData: function ()
{
var dataSource = new OrgChart.Test.TestDataSource();
var graph = RPOrgChart.graph;
var cells = graph.getChildVertices(RPOrgChart.parent);
for (var i = 0; i < cells.length; i++)
{
var cell = cells[i];
if (cell.geometry != null && cell.vertex && cell.parent == RPOrgChart.parent) //Vertices and first level children only
{
// Find cell parent. If it has more than one parent, take first parent (should be an error?)
var parentId = null;
var incomingEdge = graph.getIncomingEdges(cell)[0];
if (incomingEdge != null && incomingEdge.source != null)
{
parentId = incomingEdge.source.id;
}
var item = new OrgChart.Test.TestDataItem();
item.Id = cell.id;
item.ParentId = parentId;
dataSource.Items.add(item.getId(), item);
}
}
return dataSource;
},
initDiagram: function () {
var dataSource = RPOrgChart.generateData();
RPOrgChart.dataSource = dataSource;
var boxContainer = new OrgChart.Layout.BoxContainer.$ctor1(dataSource);
RPOrgChart.diagram = new OrgChart.Layout.Diagram();
var diagram = RPOrgChart.diagram;
diagram.setBoxes(boxContainer);
var linearLayoutStrategy = new OrgChart.Layout.LinearLayoutStrategy();
linearLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
linearLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
linearLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("linear", linearLayoutStrategy);
var multiLineHangerLayoutStrategy = new OrgChart.Layout.MultiLineHangerLayoutStrategy();
multiLineHangerLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
multiLineHangerLayoutStrategy.MaxSiblingsPerRow = 2;
multiLineHangerLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
multiLineHangerLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("hanger2", multiLineHangerLayoutStrategy);
multiLineHangerLayoutStrategy = new OrgChart.Layout.MultiLineHangerLayoutStrategy();
multiLineHangerLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
multiLineHangerLayoutStrategy.MaxSiblingsPerRow = 4;
multiLineHangerLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
multiLineHangerLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("hanger4", multiLineHangerLayoutStrategy);
var singleColumnLayoutStrategy = new OrgChart.Layout.SingleColumnLayoutStrategy();
singleColumnLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Right;
singleColumnLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
singleColumnLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("singleColumnRight", singleColumnLayoutStrategy);
singleColumnLayoutStrategy = new OrgChart.Layout.SingleColumnLayoutStrategy();
singleColumnLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Left;
singleColumnLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
singleColumnLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("singleColumnLeft", singleColumnLayoutStrategy);
var fishboneLayoutStrategy = new OrgChart.Layout.MultiLineFishboneLayoutStrategy();
fishboneLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
fishboneLayoutStrategy.MaxGroups = 1;
fishboneLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
fishboneLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("fishbone1", fishboneLayoutStrategy);
fishboneLayoutStrategy = new OrgChart.Layout.MultiLineFishboneLayoutStrategy();
fishboneLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
fishboneLayoutStrategy.MaxGroups = 2;
fishboneLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
fishboneLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("fishbone2", fishboneLayoutStrategy);
var hstackLayoutStrategy = new OrgChart.Layout.StackingLayoutStrategy();
hstackLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.InvalidValue;
hstackLayoutStrategy.Orientation = OrgChart.Layout.StackOrientation.SingleRowHorizontal;
hstackLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
hstackLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("hstack", hstackLayoutStrategy);
var vstackLayoutStrategy = new OrgChart.Layout.StackingLayoutStrategy();
vstackLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.InvalidValue;
vstackLayoutStrategy.Orientation = OrgChart.Layout.StackOrientation.SingleColumnVertical;
vstackLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
vstackLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("vstack", vstackLayoutStrategy);
vstackLayoutStrategy = new OrgChart.Layout.StackingLayoutStrategy();
vstackLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.InvalidValue;
vstackLayoutStrategy.Orientation = OrgChart.Layout.StackOrientation.SingleColumnVertical;
vstackLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
vstackLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("vstackMiddle", vstackLayoutStrategy);
vstackLayoutStrategy = new OrgChart.Layout.StackingLayoutStrategy();
vstackLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.InvalidValue;
vstackLayoutStrategy.Orientation = OrgChart.Layout.StackOrientation.SingleColumnVertical;
vstackLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
vstackLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("vstackTop", vstackLayoutStrategy);
var assistantsLayoutStrategy = new OrgChart.Layout.FishboneAssistantsLayoutStrategy();
assistantsLayoutStrategy.ParentAlignment = OrgChart.Layout.BranchParentAlignment.Center;
assistantsLayoutStrategy.ParentChildSpacing = RPOrgChart.parentChildSpacing;
assistantsLayoutStrategy.SiblingSpacing = RPOrgChart.siblingSpacing;
diagram.LayoutSettings.LayoutStrategies.add("assistants", assistantsLayoutStrategy);
diagram.LayoutSettings.DefaultLayoutStrategyId = "vstack";
diagram.LayoutSettings.DefaultAssistantLayoutStrategyId = "assistants";
//diagram.LayoutSettings.setBranchSpacing(5);
},
getBoxLevel: function(boxContainer, box) {
var level = 0;
var obj = {};
while (box.ParentId > 0) {
if (!boxContainer.getBoxesById().tryGetValue(box.ParentId, obj)) {
break;
}
box = obj.v;
level++;
}
return level;
},
onLayoutStateChanged: function (sender, args) {
if (args.State.getCurrentOperation() === OrgChart.Layout.LayoutState.Operation.PreprocessVisualTree) {
// When layout algorithm is ready to preprocess the tree,
// we need to have box sizes ready -> hence have to render visible boxes in HTML.
// Rendering can happen at earlier time, but it's just more convenient to do it here,
// to utilize some readily available information about visual tree.
RPOrgChart.renderBoxes();
}
},
renderBoxes: function () {
var visitorFunc = function (node) {
var box = node.Element;
if (box.getIsDataBound()) {
// we're being run when nodes have already been marked as visible or hidden,
// based on IsCollapsed attribute of each Box
// so use this knowledge to prevent unnecessary rendering of invisible branches
if (node.State.IsHidden) {
return true;
}
box.Size = RPOrgChart.getBoxElementSize(box.DataId);
}
return true;
}
RPOrgChart.diagram.getVisualTree().IterateParentFirst(visitorFunc);
},
getBranchOptimizerFunc: function () {
return RPOrgChart[RPOrgChart.branchOptimizer];
},
branchOptimizerAllLinear: function(node) {
return node.getIsAssistantRoot() ? null : "linear";
},
branchOptimizerAllHanger2: function(node) {
return node.getIsAssistantRoot() ? null : "hanger2";
},
branchOptimizerAllHanger4: function(node) {
return node.getIsAssistantRoot() ? null : "hanger4";
},
branchOptimizerAllFishbone1: function(node) {
return node.getIsAssistantRoot() ? null : "fishbone1";
},
branchOptimizerAllFishbone2: function (node) {
return node.getIsAssistantRoot() ? null : "fishbone2";
},
branchOptimizerAllSingleColumnLeft: function (node) {
return node.getIsAssistantRoot() ? null : "singleColumnRight";
},
branchOptimizerAllSingleColumnRight: function (node) {
return node.getIsAssistantRoot() ? null : "singleColumnLeft";
},
branchOptimizerStackers: function(node) {
if (node.getIsAssistantRoot()) {
return null;
}
return node.Level === 0 // this is Node for boxContainer.SystemRoot, which is not visible itself
? "vstackTop"
: node.Level === 1 // this is children of SystemRoot - they appear as roots in the diagram
? "vstackMiddle"
: "hstack";
},
branchOptimizerSmart: function(node) {
if (node.getIsAssistantRoot()) {
return null;
}
var childCount = node.getChildCount();
if (childCount <= 1) {
return "vstack";
}
var nonLeafChildren = 0;
for (var i = 0; i < childCount; i++) {
if (node.Children.getItem(i).getChildCount() > 0) {
nonLeafChildren++;
}
}
if (nonLeafChildren <= 1) {
if (childCount <= 4) {
return "vstack";
}
if (childCount <= 8) {
return "fishbone1";
}
return "fishbone2";
}
return "hanger4";
},
boxSizeFunc: function (dataId) {
// ChartLayoutAlgorithm requires this function to accept data ID
// so have to convert it to Box ID first, to get rendered visual element
var boxId = RPOrgChart.diagram.getBoxes().getBoxesByDataId().getItem(dataId).Id;
return RPOrgChart.diagram.getBoxes().getBoxesById().getItem(boxId).Size;
},
getBoxElementSize: function (boxId) {
var geo = RPOrgChart.graph.model.cells[boxId].geometry;
return new OrgChart.Layout.Size.$ctor1(geo.width, geo.height);
},
positionBoxes: function () {
var diagram = RPOrgChart.diagram;
var state = new OrgChart.Layout.LayoutState(diagram);
state.addOperationChanged(RPOrgChart.onLayoutStateChanged);
state.BoxSizeFunc = Bridge.fn.bind(this, RPOrgChart.boxSizeFunc, null, true);
state.LayoutOptimizerFunc = Bridge.fn.bind(this, RPOrgChart.getBranchOptimizerFunc(), null, true);
OrgChart.Layout.LayoutAlgorithm.Apply(state);
var diagramBoundary = OrgChart.Layout.LayoutAlgorithm.ComputeBranchVisualBoundingRect(diagram.getVisualTree());
var offsetx = -diagramBoundary.getLeft() + diagramBoundary.getTop();
var graph = RPOrgChart.graph;
var cells = graph.model.cells;
var pointsList = [];
var visitorVertexFunc = function (node)
{
if (node.State.IsHidden) {
return false;
}
var box = node.Element;
if (box.getIsDataBound()) {
var cell = cells[box.DataId];
var geo = cell.geometry.clone();
geo.x = node.State.TopLeft.X + offsetx;
geo.y = node.State.TopLeft.Y;
graph.model.setGeometry(cell, geo);
}
return true;
}
var visitorEdgeFunc = function (node)
{
//The algorithm default is 5 px only above the node, this centers it
var yCorrection = RPOrgChart.correctY? Math.min(0, -(RPOrgChart.parentChildSpacing / 2) + 5) : 0;
// Render connectors
if (node.State.Connector != null) {
var cell = cells[node.Element.DataId];
var outgoingEdge = graph.getOutgoingEdges(cell);
var uniquePoints = {};
//Sort segments points from top to bottom or left to right + add offset
for (var ix = 0; ix < node.State.Connector.Segments.length; ix++)
{
var edge = node.State.Connector.Segments[ix];
edge.mark = 1 << ix; //TODO Support up to 31 segments. In this a limit?
edge.From.X += offsetx;
edge.To.X += offsetx;
var fx = edge.From.X, fy = edge.From.Y, tx = edge.To.X, ty = edge.To.Y;
if ((fx == tx && fy > ty) || (fy == ty && fx > tx))
{
var tmp = edge.From;
edge.From = edge.To;
edge.To = tmp;
}
}
//Collecting points including intersection of segments
for (var ix = 0; ix < node.State.Connector.Segments.length; ix++)
{
var edge = node.State.Connector.Segments[ix];
var fx = edge.From.X, fy = edge.From.Y, tx = edge.To.X, ty = edge.To.Y;
var fp = new mxPoint(fx, fy);
pointsList.push(fp);
fp.mark = edge.mark;
var up = uniquePoints[fx + ',' + fy];
if (up != null)
{
up.mark |= fp.mark;
}
else
{
uniquePoints[fx + ',' + fy] = fp;
}
var tp = new mxPoint(tx, ty);
pointsList.push(tp);
tp.mark = edge.mark;
var up = uniquePoints[tx + ',' + ty];
if (up != null)
{
up.mark |= tp.mark;
}
else
{
uniquePoints[tx + ',' + ty] = tp;
}
//Find intersections
for (var j = ix + 1; j < node.State.Connector.Segments.length; j++)
{
var e2 = node.State.Connector.Segments[j];
var fx2 = e2.From.X, fy2 = e2.From.Y, tx2 = e2.To.X, ty2 = e2.To.Y;
if (fx == tx && fy <= fy2 && ty >= fy2 && fx2 <= fx && tx2 >= fx) //Ver |_ Hor
{
var ip = new mxPoint(fx, fy2);
pointsList.push(ip);
ip.mark = edge.mark | e2.mark;
var up = uniquePoints[fx + ',' + fy2];
if (up != null)
{
up.mark |= ip.mark;
}
else
{
uniquePoints[fx + ',' + fy2] = ip;
}
}
else if (fy == ty && fx <= fx2 && tx >= fx2 && fy2 <= fy && ty2 >= fy) //Hor _| Ver
{
var ip = new mxPoint(fx2, fy);
pointsList.push(ip);
ip.mark = edge.mark | e2.mark;
var up = uniquePoints[fx2 + ',' + fy]
if (up != null)
{
up.mark |= ip.mark;
}
else
{
uniquePoints[fx2 + ',' + fy] = ip;
}
}
}
}
//Sort points on y then x
var pointsArr = [];
for (var k in uniquePoints)
{
pointsArr.push(uniquePoints[k]);
}
pointsArr.sort(function(a, b)
{
var dy = a.y - b.y;
return dy == 0? a.x - b.x : dy;
});
function pointOnCell(geo, p)
{
return p.x >= geo.x && p.x <= geo.x + geo.width && p.y >= geo.y && p.y <= geo.y + geo.height;
};
function adjustEdgeGeoAndStyle(edge, edgePoints)
{
var eGeo = edge.geometry.clone();
for (var i = 0; edgePoints && i < edgePoints.length; i++)
{
if (!edgePoints[i].corrected)
{
edgePoints[i].y += yCorrection;
edgePoints[i].corrected = true
}
}
eGeo.points = edgePoints;
graph.model.setGeometry(edge, eGeo);
//Remove entry and exit points
graph.setCellStyles('entryX', null, [edge]);
graph.setCellStyles('entryY', null, [edge]);
graph.setCellStyles('exitX', null, [edge]);
graph.setCellStyles('exitY', null, [edge]);
//Set type orthogonal
graph.setCellStyles('edgeStyle', 'orthogonalEdgeStyle', [edge]);
};
var outgoingEdge = graph.getOutgoingEdges(cell);
//Simple case of a single segment. TODO Handle this case earlier
if (pointsArr.length == 2 && outgoingEdge.length == 1)
{
adjustEdgeGeoAndStyle(outgoingEdge[0], pointsArr);
}
else
{
var srcGeo = cell.geometry;
var srcP;
//Find src starting point //TODO It should be first point always?
for (var i = 0; i < pointsArr.length; i++)
{
if (pointOnCell(srcGeo, pointsArr[i]))
{
srcP = pointsArr[i];
break;
}
}
var selected;
function getNextPoint(lp)
{
for (var i = 0; i < pointsArr.length; i++)
{
var p = pointsArr[i];
if (selected[p.x + ',' + p.y]) continue;
if (p.mark & lp.mark)
{
selected[p.x + ',' + p.y] = true;
return p;
}
}
}
for (var j = 0; j < outgoingEdge.length; j++)
{
if (outgoingEdge[j].target != null)
{
selected = {};
selected[srcP.x + ',' + srcP.y] = true;
var trgGeo = outgoingEdge[j].target.geometry;
var edgePoints = [srcP];
var lp = srcP;
var safeGuard = 0;
//Is BFS better?
while (safeGuard < 1000)
{
safeGuard++;
var np = getNextPoint(lp);
//retract, then remove this point
if (np == null)
{
edgePoints.pop();
lp = edgePoints[edgePoints.length - 1];
}
else
{
edgePoints.push(np);
lp = np;
if (pointOnCell(trgGeo, np)) break;
}
}
//Remove retracted points TODO can we do it in a better way?
if (edgePoints.length > 2)
{
var spX = edgePoints[0].x;
var lpX = edgePoints[edgePoints.length - 1].x;
for (var i = edgePoints.length - 2; i > 0; i--)
{
if ((spX > lpX && edgePoints[i].x < lpX) || (spX < lpX && edgePoints[i].x < spX))
{
edgePoints.splice(i, 1);
}
}
}
var eGeo = outgoingEdge[j].geometry.clone();
eGeo.points = edgePoints;
RPOrgChart.graph.model.setGeometry(outgoingEdge[j], eGeo);
//Fix edge points and style
adjustEdgeGeoAndStyle(outgoingEdge[j], edgePoints);
}
}
}
}
return true;
}
diagram.getVisualTree().IterateParentFirst(visitorVertexFunc);
diagram.getVisualTree().IterateParentFirst(visitorEdgeFunc);
//Cleanup
for (var i = 0; i < pointsList.length; i++)
{
delete pointsList[i].mark;
delete pointsList[i].corrected;
}
}
}
});
Bridge.init();