Skip to content

Commit

Permalink
docs: explain mxGraph perimeter and projection (#2096)
Browse files Browse the repository at this point in the history
It references the `maxGraph` documentation and explains how we configure and use perimeters in `bpmn-visualization`.

---------

Co-authored-by: Souchet Céline <[email protected]>
  • Loading branch information
tbouffard and csouchet authored Feb 4, 2025
1 parent acab3de commit 873643d
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 0 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
101 changes: 101 additions & 0 deletions docs/contributors/mxgraph-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,107 @@ Check the [GitHub Pull Request #291](https://github.com/process-analytics/bpmn-v
to see various positioning methods in action.


#### Terminal Points and Perimeters

**Note**: All SVG files from this paragraph are generated from this [draw.io file](resources/mxGraph-perimeter.drawio).

##### Information from mxGrapĥ

`mxGraph` doesn't provide details about the Perimeters concept in the documentation. However, it is available in the `maxGraph` documentation about the [Perimeters](https://maxgraph.github.io/maxGraph/docs/usage/perimeters).

Here are some tips to switch from `maxGraph` to `mxGraph` concepts.

- **Cell Style Differences**:
- `mxGraph`: Style is a string.
- `maxGraph`: Style is an object.
- See [migration guide](https://maxgraph.github.io/maxGraph/docs/usage/migrate-from-mxgraph/#styling) from `mxGraph` to `maxGraph` for details.
- **Orthogonal Projection**:
- `mxGraph`: `style[mxgraph.mxConstants.STYLE_ORTHOGONAL] = 1;`
- `maxGraph`: `style.orthogonal = true;`
- **`mxGraph` Examples**: [All Examples](https://jgraph.github.io/mxgraph/javascript/examples/index.html), including [Orthogonal Example](https://jgraph.github.io/mxgraph/javascript/examples/orthogonal.html).


##### Perimeters in `bpmn-visualization`

- **Style Configuration**: Perimeters are set in [StyleConfigurator](../../src/component/mxgraph/config/StyleConfigurator.ts).
- **Default Perimeters**: `mxGraph` provides rectangle, ellipse, and diamond perimeters, which are sufficient for BPMN shapes.
- **Orthogonal Projection**: Not used due to past side effects ([#349](https://github.com/process-analytics/bpmn-visualization-js/issues/349), [#295](https://github.com/process-analytics/bpmn-visualization-js/issues/295), [#295#comment](https://github.com/process-analytics/bpmn-visualization-js/issues/295#issuecomment-904336449), [#1399](https://github.com/process-analytics/bpmn-visualization-js/pull/1399)).
- **Visual Tests**: Extensive tests for associations, message, and sequence flows with various edge configurations, covering:
- Edges without waypoints
- Edges with some waypoints producing simple or complex paths
- Terminal waypoints inside or outside shapes
- Terminal waypoints outside shapes without intersection of the flow segment with the shape


###### Perimeter Impact on Edges and Markers

In BPMN source, most BPMN edges include waypoints, which the BPMN specification strongly recommends.
Some modelers don't set the terminal points on the visual perimeter of the shapes, causing side effects on the last segment of the edge and its markers when using `mxGraph` perimeters:
1. **Final Waypoint Inside Shape**: An arrow may be displayed inside the terminal element ([#715](https://github.com/process-analytics/bpmn-visualization-js/issues/715)).
2. **Marker Misalignment With Original Last Edge Segment**: A new segment is created to connect the edge to the shape perimeter. This new segment is not always aligned with the original segment, which creates a visual glitch like in the following screenshots 👇

| Positioning | Rendering |
|----------------------------------------------------------|--------------------------------------------------------|
| ![](images/mxgraph-perimeter/markers-01-positioning.png) | ![](images/mxgraph-perimeter/markers-02-rendering.png) |


###### Workaround used to Fix the Problem

The current implementation was done in [PR #1868](https://github.com/process-analytics/bpmn-visualization-js/pull/1868).
It solves the previous problem by
- Ignoring perimeters if the edges have waypoints.
- Using the perimeters only if the edge has no waypoints.

This logic is implemented in `BpmnGraphView` (extends `mxGraphView`), overriding `getFloatingPoint`:
- With waypoints: Ignore the perimeter. Use the first and the last non-null value in the `points` array as endpoint.
- Without waypoints: Use perimeter calculation.

**Reminder about `mxGraph` terminal waypoints**

The points of the cell in the model are copied into the `abspoints` array property of the edge `state` instance, starting and ending with `null`.
They will later be replaced by the computed terminal points in [`mxGraphView.updateFloatingTerminalPoints`](https://github.com/jgraph/mxgraph/blob/v4.2.2/javascript/src/js/view/mxGraphView.js#L1547) which involves the perimeter if it is defined.

⚠️ So, if the edge has no waypoints, the array will contain 2 `null' values.

**Limitations of the current implementation**

Edges may appear too short, because no additional points are calculated on the perimeter of the target shape.

The screenshots below illustrate the problem and the effect of using a perimeter. The edges have no `EdgeStyle` (`STYLE_EDGE` is not set).
These images are from [PR #1765](https://github.com/process-analytics/bpmn-visualization-js/pull/1765#issuecomment-1018508771) (2 screenshots at the end) and show the test diagram `flows.sequence.04.waypoints.03.terminal.outside.shapes.02.segments.no.intersection.with.shapes.bpmn`.

| Without Projection (no perimeter) | Default (Projection to center) | Orthogonal Projection (`STYLE_ORTHOGONAL` = 1) |
|---------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ![without projection](images/mxgraph-perimeter/flows.sequence.04.waypoints.03.terminal.outside.shapes.02.segments.no.intersection.with.shapes-snap.png) | ![seq_flow_outside_no_segment_connector_01_default_projection_to_center](https://user-images.githubusercontent.com/27200110/150537056-68d7410b-9675-4bcc-9d01-ce2562965ffc.png) | ![seq_flow_outside_no_segment_connector_02_orthogonal_projection](https://user-images.githubusercontent.com/27200110/150537058-65e645c1-fb80-4f54-8da9-b0c819bbbc7a.png) |


###### Potential future enhancements

Align edges by extending them to intersect with the shape perimeter instead of adding a misaligned segment.

- **Intersect with Perimeter**: Calculate the edge endpoint to meet the shape perimeter, preventing alignment issues.
- **Fallback to `mxGraph` Perimeter**: If no intersection is found, default to `mxGraph`'s perimeter behavior.


| **Edge Markers: Projection vs Intersection** | **Perimeter Usage When No Intersection** |
|-------------------------------|------------------------------|
| ![](images/mxgraph-perimeter/markers-03-projection-vs-intersection.png) | ![](images/mxgraph-perimeter/perimeter-no-intersection.png) |


**Potential fixes**

This solution would make it possible to implement the following points:
- ["Ensure that the terminal waypoints are on the shape perimeter"](https://github.com/process-analytics/bpmn-visualization-js/issues/1870)
- ["Restore the experimental pools/subprocess live collapsing"](https://github.com/process-analytics/bpmn-visualization-js/issues/1871)


**Additional considerations**

- **Foreground/Background Positioning**: `mxGraph` supports foreground/background positioning ([PR #1863](https://github.com/process-analytics/bpmn-visualization-js/pull/1863), [Issue #1870](https://github.com/process-analytics/bpmn-visualization-js/issues/1870)). [bpmn-js](https://github.com/bpmn-io/bpmn-js/) places shapes in the foreground and edges in the background.
- **SVG Q (quadratic)**: Enabling `rounded` in the edge style caused an overlay misalignment at the edge center due to `mxPolyline.paintLine`. See `mxShape.addPoints` for details ([PR #1207](https://github.com/process-analytics/bpmn-visualization-js/pull/1207#issuecomment-810357733)).
- **Intersection Detection**: The [path-intersection](https://github.com/bpmn-io/path-intersection) library could be useful for handling edge intersections.


## Overlays

We are hacking mxCellOverlays which originally only supports image shape. This lets us use custom shapes.
Expand Down
1 change: 1 addition & 0 deletions docs/contributors/resources/mxGraph-perimeter.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<mxfile host="Electron" modified="2022-04-06T13:05:08.207Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/17.2.4 Chrome/96.0.4664.174 Electron/16.1.0 Safari/537.36" etag="epoizijUXisM-Gp8Z8wd" version="17.2.4" type="device" pages="7"><diagram id="RNMhzFc4bVhtCsQH0jFF" name="context">7Vddk5owFP01PjojBFl9VNduH9qZ7thOp48puUJqIDQEhf31DZAAQddZbe33E8m5yb0395x8MEKruHgQOI3ecgJs5E5IMUL3I9d10HSiPhVSNsh8PmuAUFCiB3XAhj6BBvW8MKcEMmug5JxJmtpgwJMEAmlhWAh+sIdtObOjpjiEI2ATYHaMfqRERg06c+86/DXQMDKRHX/eWD7jYBcKnic6XsITaCwxNm70GrMIE37oQWg9QivBuWxacbECVpXVVKyZ9+oZa5uygES+ZEJePvrRbrkOPmDicVz6T1/ej1HjZY9Zrkuhk5WlqQ0kZFGVWPXq1aFlJGOmeo5q1kuHKsJE9TIp+K6tIFLIcZI6byAWIzrlB+AxSFGqAYeOB6OuqEeBwQQwLOne5hFrOYStuzbCO05VJu7ESNfTfrRwHX9iu8h4LgLQs/rVHThyB468gR+JRQjyyI9q9FbdQTV3F/Do3ZBH90/g0a7+tSw66LyfG7M4/aEs/u6ctSej2Xt3/pV7Dw03sf9TafP/Mdqc89W+mrYh/8/QpgqJy96wtBqQfS+x4zdivJ1Nufs422ymwX5MPp28HX2myrnc8nolHcP+15wbwzirHzgLNcDx0qIzqlaov7UXagD1Nkihet8ozkEYs8qZDqcorIlt4IHQJBTSVldzmK8446JT35YyNoAwo2GiujoHtNyDkFS9kRbaEFNCqjDLQ0QlbFIcVDEP6kX4cg1XPqE4q2KjjsGR7sx1v6dy/4TK0eDI7gva0selYjh1xTacELof0nQjfaQgqFrNhRJpYSvRv1Y4nm8Jx/3Fujl1qd9EJPX98P/oqI4KSwDIuZUAVLf7f2sune7/GK2/AQ==</diagram><diagram name="center projection" id="7wKxT-a-TJRUQJqu_FCP">7ZZbb5swFMc/DY+TwE5zeVzSLpN2UaZOmvY0ufgUrBgbmUMu+/Qz2IRLtq5J00qd9gT+c/w35/yODQFdZLulYXn6SXOQAQn5LqDXASERvQrtpVL2TpnNpk5IjOA+qBVuxU/wop+XlIJD4TQvodYSRV70ZsdaKYixpzFj9LYfdq9lf9WcJXAk3MZMHqvfBMfUqVMyafX3IJK0WTkaz9yTOxavE6NL5ddTWoF7krHGxidUpIzrbUeiNwFdGK3R3WW7BciqrE3FZprh9/nnL2pOUWK83C7NhzfO7N0pUw7JGVB4WWvirDdMlr6SPlfcN6UFxd9WhOyoLg6dp5hJO4rsbV05qFYI7ahAo9cHANQqj3xznyHwHmWfxxJ0Bmj2NmDbsm06Nu1gbTQDkqHY9HuD+RZLDnaHFVZa2NcjYbMdRt7Hb4ZoHPYtCl2aGPysbskHRmRgNBr4IDMJ4JGPvelk3Uo10BPg0meES14r3AGSc9FG9GGfZ0Y7uijaVwmSENrfpRN65i6lA6MxfVGWV/9Z2m35MIKzWQ6b4g8sbXXZvhOWVwHFE2l/LfP1j/XdNL4X1yr9yFbFxviP9Im0OSvSmnDUR1/pK4YIRtUKCelvT+p/oEX+duA+vkMGH/fJpU5uO2x/Bl14+7NNb34B</diagram><diagram name="orthogonal projection" id="5u9HompIC729Kqdd-Od9">7ZZdT8MgFIZ/TS9NWtimvdQ550c0S5Zo4h2WY2mkZVL2+eulha6l83PZTGa8Grw9vKfnPMDq4X66GEoyYbeCAveQTxcePvcQCnDX1z+FsjRKGJ4YIZYJtUG1ME5WYEW7Lp4mFHKjWUkJwVUyyZ3VkcgyiJSjESnF3A17FtzNOiExbAjjiPBN9SGhihn1BB3X+iUkMasyB73QPHki0UssxTSz+TKRgXmSksrGFpQzQsW8IeGBh/tSCGVG6aIPvGhr1bGbV3591Q2fwjvGxOpePfYH/pExu/jJknVxEjK1W2tkrGeET20nba1qWbUWMnpaENKzsjn4jKmU61mgh2XnoMjg61mupHhZA8Ba+eab2wqBOpRtHUMQKSi51AHzmm21Y1kDa6VJ4EQlM3dvELvF4rXdOsNIJPr1kF8dh8rHHoag57sWuZjKCOyqZstbRqhl1Gn5KCJjUBs+etCoupZKoD+Ai/cIFx0q3I6LZFu0Af7cZ89oOztFe5AgEcLuKT3GW55S3DLq4V9l2f1nqY/l5wi2ZtneFB+w1N0ly0bYpAjI90G7tw1tSnJWEg5c9IU+IkqBzEoF+fjdm/oPbJGvLtxvX9xh68892NXNraf1x6AJrz+28eAN</diagram><diagram name="marker positionning" id="hUysYIEV5oSPOwoVvPX7">5VbbjpswEP2aPCYCmyTksbl0W6mrRo321jcXJuDG4Mg4IfTra7C5ONlLibpSpT7BHI+PmTlngAFeJKcbQfbxLQ+BDZATngZ4OUDIxWNHXUqk0Mhs5msgEjQ0SS2wob/AgGZfdKAhZBozkOScSbrPrN0BT1MIpIURIXhup205s0/dkwgugE1A2CX6QEMZa9RH0xb/BDSK65PdyUyv/CDBLhL8kJrzUp6CXklITWMKymIS8rwD4dUALwTnUt8lpwWwsq11x777if/F263H29Xd5+H9Zr5+QENN9rHPlqY4Aan8u9RIUx8JO5hOmlplUbcW0vBDqZCKqubgeSwTpiJX3Vadg/IER0WZFHzXCIAV8odPbiqE0FLZ1HEDPAEpCpWQt9rWjo07staYAEYkPdreIMZiUUPXnLDmVD0ecsw4YMfwmGHAnmNTZPwgAjC7ui0/I/LOiBor1USSiAjkBZG66ZTdQpWiz6t73N2uJsHd12/JYfrzcXifr0RWt7WfuiHJ4kpR15a6xNdEShBphSAHX0iOLiyhdBfFo6GogqdyZTSuw+Wpm7ksTNTPOLqPr3TC+acMhjzbF+7sSoPhMyJ0TvTOBnPeNpgUlKRRGc3zmErY7ElQLuXqQ2QbbMtTab4srlcZSaom89JtuLTLljK24IyL1qv9XHIEIeH0qv61QP4Lg9vxh/+MPybeCE1edoPV/r69fs9XNepOqjPy/LE9rd4UvzGvVbQGQVWxIP6LIT5/uY+vHGI0vW6IldSk6KTty4Ss35irsP2B0entDyJe/QY=</diagram><diagram name="marker rendering" id="KBc98q3cc0dlVpS0iDJ2">zVXRbpswFP0aHlsRGxLyuKRdp0mV2CK126MLt2DV2MiYAPv62dgESNa1TJu0vMT3XPuYe8694OF90d5JUub3IgXmIT9tPXzjIbTCoa//DNJZZLuNLJBJmrpNI3CgP8CB7lxW0xQqizlICcEULavZ6URwDomaYURK0cy3PQs2v7UkGVwAh4SwS/SRpiq3aIQ2I/4JaJYPN6/WW5t5IslLJkXN3X1ccLCZggw0rqAqJ6loJhC+9fBeCqHsqmj3wIysg2L8igbZ/dfPDw+PdYxiGkVf4itL9nHJkVNxErj6u9TIUh8Jq52SrlbVDdICTz8Yh3TUi4N3uSqYjlZ62SsH5gZfR5WS4uVkANbIO5/cVQjpzGVXxx2IApTs9IZm9Hbo2Hxi64BJYETR47w3iGux7ER3uiEWVD8e8t04YN/xuGHAgT+nqEQtE3CnppKfEQVnRKdWGogUkRmoCyK9mJQ9Qr2jC9wN3nZXSUp4ZqJdk1MFh5IkJtXo98Tc6mfBlRv8VdBbr7TIghunQ5OnjO0FE7In1hqa3+IWOIJU0P62CVwWRa+IO2mS6BdNsg6u0fr1lph5sFTw8B+Ok5ZipyWU3TeTvg6icAC+W2CDB+CmdQw26qZRDJLqYkE6cJk9tmHfbrn/ZJLR+QCGfzjJaHNGtH3fJGurSTfZVpoN1bJZ1+H4kbHbx484vv0J</diagram><diagram id="ne7omDIuoBgSVefN5mzM" name="no intersection">7VlNc9owEP01HNuxJJvAMZA07XQ6yZSmzOQmbIGVCMsji6/++kpYxpZwAiUF4klOWM/SSnpvdyXWLdSfLm8ETuMfPCKsBb1o2UJXLQgBgIH60cgqRzoI5sBE0Mh0KoEB/UMM6Bl0RiOSWR0l50zS1AZDniQklBaGheALu9uYM3vWFE/IFjAIMdtGhzSSsdkFvCjxr4RO4mJm0O7mb6a46Gx2ksU44osKhK5bqC84l/nTdNknTJNX8JKP+/LM283CBElkzYD7jIjb0aPmBHoMj5Qu6075sMLK7dWQ+hfD+PLmV/e+/zRZDr7NP8HN6jazZnJVMLKIqSSDFIe6vVCqt1AvllNtHqhHnKW5DmO6JGqW3pgy1ueMC4UlPFGjetkTkaFmx1MNoxwerSfQSL7EORGSLJ/dLKgs8obwKZFipbqYAbBjWC/czjQXFQ0NFFfkKzBsvGayMVwSqx4MLUWzQnW9VrUsmz3NMZuRqjSvoNqmUndJiaBqB0STz+iYMJqQuxL7H1SfjOn9aEW7aSVJdKlTQ+mQFVIFnyWRZrPiiiTaShI72ansP6jZf4EJwrCkc9t8HSlmhjtOE1nxc2SzDwKH14zPREjMqGo6cQyBtm3ItSOxmBC5ZWct0WbXh6vmH6JahLN4rRSwJdT4HZbKw5M1Aj2kk44U/GmTxOH7lRpBxxA8mta/RYi86OHnVa/b+f4YXj6sktE+ie+taK0WtSZ1Vxo/l090A0vJizcf/LUOcVDwNzZl+8AmG/mHxrFvG4KuoSPLFjQnjhuvdeA5hsBptW5/aL1La+R5n8HLIjUlsrvvKiEHXec+1D40SJ2LlWvn2PeqBl2szpaQO26QAtRQteEeajNG00yr/K+VBKtCU1PBMXO/pm7gO4UDWIRhxRP8Gk9wc+EhlYN6RjsNZ9QtxZyf0T0OEhHz6WiW7WZ0F4FHqSO2nX9GAJyZ0iLpfCT5ExzobSegts6KI+d4uMeJ/rbjxz9d/Khm+TElV6D8JIWu/wI=</diagram><diagram name="projection vs intersection" id="MDurigiudHay89gO_hJH">7VhRb5swEP41eWxkbCDJY5u06TZVi5JJbZ8mFxywCpgZp4T9+hkwAUO2LDRpVW1P4T7bd/F93/kMAzQNt3OOY/+OuSQYQOBuB2g2gNAwoCV/ciQrkTGCJeBx6qpJNbCiP4kCgUI31CVJiSlIMBYIGifaaodFEXGEhmHOWapPW7NAjxpjj3SAlYODLnpPXeGrXcBRjd8S6vlVZMOelCNP2Hn2ONtEKl7EIlKOhLhyozaU+NhlaQNC1wM05YyJ8incTkmQp7XK2PwL/jyylpNovdykdgLi+wvnonR2c8yS3eY4icRpXSuWX3CwUZlUexVZlVoSuZc5Q9IqkoOufBEG0jLkY5E5kkcA0koEZ887ApBESm/E7bB3YCvGLr9SsoSFRPBMrktrbi3Fit+gtcI4CbCgL3pMrCTm7dztIiwYlf8GgqocJsqPKgaIgO4iYRvuELWqmfKWI4R0R3bLj8DcI6LjRz40dl1DBaFHkIv6kOvixC8INXSmc3yBhSA8KhAIUIdx2FGEZJlnD8pFYTzmI0OrMmfb5sxZpqxX6UaePUVi/zDPfFd9tWQx7ikv2PJjtB2dWV/mYX0JTnHk5dZV6lNBVjF28qFUtiFdX2sWCdVXDLPQkZA5ZrnYUK6WNQ2CKQsYr6WqwhMuyLaHTLr0V15GrbxWXa4hj/EeedjmENq/F4OW/mNzbZ3xoIbNQgVDc2zpxWqO0IFyLawF4VRulvB/oYZbLcIwe9awYferYck0zhrT4nxC8soq92++f/IexDK8xLff7hZzy//xVd0q/l8RNNoseKIrgm2/1RVhL7nG+18RPib/5onq3zp0kJxZAH/xAnCSHg72t3D1PoifimDgjE3dAq1Eg/FbNvW9ye91QT+iqX/I0jLhqUrrUI2esbVKs/4wUE6vP7yg618=</diagram></mxfile>

0 comments on commit 873643d

Please sign in to comment.