UNPKG

7.28 kBPlain TextView Raw
1/*
2* Copyright (C) 1998-2021 by Northwoods Software Corporation. All Rights Reserved.
3*/
4
5/*
6* This is an extension and not part of the main GoJS library.
7* Note that the API for this class may change with any version, even point releases.
8* If you intend to use an extension in production, you should copy the code to your own source directory.
9* Extensions can be found in the GoJS kit under the extensions or extensionsTS folders.
10* See the Extensions intro page (https://gojs.net/latest/intro/extensions.html) for more information.
11*/
12
13import * as go from '../release/go-module.js';
14
15/**
16 * A custom routed {@link Link} for showing the distances between a point on one node and a point on another node.
17 *
18 * Note that because this is a Link, the points being measured must be on {@link Node}s, not simple {@link Part}s.
19 * The exact point on each Node is determined by the {@link Link#fromSpot} and {@link Link#toSpot}.
20 *
21 * Several properties of the DimensioningLink customize the appearance of the dimensioning:
22 * {@link #direction}, for orientation of the dimension line and which side it is on,
23 * {@link #extension}, for how far the dimension line is from the measured points,
24 * {@link #inset}, for leaving room for a text label, and
25 * {@link #gap}, for distance that the extension line starts from the measured points.
26 *
27 * If you want to experiment with this extension, try the <a href="../../extensionsJSM/Dimensioning.html">Dimensioning</a> sample.
28 * @category Part Extension
29 */
30export class DimensioningLink extends go.Link {
31 private _direction: number = 0;
32 private _extension: number = 30;
33 private _inset: number = 10;
34 private _gap: number = 10;
35
36 /**
37 * Constructs a DimensioningLink and sets the following properties:
38 * - {@link #isLayoutPositioned} = false
39 * - {@link #isTreeLink} = false
40 * - {@link #routing} = {@link Link.Orthogonal}
41 */
42 constructor() {
43 super();
44 this.isLayoutPositioned = false;
45 this.isTreeLink = false;
46 this.routing = go.Link.Orthogonal;
47 }
48
49 /**
50 * Copies properties to a cloned DimensioningLink.
51 */
52 public cloneProtected(copy: this): void {
53 super.cloneProtected(copy);
54 copy._direction = this._direction;
55 copy._extension = this._extension;
56 copy._inset = this._inset;
57 copy._gap = this._gap;
58 }
59
60 /**
61 * The general angle at which the measurement should be made.
62 *
63 * The default value is 0, meaning to go measure only along the X axis,
64 * with the dimension line and label above the two nodes (at lower Y coordinates).
65 * New values must be one of: 0, 90, 180, 270, or NaN.
66 * The value NaN indicates that the measurement is point-to-point and not orthogonal.
67 */
68 get direction(): number { return this._direction; }
69 set direction(val: number) {
70 if (isNaN(val) || val === 0 || val === 90 || val === 180 || val === 270) {
71 this._direction = val;
72 } else {
73 throw new Error('DimensioningLink: invalid new direction: ' + val);
74 }
75 }
76
77 /**
78 * The distance at which the dimension line should be from the points being measured.
79 *
80 * The default value is 30.
81 * Larger values mean further away from the nodes.
82 * The new value must be greater than or equal to zero.
83 */
84 get extension(): number { return this._extension; }
85 set extension(val: number) { this._extension = val; }
86
87 /**
88 * The distance that the dimension line should be "indented" from the ends of the
89 * extension lines that are orthogonal to the dimension line.
90 *
91 * The default value is 10.
92 */
93 get inset(): number { return this._inset; }
94 set inset(val: number) {
95 if (val >= 0) {
96 this._inset = val;
97 } else {
98 throw new Error('DimensionLink: invalid new inset: ' + val);
99 }
100 }
101
102 /**
103 * The distance that the extension lines should come short of the measured points.
104 *
105 * The default value is 10.
106 */
107 get gap(): number { return this._gap; }
108 set gap(val: number) {
109 if (val >= 0) {
110 this._gap = val;
111 } else {
112 throw new Error('DimensionLink: invalid new gap: ' + val);
113 }
114 }
115
116 /**
117 * Constructs the link's route by modifying {@link #points}.
118 * @return {boolean} true if it computed a route of points
119 */
120 public computePoints(): boolean {
121 const fromnode = this.fromNode;
122 if (!fromnode) return false;
123 const fromport = this.fromPort;
124 const fromspot = this.computeSpot(true);
125 const tonode = this.toNode;
126 if (!tonode) return false;
127 const toport = this.toPort;
128 const tospot = this.computeSpot(false);
129 const frompoint = this.getLinkPoint(fromnode, fromport, fromspot, true, true, tonode, toport);
130 if (!frompoint.isReal()) return false;
131 const topoint = this.getLinkPoint(tonode, toport, tospot, false, true, fromnode, fromport);
132 if (!topoint.isReal()) return false;
133
134 this.clearPoints();
135
136 let ang = this.direction;
137 if (isNaN(ang)) {
138 ang = frompoint.directionPoint(topoint);
139 const p = new go.Point(this.extension, 0);
140 p.rotate(ang + 90);
141 const q = new go.Point(this.extension - this.inset, 0);
142 q.rotate(ang + 90);
143 const g = new go.Point(this.gap, 0);
144 g.rotate(ang + 90);
145 this.addPointAt(frompoint.x + g.x, frompoint.y + g.y);
146 this.addPointAt(frompoint.x + p.x, frompoint.y + p.y);
147 this.addPointAt(frompoint.x + q.x, frompoint.y + q.y);
148 this.addPointAt(topoint.x + q.x, topoint.y + q.y);
149 this.addPointAt(topoint.x + p.x, topoint.y + p.y);
150 this.addPointAt(topoint.x + g.x, topoint.y + g.y);
151 } else {
152 const dist = this.extension;
153 let r = 0.0;
154 let s = 0.0;
155 let t0 = 0.0;
156 let t1 = 0.0;
157 if (ang === 0 || ang === 180) {
158 if (ang === 0) {
159 r = Math.min(frompoint.y, topoint.y) - this.extension;
160 s = r + this.inset;
161 t0 = frompoint.y - this.gap;
162 t1 = topoint.y - this.gap;
163 } else {
164 r = Math.max(frompoint.y, topoint.y) + this.extension;
165 s = r - this.inset;
166 t0 = frompoint.y + this.gap;
167 t1 = topoint.y + this.gap;
168 }
169 this.addPointAt(frompoint.x, t0);
170 this.addPointAt(frompoint.x + 0.01, r);
171 this.addPointAt(frompoint.x, s);
172 this.addPointAt(topoint.x, s);
173 this.addPointAt(topoint.x - 0.01, r);
174 this.addPointAt(topoint.x, t1);
175 } else if (ang === 90 || ang === 270) {
176 if (ang === 90) {
177 r = Math.max(frompoint.x, topoint.x) + this.extension;
178 s = r - this.inset;
179 t0 = frompoint.x + this.gap;
180 t1 = topoint.x + this.gap;
181 } else {
182 r = Math.min(frompoint.x, topoint.x) - this.extension;
183 s = r + this.inset;
184 t0 = frompoint.x - this.gap;
185 t1 = topoint.x - this.gap;
186 }
187 this.addPointAt(t0, frompoint.y);
188 this.addPointAt(r, frompoint.y + 0.01);
189 this.addPointAt(s, frompoint.y);
190 this.addPointAt(s, topoint.y);
191 this.addPointAt(r, topoint.y - 0.01);
192 this.addPointAt(t1, topoint.y);
193 }
194 }
195
196 return true;
197 }
198}