@peter.prib/renderengine 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +203 -2
- package/REFERENCE.md +2198 -0
- package/dist/renderengine-workspace.umd.js +46905 -0
- package/dist/renderengine.umd.js +42223 -0
- package/examples/archimate.html +66 -0
- package/examples/diagram-editor.html +51 -0
- package/package.json +65 -4
- package/src/BaseRenderer.js +57 -0
- package/src/CanvasRenderer.js +194 -0
- package/src/Mat4.js +111 -0
- package/src/OrbitCamera.js +57 -0
- package/src/RendererFactory.js +50 -0
- package/src/SVGRenderer.js +439 -0
- package/src/archimate.js +723 -0
- package/src/archimateArchiFormat.js +1693 -0
- package/src/archimateArchiTypes.js +72 -0
- package/src/archimateArchive.js +140 -0
- package/src/archimateCSV.js +127 -0
- package/src/archimateDrawio.js +182 -0
- package/src/archimateExchangeFormat.js +546 -0
- package/src/archimateRelationshipTable.js +93 -0
- package/src/archimateSpecializations.js +161 -0
- package/src/chartCatalog.js +589 -0
- package/src/charting/ArchimateDiagramEditor.js +1624 -0
- package/src/charting/ArchimateSpecializationSelector.js +134 -0
- package/src/charting/Axis.js +68 -0
- package/src/charting/CameraSeeder.js +30 -0
- package/src/charting/CatalogDialog.js +92 -0
- package/src/charting/Chart.js +37 -0
- package/src/charting/Chart3D.js +99 -0
- package/src/charting/ChartBox.js +80 -0
- package/src/charting/ChartData.js +27 -0
- package/src/charting/ChartRegistry.js +76 -0
- package/src/charting/CheckboxTreeSelector.js +304 -0
- package/src/charting/ColorField.js +107 -0
- package/src/charting/ColorPalette.js +88 -0
- package/src/charting/CommandHistory.js +176 -0
- package/src/charting/DataFilter.js +52 -0
- package/src/charting/Diagram.js +36 -0
- package/src/charting/Diagram3D.js +29 -0
- package/src/charting/DiagramClipboard.js +31 -0
- package/src/charting/DiagramEditor.js +3330 -0
- package/src/charting/DiagramEditorCommand.js +110 -0
- package/src/charting/DiagramEditorCommands.js +237 -0
- package/src/charting/DiagramEditorEdgeCommands.js +142 -0
- package/src/charting/DiagramEditorState.js +98 -0
- package/src/charting/DiagramRegistry.js +86 -0
- package/src/charting/DiagramTypeRegistry.js +326 -0
- package/src/charting/DiagramViewPropertiesDialog.js +46 -0
- package/src/charting/Edge.js +113 -0
- package/src/charting/ErrorBars.js +37 -0
- package/src/charting/FilterSystem.js +285 -0
- package/src/charting/FindReplaceDialog.js +139 -0
- package/src/charting/FormDialog.js +385 -0
- package/src/charting/Gauge.js +58 -0
- package/src/charting/Hierarchy.js +175 -0
- package/src/charting/HintPanel.js +86 -0
- package/src/charting/ImageSelector.js +148 -0
- package/src/charting/InteractionManager.js +725 -0
- package/src/charting/Legend.js +58 -0
- package/src/charting/MenuBar.js +62 -0
- package/src/charting/ModelFileFormat.js +115 -0
- package/src/charting/OrbitControls.js +77 -0
- package/src/charting/Palette.js +119 -0
- package/src/charting/PopupMenu.js +117 -0
- package/src/charting/PropertiesPanel.js +155 -0
- package/src/charting/PropertyListEditor.js +96 -0
- package/src/charting/PropertyLog.js +92 -0
- package/src/charting/SettingsCascade.js +93 -0
- package/src/charting/SettingsDialog.js +53 -0
- package/src/charting/SettingsManager.js +179 -0
- package/src/charting/SettingsViewPropertiesDialog.js +58 -0
- package/src/charting/ShapePaths.js +27 -0
- package/src/charting/Statistics.js +134 -0
- package/src/charting/TemplateCatalog.js +59 -0
- package/src/charting/TemplateLibrary.js +103 -0
- package/src/charting/TextStyle.js +168 -0
- package/src/charting/ViewFit.js +55 -0
- package/src/charting/ViewMenu.js +70 -0
- package/src/charting/ViewPropertiesDialog.js +77 -0
- package/src/charting/ViewTabStrip.js +81 -0
- package/src/charting/archimate/ArchiFileFormat.js +32 -0
- package/src/charting/archimate/ArchimateCanvasEditor.js +815 -0
- package/src/charting/archimate/ArchimateCsvFileFormat.js +35 -0
- package/src/charting/archimate/ArchimateEdge.js +137 -0
- package/src/charting/archimate/ArchimateElementTemplate.js +195 -0
- package/src/charting/archimate/ArchimatePalette.js +102 -0
- package/src/charting/archimate/CsvImportDialog.js +105 -0
- package/src/charting/archimate/CustomViewpoints.js +74 -0
- package/src/charting/archimate/DerivedEdge.js +29 -0
- package/src/charting/archimate/DrawioFileFormat.js +24 -0
- package/src/charting/archimate/ElementFilterRule.js +21 -0
- package/src/charting/archimate/ExchangeFileFormat.js +28 -0
- package/src/charting/archimate/ViewGroupTemplate.js +137 -0
- package/src/charting/archimate/ViewLineEdge.js +84 -0
- package/src/charting/archimate/ViewpointRule.js +45 -0
- package/src/charting/archimate/archimateFileFormats.js +12 -0
- package/src/charting/archimate/archimateNames.js +5 -0
- package/src/charting/archimate/csvMapping.js +122 -0
- package/src/charting/archimate/elementMenuItems.js +32 -0
- package/src/charting/archimate/elementProperties.js +146 -0
- package/src/charting/archimate/elementTypeChoices.js +7 -0
- package/src/charting/archimate/elementTypeGroups.js +19 -0
- package/src/charting/archimate/index.js +17 -0
- package/src/charting/archimate/specializationCatalogDialog.js +64 -0
- package/src/charting/archimate/typeGlyph.js +29 -0
- package/src/charting/arrangement/Arrangement.js +112 -0
- package/src/charting/arrangement/ArrangementCommand.js +29 -0
- package/src/charting/arrangement/BackgroundCommand.js +41 -0
- package/src/charting/arrangement/BackgroundGroup.js +18 -0
- package/src/charting/arrangement/GroupCommand.js +46 -0
- package/src/charting/arrangement/ItemGroup.js +62 -0
- package/src/charting/arrangement/LockCommand.js +32 -0
- package/src/charting/arrangement/UngroupCommand.js +27 -0
- package/src/charting/arrangement/alignment.js +88 -0
- package/src/charting/arrangement/arrangeMenuItems.js +25 -0
- package/src/charting/arrangement/index.js +11 -0
- package/src/charting/arrangement/layouts.js +233 -0
- package/src/charting/canvas/ArchiHint.js +78 -0
- package/src/charting/canvas/CanvasBoxKind.js +39 -0
- package/src/charting/canvas/CanvasPalette.js +49 -0
- package/src/charting/canvas/CanvasTemplateLibrary.js +61 -0
- package/src/charting/canvas/CanvasTemplateMenu.js +151 -0
- package/src/charting/canvas/EditHintCommand.js +28 -0
- package/src/charting/canvas/canvasBoxKinds.js +27 -0
- package/src/charting/canvas/canvasBoxMenuItems.js +40 -0
- package/src/charting/canvas/defaultCanvasTemplates.js +186 -0
- package/src/charting/canvas/diagramBoxKinds.js +12 -0
- package/src/charting/canvas/hintMenuItems.js +49 -0
- package/src/charting/charts/ArcGauge.js +55 -0
- package/src/charting/charts/AreaChart.js +71 -0
- package/src/charting/charts/BarChart.js +80 -0
- package/src/charting/charts/BarChart3D.js +56 -0
- package/src/charting/charts/BarChart3DOrbit.js +53 -0
- package/src/charting/charts/BarChartBase.js +70 -0
- package/src/charting/charts/BarGauge.js +42 -0
- package/src/charting/charts/BoxPlotChart.js +41 -0
- package/src/charting/charts/BubbleChart.js +99 -0
- package/src/charting/charts/BubbleChart3D.js +78 -0
- package/src/charting/charts/BulletGauge.js +87 -0
- package/src/charting/charts/CalendarHeatmapChart.js +204 -0
- package/src/charting/charts/CandlestickChart.js +54 -0
- package/src/charting/charts/ChordDiagram.js +130 -0
- package/src/charting/charts/DensityChart.js +73 -0
- package/src/charting/charts/DialGauge.js +65 -0
- package/src/charting/charts/DonutChart.js +15 -0
- package/src/charting/charts/FunnelChart.js +47 -0
- package/src/charting/charts/GanttChart.js +201 -0
- package/src/charting/charts/GaugeChart.js +175 -0
- package/src/charting/charts/GeoMapChart.js +146 -0
- package/src/charting/charts/GroupedBarChart.js +88 -0
- package/src/charting/charts/GroupedDistributionChart.js +70 -0
- package/src/charting/charts/HeatmapChart.js +80 -0
- package/src/charting/charts/HierarchyChart.js +39 -0
- package/src/charting/charts/HistogramChart.js +45 -0
- package/src/charting/charts/KpiTile.js +72 -0
- package/src/charting/charts/LagPlotChart.js +41 -0
- package/src/charting/charts/LineChart.js +124 -0
- package/src/charting/charts/MultiRingGauge.js +54 -0
- package/src/charting/charts/OutlineChart.js +95 -0
- package/src/charting/charts/ParallelCoordinatesChart.js +130 -0
- package/src/charting/charts/PieChart.js +56 -0
- package/src/charting/charts/PipeChart.js +88 -0
- package/src/charting/charts/PopulationPyramidChart.js +106 -0
- package/src/charting/charts/QQPlotChart.js +64 -0
- package/src/charting/charts/RadarChart.js +76 -0
- package/src/charting/charts/RadialBarChart.js +96 -0
- package/src/charting/charts/RingGauge.js +23 -0
- package/src/charting/charts/SankeyDiagram.js +174 -0
- package/src/charting/charts/ScatterChart.js +104 -0
- package/src/charting/charts/StackedAreaChart.js +15 -0
- package/src/charting/charts/StackedBarChart.js +33 -0
- package/src/charting/charts/StackedBarChart3DOrbit.js +58 -0
- package/src/charting/charts/StreamGraphChart.js +131 -0
- package/src/charting/charts/SunburstChart.js +57 -0
- package/src/charting/charts/ThermometerGauge.js +43 -0
- package/src/charting/charts/TreemapChart.js +54 -0
- package/src/charting/charts/ViolinChart.js +37 -0
- package/src/charting/charts/WaterfallChart.js +66 -0
- package/src/charting/charts/WordCloudChart.js +104 -0
- package/src/charting/diagramModel/AddViewCommand.js +33 -0
- package/src/charting/diagramModel/DiagramModel.js +39 -0
- package/src/charting/diagramModel/DiagramModelSearch.js +22 -0
- package/src/charting/diagramModel/DiagramView.js +50 -0
- package/src/charting/diagramModel/ModelHistory.js +43 -0
- package/src/charting/diagramModel/ModelReport.js +153 -0
- package/src/charting/diagramModel/ModelSearch.js +223 -0
- package/src/charting/diagramModel/RemoveViewCommand.js +25 -0
- package/src/charting/diagramModel/RenameViewCommand.js +21 -0
- package/src/charting/diagramModel/ReplaceTextCommand.js +25 -0
- package/src/charting/diagramModel/ViewSetChecker.js +34 -0
- package/src/charting/diagramModel/ViewSetModel.js +243 -0
- package/src/charting/diagramModel/index.js +6 -0
- package/src/charting/diagramModel/nameTransforms.js +29 -0
- package/src/charting/diagrams/ArchimateCommands.js +141 -0
- package/src/charting/diagrams/ArchimateDiagram.js +263 -0
- package/src/charting/diagrams/ArchimateModel.js +1155 -0
- package/src/charting/diagrams/ArchimateModelChecker.js +125 -0
- package/src/charting/diagrams/ArchimateModelReport.js +128 -0
- package/src/charting/diagrams/ArchimateModelSearch.js +41 -0
- package/src/charting/diagrams/ArchimateValidator.js +357 -0
- package/src/charting/diagrams/CanvasView.js +112 -0
- package/src/charting/diagrams/ContextMenu.js +37 -0
- package/src/charting/diagrams/DataModelDiagram.js +86 -0
- package/src/charting/diagrams/DataModelRelationshipStrategy.js +38 -0
- package/src/charting/diagrams/DerivedRelationships.js +102 -0
- package/src/charting/diagrams/EbnfDiagram.js +39 -0
- package/src/charting/diagrams/EdgeGeometry.js +553 -0
- package/src/charting/diagrams/EditViewItemCommand.js +128 -0
- package/src/charting/diagrams/ElementInstance.js +157 -0
- package/src/charting/diagrams/GraphDiagram.js +1340 -0
- package/src/charting/diagrams/GraphDiagram3D.js +152 -0
- package/src/charting/diagrams/GraphMetrics.js +81 -0
- package/src/charting/diagrams/GridOverlay.js +137 -0
- package/src/charting/diagrams/ImportRowsCommand.js +62 -0
- package/src/charting/diagrams/LabelHelper.js +108 -0
- package/src/charting/diagrams/MergeElementsCommand.js +101 -0
- package/src/charting/diagrams/NestInstanceCommand.js +34 -0
- package/src/charting/diagrams/NodeGeometry.js +158 -0
- package/src/charting/diagrams/PlaceItemsCommand.js +77 -0
- package/src/charting/diagrams/RadialLayout.js +101 -0
- package/src/charting/diagrams/RelationshipInstance.js +93 -0
- package/src/charting/diagrams/RemoveGroupFromViewCommand.js +28 -0
- package/src/charting/diagrams/RemoveLineCommand.js +27 -0
- package/src/charting/diagrams/ShowElementCommand.js +43 -0
- package/src/charting/diagrams/SvgCoordinate.js +17 -0
- package/src/charting/diagrams/SvgZoom.js +127 -0
- package/src/charting/diagrams/Tooltip.js +62 -0
- package/src/charting/diagrams/ViewConnectionInstance.js +102 -0
- package/src/charting/diagrams/ViewObjectInstance.js +56 -0
- package/src/charting/diagrams/commands/AddEdgeCommand.js +34 -0
- package/src/charting/diagrams/commands/AddNodeCommand.js +28 -0
- package/src/charting/diagrams/commands/AddWaypointCommand.js +27 -0
- package/src/charting/diagrams/commands/CreateFolderCommand.js +27 -0
- package/src/charting/diagrams/commands/DeleteEdgeCommand.js +30 -0
- package/src/charting/diagrams/commands/DeleteFolderCommand.js +47 -0
- package/src/charting/diagrams/commands/DeleteNodeCommand.js +35 -0
- package/src/charting/diagrams/commands/DeleteWaypointCommand.js +24 -0
- package/src/charting/diagrams/commands/GraphCommand.js +65 -0
- package/src/charting/diagrams/commands/InvertEdgeCommand.js +24 -0
- package/src/charting/diagrams/commands/MoveNodeCommand.js +44 -0
- package/src/charting/diagrams/commands/MoveWaypointCommand.js +27 -0
- package/src/charting/diagrams/commands/RenameEdgeCommand.js +23 -0
- package/src/charting/diagrams/commands/RenameFolderCommand.js +31 -0
- package/src/charting/diagrams/commands/RenameNodeCommand.js +27 -0
- package/src/charting/diagrams/commands/ResizeNodeCommand.js +46 -0
- package/src/charting/diagrams/commands/UpdateEdgeSideCommand.js +40 -0
- package/src/charting/diagrams/commands/index.js +17 -0
- package/src/charting/diagrams/duplicates.js +49 -0
- package/src/charting/diagrams/nesting.js +30 -0
- package/src/charting/diagrams/roadmap.js +77 -0
- package/src/charting/edgeMarkers/ArrowMarker.js +15 -0
- package/src/charting/edgeMarkers/CircleMarker.js +13 -0
- package/src/charting/edgeMarkers/CrowsFootMarker.js +16 -0
- package/src/charting/edgeMarkers/DiamondMarker.js +15 -0
- package/src/charting/edgeMarkers/EdgeMarker.js +34 -0
- package/src/charting/edgeMarkers/HalfArrowMarker.js +8 -0
- package/src/charting/edgeMarkers/HollowDiamondMarker.js +18 -0
- package/src/charting/edgeMarkers/HollowTriangleMarker.js +18 -0
- package/src/charting/edgeMarkers/OpenArrowMarker.js +17 -0
- package/src/charting/edgeMarkers/index.js +27 -0
- package/src/charting/edgeStyle/EdgeStyleCascade.js +22 -0
- package/src/charting/edgeStyle/EdgeStyleDialog.js +51 -0
- package/src/charting/edgeStyle/EdgeStyleSchema.js +43 -0
- package/src/charting/edgeStyle/SetStyleCommand.js +12 -0
- package/src/charting/edgeStyle/index.js +4 -0
- package/src/charting/emphasis/EmphasisRule.js +42 -0
- package/src/charting/emphasis/HighlightRule.js +24 -0
- package/src/charting/gauges/ArcTrack.js +51 -0
- package/src/charting/gauges/GaugeAnimation.js +51 -0
- package/src/charting/gauges/GaugeBands.js +48 -0
- package/src/charting/gauges/GaugeScale.js +87 -0
- package/src/charting/gauges/GaugeTrack.js +44 -0
- package/src/charting/gauges/GaugeValue.js +61 -0
- package/src/charting/gauges/HorizontalTrack.js +14 -0
- package/src/charting/gauges/LinearTrack.js +29 -0
- package/src/charting/gauges/Sparkline.js +42 -0
- package/src/charting/gauges/VerticalTrack.js +17 -0
- package/src/charting/glyphs/ArrowGlyph.js +21 -0
- package/src/charting/glyphs/BatteryGlyph.js +18 -0
- package/src/charting/glyphs/ChevronGlyph.js +18 -0
- package/src/charting/glyphs/CircleGlyph.js +15 -0
- package/src/charting/glyphs/CloudGlyph.js +19 -0
- package/src/charting/glyphs/ComponentGlyph.js +18 -0
- package/src/charting/glyphs/ConstraintGlyph.js +24 -0
- package/src/charting/glyphs/ContractBoxGlyph.js +10 -0
- package/src/charting/glyphs/CubeGlyph.js +19 -0
- package/src/charting/glyphs/CylinderGlyph.js +19 -0
- package/src/charting/glyphs/DashedDoubleArrowGlyph.js +11 -0
- package/src/charting/glyphs/DeviceGlyph.js +17 -0
- package/src/charting/glyphs/DiamondGlyph.js +17 -0
- package/src/charting/glyphs/DocumentGlyph.js +17 -0
- package/src/charting/glyphs/DoubleArrowGlyph.js +23 -0
- package/src/charting/glyphs/DoubleCircleGlyph.js +24 -0
- package/src/charting/glyphs/EllipseGlyph.js +18 -0
- package/src/charting/glyphs/FactoryGlyph.js +20 -0
- package/src/charting/glyphs/FlagGlyph.js +16 -0
- package/src/charting/glyphs/GapCircleGlyph.js +17 -0
- package/src/charting/glyphs/GearGlyph.js +37 -0
- package/src/charting/glyphs/Glyph.js +98 -0
- package/src/charting/glyphs/GroupingBoxGlyph.js +13 -0
- package/src/charting/glyphs/HalfCircleGlyph.js +22 -0
- package/src/charting/glyphs/HexagonGlyph.js +28 -0
- package/src/charting/glyphs/IconGlyph.js +22 -0
- package/src/charting/glyphs/ImageGlyph.js +16 -0
- package/src/charting/glyphs/JunctionGlyph.js +17 -0
- package/src/charting/glyphs/LollipopGlyph.js +22 -0
- package/src/charting/glyphs/MagnifierGlyph.js +17 -0
- package/src/charting/glyphs/NoteGlyph.js +33 -0
- package/src/charting/glyphs/ObjectBoxGlyph.js +21 -0
- package/src/charting/glyphs/OrJunctionGlyph.js +17 -0
- package/src/charting/glyphs/ParallelogramGlyph.js +20 -0
- package/src/charting/glyphs/PersonGlyph.js +23 -0
- package/src/charting/glyphs/PillGlyph.js +23 -0
- package/src/charting/glyphs/PinGlyph.js +18 -0
- package/src/charting/glyphs/PrincipleGlyph.js +23 -0
- package/src/charting/glyphs/ProductBoxGlyph.js +16 -0
- package/src/charting/glyphs/RectGlyph.js +15 -0
- package/src/charting/glyphs/RoundedBoxGlyph.js +13 -0
- package/src/charting/glyphs/StackGlyph.js +14 -0
- package/src/charting/glyphs/StepsGlyph.js +20 -0
- package/src/charting/glyphs/StickFigureGlyph.js +32 -0
- package/src/charting/glyphs/SystemSoftwareBoxGlyph.js +16 -0
- package/src/charting/glyphs/TabbedBoxGlyph.js +37 -0
- package/src/charting/glyphs/TargetGlyph.js +23 -0
- package/src/charting/glyphs/WavyBoxGlyph.js +17 -0
- package/src/charting/glyphs/WheelGlyph.js +28 -0
- package/src/charting/glyphs/drawGlyph.js +28 -0
- package/src/charting/glyphs/glyphSvg.js +55 -0
- package/src/charting/glyphs/index.js +109 -0
- package/src/charting/modelTree/AnalysisPanel.js +159 -0
- package/src/charting/modelTree/DiagramTabs.js +217 -0
- package/src/charting/modelTree/ModelTree.js +164 -0
- package/src/charting/modelTree/ModelTreePanel.js +914 -0
- package/src/charting/modelTree/TreeBuilder.js +238 -0
- package/src/charting/modelTree/TreeModeRegistry.js +51 -0
- package/src/charting/modelTree/TreeViewMode.js +110 -0
- package/src/charting/modelTree/buildFilterTrees.js +138 -0
- package/src/charting/modelTree/modes/FlatTreeMode.js +46 -0
- package/src/charting/modelTree/modes/LayerGroupedTreeMode.js +62 -0
- package/src/charting/modelTree/modes/TypeGroupedTreeMode.js +60 -0
- package/src/charting/modelTree/treeLayers.js +11 -0
- package/src/charting/report/reportHtml.js +82 -0
- package/src/charting/report/reportViewer.js +118 -0
- package/src/charting/shapes/CircleShape.js +19 -0
- package/src/charting/shapes/PathShape.js +17 -0
- package/src/charting/shapes/RectShape.js +20 -0
- package/src/charting/shapes/Shape.js +20 -0
- package/src/charting/shapes/ShapeFactory.js +23 -0
- package/src/charting/storage/LocalJsonStore.js +43 -0
- package/src/charting/templates/ActorTemplate.js +36 -0
- package/src/charting/templates/BoxTemplate.js +27 -0
- package/src/charting/templates/CircleTemplate.js +18 -0
- package/src/charting/templates/ClassTemplate.js +20 -0
- package/src/charting/templates/CloudTemplate.js +43 -0
- package/src/charting/templates/ComponentTemplate.js +19 -0
- package/src/charting/templates/CylinderTemplate.js +30 -0
- package/src/charting/templates/DataStoreTemplate.js +16 -0
- package/src/charting/templates/DiamondTemplate.js +10 -0
- package/src/charting/templates/DocumentTemplate.js +32 -0
- package/src/charting/templates/EllipseTemplate.js +15 -0
- package/src/charting/templates/FinalStateTemplate.js +12 -0
- package/src/charting/templates/GlyphTemplate.js +47 -0
- package/src/charting/templates/HexagonTemplate.js +17 -0
- package/src/charting/templates/LifelineTemplate.js +20 -0
- package/src/charting/templates/ManualInputTemplate.js +12 -0
- package/src/charting/templates/NoteTemplate.js +23 -0
- package/src/charting/templates/OctagonTemplate.js +7 -0
- package/src/charting/templates/PackageTemplate.js +25 -0
- package/src/charting/templates/ParallelogramTemplate.js +11 -0
- package/src/charting/templates/PentagonTemplate.js +5 -0
- package/src/charting/templates/PolygonTemplate.js +18 -0
- package/src/charting/templates/PredefinedProcessTemplate.js +13 -0
- package/src/charting/templates/RectangleTemplate.js +28 -0
- package/src/charting/templates/RegularPolygonTemplate.js +21 -0
- package/src/charting/templates/RoundedRectangleTemplate.js +5 -0
- package/src/charting/templates/StadiumTemplate.js +8 -0
- package/src/charting/templates/StarTemplate.js +17 -0
- package/src/charting/templates/SwimlaneTemplate.js +18 -0
- package/src/charting/templates/Template.js +208 -0
- package/src/charting/templates/TrapezoidTemplate.js +11 -0
- package/src/charting/templates/TriangleTemplate.js +12 -0
- package/src/charting/templates/index.js +31 -0
- package/src/charting/templates/outline.js +59 -0
- package/src/charting/templates/svg.js +19 -0
- package/src/charting/textToShapes.js +61 -0
- package/src/charting/toolbar/ToolbarButton.js +38 -0
- package/src/charting/toolbar/ToolbarCheckbox.js +31 -0
- package/src/charting/toolbar/ToolbarItem.js +19 -0
- package/src/charting/toolbar/ToolbarMenu.js +36 -0
- package/src/charting/toolbar/ToolbarSelect.js +38 -0
- package/src/charting/toolbar/ToolbarSeparator.js +7 -0
- package/src/charting/toolbar/ToolbarText.js +22 -0
- package/src/charting/toolbar/index.js +8 -0
- package/src/charting/toolbar/pickFile.js +14 -0
- package/src/charting/viewDecorations.js +85 -0
- package/src/charting/zOrder.js +57 -0
- package/src/csvTable.js +61 -0
- package/src/datamodel.js +122 -0
- package/src/datawindow/BoundedWindow.js +36 -0
- package/src/datawindow/FlatDataWindow.js +34 -0
- package/src/datawindow/GraphDataWindow.js +40 -0
- package/src/datawindow/GroupedSampleDataWindow.js +16 -0
- package/src/datawindow/SeriesDataWindow.js +42 -0
- package/src/datawindow/index.js +31 -0
- package/src/diagramCatalog.js +30 -0
- package/src/ebnfDiagram.js +57 -0
- package/src/ebnfParser.js +129 -0
- package/src/exportImage.js +233 -0
- package/src/index.js +2636 -0
- package/src/itIcons.js +84 -0
- package/src/kernelExpr.js +243 -0
- package/src/propertiesDialog.js +463 -0
- package/src/railroadDiagram.js +571 -0
- package/src/treeModeCatalog.js +16 -0
- package/src/workspace/ContextBus.js +79 -0
- package/src/workspace/EditorShell.js +67 -0
- package/src/workspace/Part.js +163 -0
- package/src/workspace/PartFactory.js +49 -0
- package/src/workspace/PartRegistry.js +86 -0
- package/src/workspace/Workspace.js +321 -0
- package/src/workspace/archimateServices.js +33 -0
- package/src/workspace/dom.js +120 -0
- package/src/workspace/index.js +75 -0
- package/src/workspace/layout/GridNode.js +280 -0
- package/src/workspace/layout/LayoutNode.js +89 -0
- package/src/workspace/layout/PartNode.js +77 -0
- package/src/workspace/layout/SplitNode.js +114 -0
- package/src/workspace/layout/TabsNode.js +191 -0
- package/src/workspace/layout/index.js +24 -0
- package/src/workspace/parts/AdapterPart.js +33 -0
- package/src/workspace/parts/ArchimateCanvasPart.js +345 -0
- package/src/workspace/parts/ArchimateEditorPart.js +79 -0
- package/src/workspace/parts/ChartPart.js +115 -0
- package/src/workspace/parts/ContentPart.js +34 -0
- package/src/workspace/parts/DetailPart.js +46 -0
- package/src/workspace/parts/DiagramEditorPart.js +135 -0
- package/src/workspace/parts/EditorPart.js +388 -0
- package/src/workspace/parts/HtmlPart.js +25 -0
- package/src/workspace/parts/ListPart.js +57 -0
- package/src/workspace/parts/ModelFile.js +187 -0
- package/src/workspace/parts/ModelsPart.js +135 -0
- package/src/workspace/styles.js +258 -0
- package/src/workspace/themes.js +96 -0
- package/src/workspace/workArea.js +413 -0
- package/src/workspace/workAreaModel.js +197 -0
- package/src/workspace.js +16 -0
- package/src/zip/ZipArchive.js +160 -0
- package/src/zip/crc32.js +25 -0
- package/src/zip/inflate.js +159 -0
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
import { NodeGeometry } from './NodeGeometry.js';
|
|
2
|
+
|
|
3
|
+
const SIDE_VECTORS = { top: [0, -1], right: [1, 0], bottom: [0, 1], left: [-1, 0] };
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* EdgeGeometry — pure, stateless helpers for graph edge anchors, routing,
|
|
7
|
+
* waypoints, and path generation.
|
|
8
|
+
*
|
|
9
|
+
* These used to live on RenderEngine; they are collected here so diagram
|
|
10
|
+
* classes can compute edge geometry without going through the engine façade.
|
|
11
|
+
*/
|
|
12
|
+
export class EdgeGeometry {
|
|
13
|
+
/** Pure. The point (and outward unit normal) where an edge attaches to a
|
|
14
|
+
* node's bounding box for a given `side`: 'top'/'right'/'bottom'/'left'
|
|
15
|
+
* pins the anchor to a fixed spot on the node — it stays there as the
|
|
16
|
+
* node moves, instead of sliding around the node to keep facing whatever
|
|
17
|
+
* it's connected to. `'auto'` (default) keeps that older sliding
|
|
18
|
+
* behavior, using `ux,uy` (a unit vector already pointing at the other
|
|
19
|
+
* endpoint) as the direction to project out to the node's edge.
|
|
20
|
+
*
|
|
21
|
+
* `rectBoundary` (true for `shape:'rect'`/`'table'`, false otherwise —
|
|
22
|
+
* see computeEdgePath's callers) picks WHICH boundary 'auto' projects
|
|
23
|
+
* onto: for a circle/person node (always drawn as a true circle, square
|
|
24
|
+
* bounding box or not) a fixed-radius circle is exactly its visible
|
|
25
|
+
* edge, but for a rect/table node that same circle radius (using the
|
|
26
|
+
* LARGER of w/h) massively overshoots a box that's wide but short —
|
|
27
|
+
* visually "the line stops in empty space well outside the rectangle"
|
|
28
|
+
* instead of touching it. `rectBoundary` instead finds where the ray
|
|
29
|
+
* from centre exits the actual w x h box (whichever of the top/bottom
|
|
30
|
+
* or left/right edges it reaches first). */
|
|
31
|
+
static edgeAnchor(pos, size, side, ux, uy, rectBoundary, shapeType = null) {
|
|
32
|
+
const hw = size.w / 2, hh = size.h / 2;
|
|
33
|
+
switch (side) {
|
|
34
|
+
case 'top': return { x: pos.x, y: pos.y - hh, nx: 0, ny: -1 };
|
|
35
|
+
case 'bottom': return { x: pos.x, y: pos.y + hh, nx: 0, ny: 1 };
|
|
36
|
+
case 'left': return { x: pos.x - hw, y: pos.y, nx: -1, ny: 0 };
|
|
37
|
+
case 'right': return { x: pos.x + hw, y: pos.y, nx: 1, ny: 0 };
|
|
38
|
+
default: {
|
|
39
|
+
if (rectBoundary) {
|
|
40
|
+
const tx = ux !== 0 ? hw / Math.abs(ux) : Infinity;
|
|
41
|
+
const ty = uy !== 0 ? hh / Math.abs(uy) : Infinity;
|
|
42
|
+
const t = Math.min(tx, ty);
|
|
43
|
+
const safeT = Number.isFinite(t) ? t : 0;
|
|
44
|
+
return { x: pos.x + ux * safeT, y: pos.y + uy * safeT, nx: ux, ny: uy };
|
|
45
|
+
}
|
|
46
|
+
// Diamond-specific anchoring: find intersection with actual diamond edges
|
|
47
|
+
if (shapeType === 'diamond') {
|
|
48
|
+
const t = EdgeGeometry._diamondBoundaryT(ux, uy, hw, hh);
|
|
49
|
+
return { x: pos.x + ux * t, y: pos.y + uy * t, nx: ux, ny: uy };
|
|
50
|
+
}
|
|
51
|
+
// Default circle-based anchoring for other shapes
|
|
52
|
+
const r = Math.max(size.w, size.h) / 2;
|
|
53
|
+
return { x: pos.x + ux * r, y: pos.y + uy * r, nx: ux, ny: uy };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Pure. Given a unit direction vector (ux, uy) and diamond half-dimensions (hw, hh),
|
|
59
|
+
* find the distance t such that (t*ux, t*uy) intersects the diamond's perimeter.
|
|
60
|
+
* Diamond vertices are at (±hw, 0) and (0, ±hh), with perimeter equation |x|/hw + |y|/hh = 1.
|
|
61
|
+
* For a ray at (t*ux, t*uy): t*(|ux|/hw + |uy|/hh) = 1 => t = 1 / (|ux|/hw + |uy|/hh) */
|
|
62
|
+
static _diamondBoundaryT(ux, uy, hw, hh) {
|
|
63
|
+
const absUx = Math.abs(ux), absUy = Math.abs(uy);
|
|
64
|
+
if (absUx === 0 && absUy === 0) return 0; // Coincident nodes
|
|
65
|
+
const denom = (absUx / hw) + (absUy / hh);
|
|
66
|
+
return denom > 0 ? 1 / denom : Math.max(hw, hh);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Pure. Anchor for one end of an edge. A node that knows its own outline
|
|
70
|
+
* supplies `info.boundaryPoint(dx, dy) → {x, y}` (DiagramEditor templates
|
|
71
|
+
* do, rotation included), and the anchor is where the ray toward the other
|
|
72
|
+
* end — or out of the pinned side — meets it. Otherwise falls back to the
|
|
73
|
+
* shape-class model in edgeAnchor. */
|
|
74
|
+
static nodeAnchor(info, pos, size, side, ux, uy, rectBoundary) {
|
|
75
|
+
if (typeof info?.boundaryPoint !== 'function') {
|
|
76
|
+
return EdgeGeometry.edgeAnchor(pos, size, side, ux, uy, rectBoundary, info?.shape);
|
|
77
|
+
}
|
|
78
|
+
const [nx, ny] = SIDE_VECTORS[side] ?? [ux, uy];
|
|
79
|
+
const p = info.boundaryPoint(nx, ny);
|
|
80
|
+
return { x: p.x, y: p.y, nx, ny };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Pure. The side of a `size.w × size.h` node at `pos` that faces
|
|
84
|
+
* `toward`, comparing offsets relative to the node's proportions so a wide
|
|
85
|
+
* box prefers its long sides. */
|
|
86
|
+
static facingSide(pos, size, toward) {
|
|
87
|
+
const dx = toward.x - pos.x, dy = toward.y - pos.y;
|
|
88
|
+
if (Math.abs(dx) / (size.w || 1) >= Math.abs(dy) / (size.h || 1)) return dx >= 0 ? 'right' : 'left';
|
|
89
|
+
return dy >= 0 ? 'bottom' : 'top';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Pure. Unit directions in which a path arrives at each end, pointing
|
|
93
|
+
* into the node: `start` runs from the path's next point toward its first
|
|
94
|
+
* point, `end` from the previous point toward its last. Works for every
|
|
95
|
+
* path computeEdgePath emits (absolute M/L/C): the neighbouring coordinate
|
|
96
|
+
* pair is the adjacent vertex or bezier control point, both tangent to
|
|
97
|
+
* the end. Coincident points are skipped; {x:0,y:0} if all coincide. */
|
|
98
|
+
static endDirections(d) {
|
|
99
|
+
const nums = (d || '').match(/-?\d*\.?\d+(?:e[-+]?\d+)?/gi)?.map(Number) ?? [];
|
|
100
|
+
const pts = [];
|
|
101
|
+
for (let i = 0; i + 1 < nums.length; i += 2) pts.push({ x: nums[i], y: nums[i + 1] });
|
|
102
|
+
const toward = (tip, others) => {
|
|
103
|
+
for (const p of others) {
|
|
104
|
+
const dx = tip.x - p.x, dy = tip.y - p.y, len = Math.hypot(dx, dy);
|
|
105
|
+
if (len > 1e-9) return { x: dx / len, y: dy / len };
|
|
106
|
+
}
|
|
107
|
+
return { x: 0, y: 0 };
|
|
108
|
+
};
|
|
109
|
+
if (!pts.length) return { start: { x: 0, y: 0 }, end: { x: 0, y: 0 } };
|
|
110
|
+
return {
|
|
111
|
+
start: toward(pts[0], pts.slice(1)),
|
|
112
|
+
end: toward(pts[pts.length - 1], pts.slice(0, -1).reverse()),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Pure. 'h' when `side` pins the anchor to a vertical edge of the node's
|
|
117
|
+
* box (left/right — the line touches it moving horizontally), 'v' for
|
|
118
|
+
* top/bottom, null for 'auto' (no fixed orientation to route around). */
|
|
119
|
+
static edgeSideOrientation(side) {
|
|
120
|
+
if (side === 'left' || side === 'right') return 'h';
|
|
121
|
+
if (side === 'top' || side === 'bottom') return 'v';
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Pure. Cubic-bezier path between two pinned/auto anchors, leaving and
|
|
126
|
+
* arriving along each anchor's own normal (`nx,ny`) so a pinned side
|
|
127
|
+
* produces a visibly perpendicular exit/entry instead of a straight
|
|
128
|
+
* dog-leg. The generalized shape of the table-link curve in
|
|
129
|
+
* computeEdgePath, usable for any node pair. */
|
|
130
|
+
static curvedEdgePath(a1, a2) {
|
|
131
|
+
const dist = Math.hypot(a2.x - a1.x, a2.y - a1.y) || 1;
|
|
132
|
+
const k = Math.min(dist * 0.5, 80);
|
|
133
|
+
const c1x = a1.x + a1.nx * k, c1y = a1.y + a1.ny * k;
|
|
134
|
+
const c2x = a2.x + a2.nx * k, c2y = a2.y + a2.ny * k;
|
|
135
|
+
return { x1: a1.x, y1: a1.y, x2: a2.x, y2: a2.y, d: `M${a1.x},${a1.y} C${c1x},${c1y} ${c2x},${c2y} ${a2.x},${a2.y}` };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Pure. Right-angle (Manhattan) path between two anchors. When a side is
|
|
139
|
+
* pinned, the segment touching that anchor is forced to the matching
|
|
140
|
+
* orientation (horizontal for left/right, vertical for top/bottom); with
|
|
141
|
+
* both anchors 'auto' it just bends along whichever axis has the bigger
|
|
142
|
+
* gap. Mixed orientations (e.g. source pinned right, target pinned top)
|
|
143
|
+
* get a single-corner elbow instead of the usual midpoint jog, since a
|
|
144
|
+
* midpoint jog can't satisfy two different orientations at once.
|
|
145
|
+
*
|
|
146
|
+
* With `obstacles` (array of {x,y,r} nodes), routes around blocking obstacles
|
|
147
|
+
* using axis-aligned detour lanes. No avoidance for mixed-orientation elbows;
|
|
148
|
+
* those are rare and have degenerate geometry. */
|
|
149
|
+
static orthogonalEdgePath(a1, a2, sourceSide, targetSide, obstacles = []) {
|
|
150
|
+
const so = EdgeGeometry.edgeSideOrientation(sourceSide);
|
|
151
|
+
const to = EdgeGeometry.edgeSideOrientation(targetSide);
|
|
152
|
+
let d;
|
|
153
|
+
if (so && to && so !== to) {
|
|
154
|
+
const corner = so === 'h' ? { x: a2.x, y: a1.y } : { x: a1.x, y: a2.y };
|
|
155
|
+
d = `M${a1.x},${a1.y} L${corner.x},${corner.y} L${a2.x},${a2.y}`;
|
|
156
|
+
} else {
|
|
157
|
+
const horizontalFirst = so ? so === 'h' : (to ? to === 'h' : Math.abs(a2.x - a1.x) >= Math.abs(a2.y - a1.y));
|
|
158
|
+
const blocking = EdgeGeometry.findBlockingObstacles(a1, a2, obstacles);
|
|
159
|
+
|
|
160
|
+
if (blocking.length === 0) {
|
|
161
|
+
// No obstacles — use the plain midpoint jog
|
|
162
|
+
if (horizontalFirst) {
|
|
163
|
+
const midX = (a1.x + a2.x) / 2;
|
|
164
|
+
d = `M${a1.x},${a1.y} L${midX},${a1.y} L${midX},${a2.y} L${a2.x},${a2.y}`;
|
|
165
|
+
} else {
|
|
166
|
+
const midY = (a1.y + a2.y) / 2;
|
|
167
|
+
d = `M${a1.x},${a1.y} L${a1.x},${midY} L${a2.x},${midY} L${a2.x},${a2.y}`;
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
// Route around the obstacle cluster with a detour lane
|
|
171
|
+
const bounds = EdgeGeometry.obstacleClusterBounds(blocking);
|
|
172
|
+
if (horizontalFirst) {
|
|
173
|
+
const naturalY = (a1.y + a2.y) / 2;
|
|
174
|
+
const routeY = naturalY < bounds.minY ? bounds.minY - 12 : bounds.maxY + 12;
|
|
175
|
+
d = `M${a1.x},${a1.y} L${a1.x},${routeY} L${a2.x},${routeY} L${a2.x},${a2.y}`;
|
|
176
|
+
} else {
|
|
177
|
+
const naturalX = (a1.x + a2.x) / 2;
|
|
178
|
+
const routeX = naturalX < bounds.minX ? bounds.minX - 12 : bounds.maxX + 12;
|
|
179
|
+
d = `M${a1.x},${a1.y} L${routeX},${a1.y} L${routeX},${a2.y} L${a2.x},${a2.y}`;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return { x1: a1.x, y1: a1.y, x2: a2.x, y2: a2.y, d };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Pure. True if the segment a1->a2 passes within `circle.r` of `circle`'s
|
|
187
|
+
* centre (see pointToSegmentDist2 for the underlying clamped-distance math). */
|
|
188
|
+
static segmentIntersectsCircle(a1, a2, circle) {
|
|
189
|
+
return EdgeGeometry.pointToSegmentDist2(a1, a2, circle.x, circle.y) < circle.r * circle.r;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Pure. Find all obstacles that block the direct line from a1 to a2.
|
|
193
|
+
* Returns array of blocking obstacles, sorted by their position along the line. */
|
|
194
|
+
static findBlockingObstacles(a1, a2, obstacles = []) {
|
|
195
|
+
return obstacles
|
|
196
|
+
.filter(o => EdgeGeometry.segmentIntersectsCircle(a1, a2, o))
|
|
197
|
+
.sort((o1, o2) => {
|
|
198
|
+
const dx = a2.x - a1.x, dy = a2.y - a1.y;
|
|
199
|
+
const len2 = dx * dx + dy * dy;
|
|
200
|
+
const t1 = ((o1.x - a1.x) * dx + (o1.y - a1.y) * dy) / len2;
|
|
201
|
+
const t2 = ((o2.x - a1.x) * dx + (o2.y - a1.y) * dy) / len2;
|
|
202
|
+
return t1 - t2;
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Pure. Compute bounding box around a cluster of obstacles with clearance margin. */
|
|
207
|
+
static obstacleClusterBounds(obstacles, margin = 12) {
|
|
208
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
209
|
+
for (const o of obstacles) {
|
|
210
|
+
minX = Math.min(minX, o.x - o.r - margin);
|
|
211
|
+
minY = Math.min(minY, o.y - o.r - margin);
|
|
212
|
+
maxX = Math.max(maxX, o.x + o.r + margin);
|
|
213
|
+
maxY = Math.max(maxY, o.y + o.r + margin);
|
|
214
|
+
}
|
|
215
|
+
return { minX, minY, maxX, maxY };
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** Pure. Route around a cluster of obstacles by computing two waypoints (above/below or left/right).
|
|
219
|
+
* Returns array of waypoints to thread between source and target anchors. */
|
|
220
|
+
static routeAroundCluster(a1, a2, obstacles) {
|
|
221
|
+
const bounds = EdgeGeometry.obstacleClusterBounds(obstacles);
|
|
222
|
+
const dx = a2.x - a1.x, dy = a2.y - a1.y;
|
|
223
|
+
const isHorizontal = Math.abs(dx) >= Math.abs(dy);
|
|
224
|
+
|
|
225
|
+
// Choose routing direction: if more horizontal, route above/below; else left/right
|
|
226
|
+
if (isHorizontal) {
|
|
227
|
+
// Route vertically around the cluster
|
|
228
|
+
const side = a1.y < bounds.minY ? -1 : 1; // above if source is above, else below
|
|
229
|
+
const routeY = side > 0 ? bounds.maxY : bounds.minY;
|
|
230
|
+
const midX = (bounds.minX + bounds.maxX) / 2;
|
|
231
|
+
return [
|
|
232
|
+
{ x: midX, y: a1.y }, // move horizontally to cluster's horizontal center
|
|
233
|
+
{ x: midX, y: routeY }, // move vertically around cluster
|
|
234
|
+
];
|
|
235
|
+
} else {
|
|
236
|
+
// Route horizontally around the cluster
|
|
237
|
+
const side = a1.x < bounds.minX ? -1 : 1; // left if source is left, else right
|
|
238
|
+
const routeX = side > 0 ? bounds.maxX : bounds.minX;
|
|
239
|
+
const midY = (bounds.minY + bounds.maxY) / 2;
|
|
240
|
+
return [
|
|
241
|
+
{ x: a1.x, y: midY }, // move vertically to cluster's vertical center
|
|
242
|
+
{ x: routeX, y: midY }, // move horizontally around cluster
|
|
243
|
+
];
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** Pure. Straight line between two anchors, unless `obstacles` (other
|
|
248
|
+
* nodes as {x,y,r}, source/target already excluded by the caller) puts
|
|
249
|
+
* one in the way. Routes around single obstacles with a perpendicular
|
|
250
|
+
* waypoint; routes around clusters by threading around the bounding box.
|
|
251
|
+
* Degrades to a plain straight line on an uncrowded graph.
|
|
252
|
+
*
|
|
253
|
+
* Note: This is 'polyline' routing only. 'curved' and 'orthogonal' modes
|
|
254
|
+
* currently do not have obstacle avoidance — they route directly regardless
|
|
255
|
+
* of obstacles. A caller needing avoidance on those modes should either:
|
|
256
|
+
* 1. Switch to 'polyline' routing, or
|
|
257
|
+
* 2. Manually add waypoints (edge.waypoints) to the edge data. */
|
|
258
|
+
static polylineEdgePath(a1, a2, obstacles = []) {
|
|
259
|
+
const blocking = EdgeGeometry.findBlockingObstacles(a1, a2, obstacles);
|
|
260
|
+
if (blocking.length === 0) {
|
|
261
|
+
return { x1: a1.x, y1: a1.y, x2: a2.x, y2: a2.y, d: `M${a1.x},${a1.y} L${a2.x},${a2.y}` };
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
let waypoints;
|
|
265
|
+
if (blocking.length === 1) {
|
|
266
|
+
// Single obstacle: use perpendicular offset (original behavior)
|
|
267
|
+
const o = blocking[0];
|
|
268
|
+
const dx = a2.x - a1.x, dy = a2.y - a1.y;
|
|
269
|
+
const len = Math.hypot(dx, dy) || 1;
|
|
270
|
+
const px = -dy / len, py = dx / len;
|
|
271
|
+
const len2 = len * len;
|
|
272
|
+
const t = ((o.x - a1.x) * dx + (o.y - a1.y) * dy) / len2;
|
|
273
|
+
const footX = a1.x + dx * t, footY = a1.y + dy * t;
|
|
274
|
+
const cross = dx * (o.y - a1.y) - dy * (o.x - a1.x);
|
|
275
|
+
const side = cross >= 0 ? -1 : 1;
|
|
276
|
+
const clearance = o.r + 12;
|
|
277
|
+
waypoints = [{ x: footX + px * clearance * side, y: footY + py * clearance * side }];
|
|
278
|
+
} else {
|
|
279
|
+
// Multiple obstacles: route around the cluster
|
|
280
|
+
waypoints = EdgeGeometry.routeAroundCluster(a1, a2, blocking);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const points = [a1, ...waypoints, a2];
|
|
284
|
+
const d = points.map((pt, i) => `${i === 0 ? 'M' : 'L'}${pt.x},${pt.y}`).join(' ');
|
|
285
|
+
return { x1: a1.x, y1: a1.y, x2: a2.x, y2: a2.y, d };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** Pure. Given `points` (an ordered polyline — anchor, any existing
|
|
289
|
+
* waypoints, anchor), finds which SEGMENT a click at `(x,y)` landed
|
|
290
|
+
* closest to and returns that segment's starting index. Since
|
|
291
|
+
* `points[0]` is the source anchor (not a stored waypoint), segment `i`
|
|
292
|
+
* is exactly where a new `edge.waypoints[i]` belongs (`Array.splice(i, 0,
|
|
293
|
+
* point)`) — see the double-click-to-add-a-bend handler in
|
|
294
|
+
* RenderEngine's drag listeners. */
|
|
295
|
+
static nearestSegmentInsertIndex(points, x, y) {
|
|
296
|
+
let bestIdx = 0, bestDist2 = Infinity;
|
|
297
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
298
|
+
const dist2 = EdgeGeometry.pointToSegmentDist2(points[i], points[i + 1], x, y);
|
|
299
|
+
if (dist2 < bestDist2) { bestDist2 = dist2; bestIdx = i; }
|
|
300
|
+
}
|
|
301
|
+
return bestIdx;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** Pure. Detect if two line segments intersect. Returns intersection point if they do, null otherwise.
|
|
305
|
+
* Used for edge-crossing visualization. */
|
|
306
|
+
static lineSegmentIntersection(p1, p2, p3, p4) {
|
|
307
|
+
const x1 = p1.x, y1 = p1.y, x2 = p2.x, y2 = p2.y;
|
|
308
|
+
const x3 = p3.x, y3 = p3.y, x4 = p4.x, y4 = p4.y;
|
|
309
|
+
|
|
310
|
+
const denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
|
|
311
|
+
if (Math.abs(denom) < 1e-10) return null; // parallel or coincident
|
|
312
|
+
|
|
313
|
+
const t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / denom;
|
|
314
|
+
const u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / denom;
|
|
315
|
+
|
|
316
|
+
if (t > 0 && t < 1 && u > 0 && u < 1) {
|
|
317
|
+
return { x: x1 + t * (x2 - x1), y: y1 + t * (y2 - y1) };
|
|
318
|
+
}
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/** Pure. Find all crossing points between a given edge path and an array of other edge paths.
|
|
323
|
+
* Returns array of {x, y, angle} crossing points. */
|
|
324
|
+
static findEdgeCrossings(edgePath, otherEdgePaths) {
|
|
325
|
+
const crossings = [];
|
|
326
|
+
const points = EdgeGeometry.pathToPoints(edgePath);
|
|
327
|
+
|
|
328
|
+
for (const otherPath of otherEdgePaths) {
|
|
329
|
+
const otherPoints = EdgeGeometry.pathToPoints(otherPath);
|
|
330
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
331
|
+
for (let j = 0; j < otherPoints.length - 1; j++) {
|
|
332
|
+
const intersection = EdgeGeometry.lineSegmentIntersection(
|
|
333
|
+
points[i], points[i + 1],
|
|
334
|
+
otherPoints[j], otherPoints[j + 1]
|
|
335
|
+
);
|
|
336
|
+
if (intersection) {
|
|
337
|
+
const angle = Math.atan2(
|
|
338
|
+
points[i + 1].y - points[i].y,
|
|
339
|
+
points[i + 1].x - points[i].x
|
|
340
|
+
);
|
|
341
|
+
crossings.push({ ...intersection, angle });
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return crossings;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/** Pure. Convert SVG path string to array of points (samples bezier curves).
|
|
350
|
+
* Used for edge-crossing detection. */
|
|
351
|
+
static pathToPoints(pathStr) {
|
|
352
|
+
const points = [];
|
|
353
|
+
const tokens = pathStr.match(/[MmLlCc]|[+-]?[\d.]+/g) || [];
|
|
354
|
+
let current = { x: 0, y: 0 };
|
|
355
|
+
let i = 0;
|
|
356
|
+
|
|
357
|
+
while (i < tokens.length) {
|
|
358
|
+
const cmd = tokens[i];
|
|
359
|
+
if (cmd === 'M' || cmd === 'm') {
|
|
360
|
+
i++;
|
|
361
|
+
const x = Number(tokens[i++]), y = Number(tokens[i++]);
|
|
362
|
+
current = cmd === 'M' ? { x, y } : { x: current.x + x, y: current.y + y };
|
|
363
|
+
points.push({ ...current });
|
|
364
|
+
} else if (cmd === 'L' || cmd === 'l') {
|
|
365
|
+
i++;
|
|
366
|
+
const x = Number(tokens[i++]), y = Number(tokens[i++]);
|
|
367
|
+
current = cmd === 'L' ? { x, y } : { x: current.x + x, y: current.y + y };
|
|
368
|
+
points.push({ ...current });
|
|
369
|
+
} else if (cmd === 'C' || cmd === 'c') {
|
|
370
|
+
i++;
|
|
371
|
+
const coords = [];
|
|
372
|
+
while (i < tokens.length && !/[MmLlCc]/.test(tokens[i])) {
|
|
373
|
+
coords.push(Number(tokens[i++]));
|
|
374
|
+
}
|
|
375
|
+
const p0 = current;
|
|
376
|
+
const p1 = cmd === 'C' ? { x: coords[0], y: coords[1] } : { x: current.x + coords[0], y: current.y + coords[1] };
|
|
377
|
+
const p2 = cmd === 'C' ? { x: coords[2], y: coords[3] } : { x: current.x + coords[2], y: current.y + coords[3] };
|
|
378
|
+
const p3 = cmd === 'C' ? { x: coords[4], y: coords[5] } : { x: current.x + coords[4], y: current.y + coords[5] };
|
|
379
|
+
|
|
380
|
+
for (let s = 1; s <= 8; s++) {
|
|
381
|
+
const t = s / 8;
|
|
382
|
+
const mt = 1 - t;
|
|
383
|
+
const pt = {
|
|
384
|
+
x: mt * mt * mt * p0.x + 3 * mt * mt * t * p1.x + 3 * mt * t * t * p2.x + t * t * t * p3.x,
|
|
385
|
+
y: mt * mt * mt * p0.y + 3 * mt * mt * t * p1.y + 3 * mt * t * t * p2.y + t * t * t * p3.y,
|
|
386
|
+
};
|
|
387
|
+
points.push(pt);
|
|
388
|
+
}
|
|
389
|
+
current = p3;
|
|
390
|
+
} else {
|
|
391
|
+
i++;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return points;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/** Pure. Returns a NEW `edge.waypoints` array with one more point added
|
|
398
|
+
* at `point`, landing in the segment nearest it along the current route
|
|
399
|
+
* sourcePos -> ...edge.waypoints -> targetPos (see nearestSegmentInsertIndex).
|
|
400
|
+
* Used by the edge context menu's "Add Waypoint Here" — hand-routing used
|
|
401
|
+
* to be reachable by double-clicking the edge line itself, but that
|
|
402
|
+
* gesture now opens `onEdgeDoubleClick`'s properties dialog instead, so
|
|
403
|
+
* adding a bend point moved to the context menu. */
|
|
404
|
+
static edgeWaypointsWithInsertion(edge, sourcePos, targetPos, point) {
|
|
405
|
+
const points = [sourcePos, ...(edge.waypoints || []), targetPos];
|
|
406
|
+
const insertIdx = EdgeGeometry.nearestSegmentInsertIndex(points, point.x, point.y);
|
|
407
|
+
const waypoints = edge.waypoints ? [...edge.waypoints] : [];
|
|
408
|
+
waypoints.splice(insertIdx, 0, { x: point.x, y: point.y });
|
|
409
|
+
return waypoints;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/** Pure. Squared distance from `(x,y)` to the closest point on segment
|
|
413
|
+
* a->b (clamped to the segment, not the infinite line) — shared by
|
|
414
|
+
* segmentIntersectsCircle's threshold test and nearestSegmentInsertIndex's
|
|
415
|
+
* plain distance comparison. */
|
|
416
|
+
static pointToSegmentDist2(a, b, x, y) {
|
|
417
|
+
const dx = b.x - a.x, dy = b.y - a.y;
|
|
418
|
+
const len2 = dx * dx + dy * dy || 1;
|
|
419
|
+
let t = ((x - a.x) * dx + (y - a.y) * dy) / len2;
|
|
420
|
+
t = Math.max(0, Math.min(1, t));
|
|
421
|
+
const cx = a.x + dx * t, cy = a.y + dy * t;
|
|
422
|
+
return (x - cx) * (x - cx) + (y - cy) * (y - cy);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/** Pure. Approximate squared distance from `(x,y)` to the polyline or
|
|
426
|
+
* cubic-bezier path described by an SVG `d` attribute. Straight, polyline,
|
|
427
|
+
* orthogonal and waypoint paths are checked exactly segment-by-segment;
|
|
428
|
+
* cubic beziers are sampled into short line segments so the result is
|
|
429
|
+
* accurate enough for a generous hit-test tolerance without parsing
|
|
430
|
+
* arbitrary SVG path syntax. */
|
|
431
|
+
static pathDistance2(d, x, y) {
|
|
432
|
+
const tokens = (d || '').match(/[MmLlCc]|-?\d+(?:\.\d+)?/g) || [];
|
|
433
|
+
let min = Infinity, current = { x: 0, y: 0 };
|
|
434
|
+
let i = 0;
|
|
435
|
+
while (i < tokens.length) {
|
|
436
|
+
const cmd = tokens[i];
|
|
437
|
+
if (/[MmLl]/.test(cmd)) {
|
|
438
|
+
i++;
|
|
439
|
+
while (i < tokens.length && !/[MmLlCc]/.test(tokens[i])) {
|
|
440
|
+
const px = Number(tokens[i]), py = Number(tokens[i + 1]);
|
|
441
|
+
if (Number.isFinite(px) && Number.isFinite(py)) {
|
|
442
|
+
if (cmd === 'M' || cmd === 'L') {
|
|
443
|
+
min = Math.min(min, EdgeGeometry.pointToSegmentDist2(current, { x: px, y: py }, x, y));
|
|
444
|
+
current = { x: px, y: py };
|
|
445
|
+
} else if (cmd === 'm' || cmd === 'l') {
|
|
446
|
+
min = Math.min(min, EdgeGeometry.pointToSegmentDist2(current, { x: current.x + px, y: current.y + py }, x, y));
|
|
447
|
+
current = { x: current.x + px, y: current.y + py };
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
i += 2;
|
|
451
|
+
}
|
|
452
|
+
} else if (cmd === 'C' || cmd === 'c') {
|
|
453
|
+
i++;
|
|
454
|
+
const coords = [];
|
|
455
|
+
while (i < tokens.length && !/[MmLlCc]/.test(tokens[i])) {
|
|
456
|
+
coords.push(Number(tokens[i]));
|
|
457
|
+
i++;
|
|
458
|
+
}
|
|
459
|
+
// Read cubic bezier triplets: c1x c1y c2x c2y x y
|
|
460
|
+
for (let k = 0; k + 5 < coords.length; k += 6) {
|
|
461
|
+
const p0 = current;
|
|
462
|
+
const p1 = cmd === 'C'
|
|
463
|
+
? { x: coords[k], y: coords[k + 1] }
|
|
464
|
+
: { x: current.x + coords[k], y: current.y + coords[k + 1] };
|
|
465
|
+
const p2 = cmd === 'C'
|
|
466
|
+
? { x: coords[k + 2], y: coords[k + 3] }
|
|
467
|
+
: { x: current.x + coords[k + 2], y: current.y + coords[k + 3] };
|
|
468
|
+
const p3 = cmd === 'C'
|
|
469
|
+
? { x: coords[k + 4], y: coords[k + 5] }
|
|
470
|
+
: { x: current.x + coords[k + 4], y: current.y + coords[k + 5] };
|
|
471
|
+
let prev = p0;
|
|
472
|
+
for (let s = 1; s <= 8; s++) {
|
|
473
|
+
const t = s / 8;
|
|
474
|
+
const mt = 1 - t;
|
|
475
|
+
const pt = {
|
|
476
|
+
x: mt * mt * mt * p0.x + 3 * mt * mt * t * p1.x + 3 * mt * t * t * p2.x + t * t * t * p3.x,
|
|
477
|
+
y: mt * mt * mt * p0.y + 3 * mt * mt * t * p1.y + 3 * mt * t * t * p2.y + t * t * t * p3.y,
|
|
478
|
+
};
|
|
479
|
+
min = Math.min(min, EdgeGeometry.pointToSegmentDist2(prev, pt, x, y));
|
|
480
|
+
prev = pt;
|
|
481
|
+
}
|
|
482
|
+
current = p3;
|
|
483
|
+
}
|
|
484
|
+
} else {
|
|
485
|
+
i++;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return min;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/** Pure. One edge's full geometry: `{x1,y1,x2,y2,d}` — `x1,y1`/`x2,y2` are
|
|
492
|
+
* each anchor's final attach point (for label placement), `d` the SVG
|
|
493
|
+
* path. Table-to-table FK links keep their own fixed left/right-column
|
|
494
|
+
* bezier (`isTableLink`, unaffected by `routing`/side pinning). Explicit
|
|
495
|
+
* `edge.waypoints` (see nearestSegmentInsertIndex) beat every auto
|
|
496
|
+
* routing style, threading the line through them in order. Otherwise, an
|
|
497
|
+
* edge picks its routing from `edge.routing` (falls back to
|
|
498
|
+
* `defaultRouting`) and its anchor sides from
|
|
499
|
+
* `edge.sourceSide`/`edge.targetSide` ('top'|'right'|'bottom'|'left',
|
|
500
|
+
* default 'auto') — the single source of truth both the initial draw
|
|
501
|
+
* (graphDiagram) and live drag frames call, so they can't drift apart. */
|
|
502
|
+
static computeEdgePath(sourceInfo, sourcePos, sourceSize, targetInfo, targetPos, targetSize, edge, defaultRouting = 'straight', obstacles = []) {
|
|
503
|
+
const isTableLink = sourceInfo?.shape === 'table' && targetInfo?.shape === 'table'
|
|
504
|
+
&& edge.fromCol != null && edge.toCol != null;
|
|
505
|
+
if (isTableLink) {
|
|
506
|
+
const y1 = NodeGeometry.tableColumnY(sourceInfo, sourcePos, sourceSize, edge.fromCol);
|
|
507
|
+
const x1 = sourcePos.x + sourceSize.w / 2;
|
|
508
|
+
const y2 = NodeGeometry.tableColumnY(targetInfo, targetPos, targetSize, edge.toCol);
|
|
509
|
+
const x2 = targetPos.x - targetSize.w / 2;
|
|
510
|
+
const mx = (x1 + x2) / 2;
|
|
511
|
+
return { x1, y1, x2, y2, d: `M${x1},${y1} C${mx},${y1} ${mx},${y2} ${x2},${y2}` };
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const sourceSide = edge.sourceSide || 'auto';
|
|
515
|
+
const targetSide = edge.targetSide || 'auto';
|
|
516
|
+
// 'auto' clips to the real box edge for rect/table nodes (see
|
|
517
|
+
// edgeAnchor's own doc comment) — a fixed circular radius is only
|
|
518
|
+
// correct for shapes actually drawn as a circle (circle/person).
|
|
519
|
+
const sourceRectBoundary = sourceInfo?.shape === 'rect' || sourceInfo?.shape === 'table';
|
|
520
|
+
const targetRectBoundary = targetInfo?.shape === 'rect' || targetInfo?.shape === 'table';
|
|
521
|
+
|
|
522
|
+
// Explicit waypoints (dragged/inserted by the user, or supplied by the
|
|
523
|
+
// caller) beat every auto-routing style: the line threads straight
|
|
524
|
+
// through each one in order, and an 'auto' anchor points at the
|
|
525
|
+
// nearest waypoint rather than at the other node.
|
|
526
|
+
if (edge.waypoints && edge.waypoints.length) {
|
|
527
|
+
const first = edge.waypoints[0], last = edge.waypoints[edge.waypoints.length - 1];
|
|
528
|
+
const d1x = first.x - sourcePos.x, d1y = first.y - sourcePos.y, dist1 = Math.hypot(d1x, d1y) || 1;
|
|
529
|
+
const d2x = targetPos.x - last.x, d2y = targetPos.y - last.y, dist2 = Math.hypot(d2x, d2y) || 1;
|
|
530
|
+
const wa1 = EdgeGeometry.nodeAnchor(sourceInfo, sourcePos, sourceSize, sourceSide, d1x / dist1, d1y / dist1, sourceRectBoundary);
|
|
531
|
+
const wa2 = EdgeGeometry.nodeAnchor(targetInfo, targetPos, targetSize, targetSide, -d2x / dist2, -d2y / dist2, targetRectBoundary);
|
|
532
|
+
const points = [wa1, ...edge.waypoints, wa2];
|
|
533
|
+
const d = points.map((pt, i) => `${i === 0 ? 'M' : 'L'}${pt.x},${pt.y}`).join(' ');
|
|
534
|
+
return { x1: wa1.x, y1: wa1.y, x2: wa2.x, y2: wa2.y, d };
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
const routing = edge.routing || defaultRouting;
|
|
538
|
+
const dx0 = targetPos.x - sourcePos.x, dy0 = targetPos.y - sourcePos.y;
|
|
539
|
+
const dist0 = Math.hypot(dx0, dy0) || 1;
|
|
540
|
+
const ux = dx0 / dist0, uy = dy0 / dist0;
|
|
541
|
+
const a1 = EdgeGeometry.nodeAnchor(sourceInfo, sourcePos, sourceSize, sourceSide, ux, uy, sourceRectBoundary);
|
|
542
|
+
const a2 = EdgeGeometry.nodeAnchor(targetInfo, targetPos, targetSize, targetSide, -ux, -uy, targetRectBoundary);
|
|
543
|
+
|
|
544
|
+
switch (routing) {
|
|
545
|
+
case 'orthogonal': return EdgeGeometry.orthogonalEdgePath(a1, a2, sourceSide, targetSide, obstacles);
|
|
546
|
+
case 'curved': return EdgeGeometry.curvedEdgePath(a1, a2);
|
|
547
|
+
case 'polyline': return EdgeGeometry.polylineEdgePath(a1, a2, obstacles);
|
|
548
|
+
case 'straight':
|
|
549
|
+
default:
|
|
550
|
+
return { x1: a1.x, y1: a1.y, x2: a2.x, y2: a2.y, d: `M${a1.x},${a1.y} L${a2.x},${a2.y}` };
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|