By determining the position of the end-point objects (start object and end object), a flexible/variable alignment of the objects at the MIDDLE is possible. As an example implementation, see the 2 figures below, the position of the element is dynamically determined and the GraphRep implementation takes it into account when re-arranging the model content.
IMPLEMENTATION/PROPOSAL:Expression attributes (as hidden attributes of the relation class) are setup to dynamically determine the actual position of start and end-point. Calculation of a quotient to adjust the position of MIDDLE elments accordingly is performed. The same quotient is also used to identify whether a horizontal or vertical alignment should be done.
endX, endY, startX, startY …. Retrieve start and end object and parse X and Y coordinates
LengthA, LengthB, LengthC … Calculation of lengths of triangle (Pytagoras) used for quotient calculation in GraphRep
NumberOfObjects … simulate the objects on the relation class
endX:
1EXPR type:string expr:fixed: (replall (replall (token (replall (aval (ctobj(), "Position"), "NODE ", ""), 0, " "), "x:", ""), "cm", ""))
endY:
1EXPR type:string expr:fixed: (replall (replall (token (replall (aval (ctobj(), "Position"), "NODE ", ""), 1, " "), "y:", ""), "cm", ""))
startX:
1EXPR type:string expr:fixed: (replall (replall (token (replall (aval (cfobj(), "Position"), "NODE ", ""), 0, " "), "x:", ""), "cm", ""))
startY:
1EXPR type:string expr:fixed: (replall (replall (token (replall (aval (cfobj(), "Position"), "NODE ", ""), 1, " "), "y:", ""), "cm", ""))
LengthA (as the X Axis)
1EXPR type:double expr:fixed: (VAL aval("startX") - VAL aval("endX"))
LengthB (as the Y Axis)
1EXPR type:double expr:fixed: (VAL aval("startY") - VAL aval("endY"))
LengthC (not used, just to show Expression Functionality)
1EXPR type:double expr:fixed: (sqrt(pow(aval("LengthA"), 2) + pow(aval("LengthB"), 2)))
GRAPHREP IMPLEMENTATION
1# no shadow graphrep, since the shadow disturbs to a certain extend the alignment visually
2GRAPHREP SHADOW off
3# ready in values from the object. all elements are calculating information from the object positioning
4AVAL set-default:"3" numberOfObjects:"NumberOfObjects"
5AVAL startX:"startX"
6AVAL startY:"startY"
7AVAL endX:"endX"
8AVAL endY:"endY"
9AVAL lengthA:"LengthA" #x-axis
10AVAL lengthB:"LengthB" #y-axis
11# IMPORTANT to adjust the position of the connector marks
12SET quotient: (VAL lengthB/VAL lengthA)
13SET quotientInverse: (VAL lengthA/VAL lengthB )
14# draw the edge
15EDGE
16# draw on the middle position
17MIDDLE
18SET t:0
19# highly recommended to use a while loop, for loop crashes under certain circumstances the environment
20WHILE (t < VAL numberOfObjects) {
21 # calculate the position of the "on-connector" elements based on start and end position
22 IF (quotient >= -1 AND quotient <= 1) {
23 # case: vertically aligned
24 SET x:0
25 SET y: (((VAL numberOfObjects-1)/2)-t)
26 }
27 ELSE {
28 # case: hoirzontal aligned
29 SET x: (((VAL numberOfObjects-1)/2)-t)
30 SET y:0
31 }
32 # if more than 1 object, draw the connecting lines to the connector marks
33 IF (VAL numberOfObjects > 1) {
34 IF (quotient >= -1 AND quotient <= 1) {
35 POLYLINE 3 x1:0.5cm y1:0cm x2:0.5cm y2: (CM y) x3: (CM x) y3: (CM y)
36 POLYLINE 3 x1:-0.5cm y1:0cm x2:-0.5cm y2: (CM y) x3: (CM x) y3: (CM y)
37 }
38 ELSE {
39 POLYLINE 3 x1:0cm y1:0.5cm x2: (CM x) y2:0.5cm x3: (CM x) y3: (CM y)
40 POLYLINE 3 x1:0cm y1:-0.5cm x2: (CM x) y2:-0.5cm x3: (CM x) y3: (CM y)
41 }
42 }
43 # draw the elements on the connector
44 FILL color:red
45 ELLIPSE x: (CM x) y: (CM y) rx:0.2cm ry:0.2cm
46 # write numbering in object
47 FONT h:8pt
48 TEXT (t) x: (CM x) y: (CM y) w:c h:c
49 # update while counter
50 SET t: (t + 1)
51}
52# draw the connector marks
53FILL color:white
54
55IF (quotient >= -1 AND quotient <= 1) {
56 SET yMarkPos: (quotient*0.5)
57 SET yMarkNeg: (-1*quotient*0.5)
58 ELLIPSE rx:0.1cm ry:0.1cm x:0.5cm y: (CM yMarkPos)
59 ELLIPSE rx:0.1cm ry:0.1cm x:-0.5cm y: (CM yMarkNeg)
60}
61ELSE {
62 SET xMarkPos: (quotientInverse*0.5)
63 SET xMarkNeg: (-1*quotientInverse*0.5)
64 ELLIPSE rx:0.1cm ry:0.1cm y:0.5cm x: (CM xMarkPos)
65 ELLIPSE rx:0.1cm ry:0.1cm y:-0.5cm x: (CM xMarkNeg)
66
67}
68# DEBUG to display the quotient calculated
69#TEXT (STR quotient)
LIMITATIONS:- Currently bendpoints are not considered in the implementation, in case bendpoints are created by the user, a strategy to eighter read-out the position of the bend-point and compare to the MIDDEL position has to be added
- Merging/Parallel markers: the repositioning is not smooth but happens when the user releases the move action and the panel is drawn.