circuitscript 0.0.22 → 0.0.25
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/dist/cjs/BaseVisitor.js +487 -0
- package/dist/cjs/SemanticTokenVisitor.js +218 -0
- package/dist/cjs/SymbolValidatorVisitor.js +233 -0
- package/dist/cjs/antlr/CircuitScriptLexer.js +302 -0
- package/dist/cjs/antlr/CircuitScriptParser.js +5128 -0
- package/dist/cjs/antlr/CircuitScriptVisitor.js +7 -0
- package/dist/cjs/draw_symbols.js +819 -0
- package/dist/cjs/execute.js +778 -0
- package/{src/export.ts → dist/cjs/export.js} +34 -56
- package/dist/cjs/fonts.js +4 -0
- package/dist/cjs/geometry.js +450 -0
- package/dist/cjs/globals.js +60 -0
- package/dist/cjs/helpers.js +269 -0
- package/dist/cjs/index.js +31 -0
- package/{src/layout.ts → dist/cjs/layout.js} +421 -1002
- package/dist/cjs/lexer.js +111 -0
- package/dist/cjs/logger.js +17 -0
- package/dist/cjs/main.js +82 -0
- package/dist/cjs/objects/ClassComponent.js +145 -0
- package/dist/cjs/objects/ExecutionScope.js +135 -0
- package/dist/cjs/objects/Frame.js +22 -0
- package/{src/objects/Net.ts → dist/cjs/objects/Net.js} +9 -24
- package/dist/cjs/objects/ParamDefinition.js +42 -0
- package/dist/cjs/objects/PinDefinition.js +31 -0
- package/dist/cjs/objects/PinTypes.js +11 -0
- package/dist/cjs/objects/Wire.js +9 -0
- package/dist/cjs/objects/types.js +15 -0
- package/dist/cjs/parser.js +70 -0
- package/dist/cjs/regenerate-tests.js +23 -0
- package/dist/cjs/render.js +155 -0
- package/{src/server.ts → dist/cjs/server.js} +15 -21
- package/dist/cjs/sizing.js +105 -0
- package/{src/utils.ts → dist/cjs/utils.js} +25 -35
- package/dist/cjs/validate.js +81 -0
- package/dist/cjs/visitor.js +844 -0
- package/dist/esm/BaseVisitor.mjs +488 -0
- package/dist/esm/SemanticTokenVisitor.mjs +215 -0
- package/dist/esm/SymbolValidatorVisitor.mjs +222 -0
- package/dist/esm/antlr/CircuitScriptLexer.mjs +276 -0
- package/dist/esm/antlr/CircuitScriptParser.mjs +5038 -0
- package/{build/src/antlr/CircuitScriptVisitor.js → dist/esm/antlr/CircuitScriptVisitor.mjs} +8 -3
- package/{build/src/draw_symbols.js → dist/esm/draw_symbols.mjs} +78 -33
- package/{build/src/execute.js → dist/esm/execute.mjs} +59 -60
- package/{build/src/export.js → dist/esm/export.mjs} +2 -2
- package/{build/src/geometry.js → dist/esm/geometry.mjs} +31 -15
- package/dist/esm/helpers.mjs +252 -0
- package/dist/esm/index.mjs +15 -0
- package/{build/src/layout.js → dist/esm/layout.mjs} +19 -11
- package/{build/src/lexer.js → dist/esm/lexer.mjs} +10 -10
- package/{build/src/main.js → dist/esm/main.mjs} +9 -14
- package/{build/src/objects/ClassComponent.js → dist/esm/objects/ClassComponent.mjs} +6 -3
- package/{build/src/objects/ExecutionScope.js → dist/esm/objects/ExecutionScope.mjs} +1 -0
- package/{build/src/objects/PinDefinition.js → dist/esm/objects/PinDefinition.mjs} +1 -1
- package/dist/esm/objects/types.mjs +12 -0
- package/dist/esm/parser.mjs +64 -0
- package/{build/src/regenerate-tests.js → dist/esm/regenerate-tests.mjs} +1 -1
- package/{build/src/render.js → dist/esm/render.mjs} +7 -24
- package/{build/src/sizing.js → dist/esm/sizing.mjs} +22 -8
- package/{src/main.ts → dist/esm/validate.mjs} +31 -62
- package/dist/esm/visitor.mjs +838 -0
- package/dist/types/BaseVisitor.d.ts +69 -0
- package/dist/types/SemanticTokenVisitor.d.ts +36 -0
- package/dist/types/SymbolValidatorVisitor.d.ts +61 -0
- package/{build/src → dist/types}/antlr/CircuitScriptLexer.d.ts +28 -27
- package/dist/types/antlr/CircuitScriptParser.d.ts +719 -0
- package/{build/src → dist/types}/antlr/CircuitScriptVisitor.d.ts +69 -59
- package/{build/src → dist/types}/draw_symbols.d.ts +11 -2
- package/{build/src → dist/types}/execute.d.ts +6 -9
- package/{build/src → dist/types}/geometry.d.ts +5 -1
- package/dist/types/helpers.d.ts +40 -0
- package/dist/types/index.d.ts +15 -0
- package/{build/src → dist/types}/layout.d.ts +10 -10
- package/{build/src → dist/types}/lexer.d.ts +2 -2
- package/{build/src → dist/types}/objects/ClassComponent.d.ts +2 -2
- package/{build/src → dist/types}/objects/ExecutionScope.d.ts +4 -1
- package/{build/src → dist/types}/objects/PinDefinition.d.ts +1 -1
- package/{build/src → dist/types}/objects/types.d.ts +5 -0
- package/dist/types/parser.d.ts +25 -0
- package/{build/src → dist/types}/render.d.ts +1 -1
- package/{build/src → dist/types}/sizing.d.ts +3 -1
- package/dist/types/validate.d.ts +2 -0
- package/dist/types/visitor.d.ts +80 -0
- package/libs/lib.cst +0 -2
- package/package.json +38 -15
- package/.editorconfig +0 -15
- package/.eslintignore +0 -1
- package/.eslintrc.json +0 -27
- package/.gitlab-ci.yml +0 -81
- package/.prettierignore +0 -8
- package/.prettierrc +0 -16
- package/__tests__/expectedResults.ts +0 -657
- package/__tests__/helpers.ts +0 -82
- package/__tests__/parseScripts.ts +0 -593
- package/__tests__/renderData/script1.cst +0 -58
- package/__tests__/renderData/script1.cst.svg +0 -1
- package/__tests__/renderData/script2.cst +0 -16
- package/__tests__/renderData/script2.cst.svg +0 -1
- package/__tests__/renderData/script3.cst +0 -30
- package/__tests__/renderData/script3.cst.svg +0 -1
- package/__tests__/renderData/script4.cst +0 -54
- package/__tests__/renderData/script4.cst.svg +0 -1
- package/__tests__/renderData/script5.cst +0 -23
- package/__tests__/renderData/script5.cst.svg +0 -1
- package/__tests__/renderData/script6.cst +0 -28
- package/__tests__/renderData/script6.cst.svg +0 -1
- package/__tests__/renderData/script7.cst +0 -26
- package/__tests__/renderData/script7.cst.svg +0 -1
- package/__tests__/renderData/script8.cst +0 -37
- package/__tests__/renderData/script8.cst.svg +0 -1
- package/__tests__/testCLI.ts +0 -68
- package/__tests__/testMathOps.ts +0 -36
- package/__tests__/testMergeWires.ts +0 -141
- package/__tests__/testParse.ts +0 -263
- package/__tests__/testRender.ts +0 -38
- package/build/src/antlr/CircuitScriptLexer.js +0 -287
- package/build/src/antlr/CircuitScriptParser.d.ts +0 -674
- package/build/src/antlr/CircuitScriptParser.js +0 -4841
- package/build/src/helpers.d.ts +0 -1
- package/build/src/helpers.js +0 -73
- package/build/src/objects/types.js +0 -6
- package/build/src/parser.js +0 -69
- package/build/src/visitor.d.ts +0 -133
- package/build/src/visitor.js +0 -1154
- package/documentation.md +0 -238
- package/examples/example_arduino_uno.cst +0 -1146
- package/examples/example_garden_pump.cst +0 -567
- package/examples/lib.cst +0 -185
- package/jest.config.js +0 -23
- package/refresh.html +0 -42
- package/server.cjs +0 -50
- package/src/antlr/CircuitScript.g4 +0 -209
- package/src/antlr/CircuitScriptLexer.ts +0 -317
- package/src/antlr/CircuitScriptParser.ts +0 -4979
- package/src/antlr/CircuitScriptVisitor.ts +0 -420
- package/src/draw_symbols.ts +0 -1085
- package/src/execute.ts +0 -1227
- package/src/fonts.ts +0 -1
- package/src/geometry.ts +0 -638
- package/src/globals.ts +0 -67
- package/src/helpers.ts +0 -114
- package/src/lexer.ts +0 -151
- package/src/logger.ts +0 -17
- package/src/objects/ClassComponent.ts +0 -223
- package/src/objects/ExecutionScope.ts +0 -201
- package/src/objects/Frame.ts +0 -20
- package/src/objects/ParamDefinition.ts +0 -49
- package/src/objects/PinDefinition.ts +0 -49
- package/src/objects/PinTypes.ts +0 -7
- package/src/objects/Wire.ts +0 -19
- package/src/objects/types.ts +0 -66
- package/src/parser.ts +0 -106
- package/src/regenerate-tests.ts +0 -25
- package/src/render.ts +0 -260
- package/src/sizing.ts +0 -96
- package/src/visitor.ts +0 -1691
- package/tsconfig.json +0 -27
- package/tsconfig.release.json +0 -8
- /package/{build/src/fonts.js → dist/esm/fonts.mjs} +0 -0
- /package/{build/src/globals.js → dist/esm/globals.mjs} +0 -0
- /package/{build/src/logger.js → dist/esm/logger.mjs} +0 -0
- /package/{build/src/objects/Frame.js → dist/esm/objects/Frame.mjs} +0 -0
- /package/{build/src/objects/Net.js → dist/esm/objects/Net.mjs} +0 -0
- /package/{build/src/objects/ParamDefinition.js → dist/esm/objects/ParamDefinition.mjs} +0 -0
- /package/{build/src/objects/PinTypes.js → dist/esm/objects/PinTypes.mjs} +0 -0
- /package/{build/src/objects/Wire.js → dist/esm/objects/Wire.mjs} +0 -0
- /package/{build/src/server.js → dist/esm/server.mjs} +0 -0
- /package/{build/src/utils.js → dist/esm/utils.mjs} +0 -0
- /package/{build/src → dist/types}/export.d.ts +0 -0
- /package/{build/src → dist/types}/fonts.d.ts +0 -0
- /package/{build/src → dist/types}/globals.d.ts +0 -0
- /package/{build/src → dist/types}/logger.d.ts +0 -0
- /package/{build/src → dist/types}/main.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Frame.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Net.d.ts +0 -0
- /package/{build/src → dist/types}/objects/ParamDefinition.d.ts +0 -0
- /package/{build/src → dist/types}/objects/PinTypes.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Wire.d.ts +0 -0
- /package/{build/src → dist/types}/regenerate-tests.d.ts +0 -0
- /package/{build/src → dist/types}/server.d.ts +0 -0
- /package/{build/src → dist/types}/utils.d.ts +0 -0
package/src/draw_symbols.ts
DELETED
|
@@ -1,1085 +0,0 @@
|
|
|
1
|
-
import { G } from "@svgdotjs/svg.js";
|
|
2
|
-
|
|
3
|
-
import { SymbolPinSide, bodyColor, defaultFontBold, defaultFont } from "./globals.js";
|
|
4
|
-
import { Feature, Geometry, GeometryProp, HorizontalAlign, Label, LabelStyle, VerticalAlign } from "./geometry.js";
|
|
5
|
-
import { Logger } from "./logger.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Symbols should also define where their ports
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const defaultSymbolLineColor = '#333';
|
|
13
|
-
const defaultSymbolLineWidth = 2;
|
|
14
|
-
|
|
15
|
-
export abstract class SymbolGraphic {
|
|
16
|
-
|
|
17
|
-
drawPortsName = true;
|
|
18
|
-
|
|
19
|
-
displayBounds = true;
|
|
20
|
-
|
|
21
|
-
drawing: SymbolDrawing;
|
|
22
|
-
|
|
23
|
-
_angle = 0;
|
|
24
|
-
|
|
25
|
-
width: number;
|
|
26
|
-
height: number;
|
|
27
|
-
|
|
28
|
-
// Stores a reference of <labelID> to the label value
|
|
29
|
-
labelTexts = new Map<string, string>();
|
|
30
|
-
|
|
31
|
-
get angle(): number {
|
|
32
|
-
return (this._angle % 360);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
set angle(value: number) {
|
|
36
|
-
this._angle = value;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
refreshDrawing(calculateSize = true): void {
|
|
40
|
-
this.generateDrawing();
|
|
41
|
-
calculateSize && this.calculateSize();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
calculateSize(): void {
|
|
45
|
-
const { width, height } = this.drawing.getBoundingBox();
|
|
46
|
-
this.width = width;
|
|
47
|
-
this.height = height;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Subclasses should implement this
|
|
51
|
-
abstract generateDrawing(): void;
|
|
52
|
-
|
|
53
|
-
size(): { width: number; height: number; } {
|
|
54
|
-
return {
|
|
55
|
-
width: this.width,
|
|
56
|
-
height: this.height
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
draw(group: G, extra?: {}): void {
|
|
61
|
-
// Assume that the symbol is vertical
|
|
62
|
-
const innerGroup = group.group();
|
|
63
|
-
|
|
64
|
-
this.drawBody(innerGroup);
|
|
65
|
-
|
|
66
|
-
this.drawPins(innerGroup);
|
|
67
|
-
|
|
68
|
-
this.drawLabels(innerGroup);
|
|
69
|
-
|
|
70
|
-
this.drawPlaceRemove(innerGroup, extra);
|
|
71
|
-
|
|
72
|
-
// this.displayBounds && this.drawBounds(group);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
drawPlaceRemove(group: G, extra?: { place?: boolean }): void {
|
|
76
|
-
if (extra && extra.place === false) {
|
|
77
|
-
// Do not place this component!
|
|
78
|
-
// Draw the x
|
|
79
|
-
const { start, end } = this.drawing.getBoundingBox(true);
|
|
80
|
-
|
|
81
|
-
group.path([
|
|
82
|
-
"M", start[0], start[1], "L", end[0], end[1],
|
|
83
|
-
"M", end[0], start[1], "L", start[0], end[1]
|
|
84
|
-
].join(" "))
|
|
85
|
-
.stroke({
|
|
86
|
-
width: defaultSymbolLineWidth,
|
|
87
|
-
color: 'red'
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Returns the port position, relative to the symbol origin
|
|
93
|
-
pinPosition(id: number): { x: number; y: number; angle: number; } {
|
|
94
|
-
const pin = this.drawing.getPinPosition(id);
|
|
95
|
-
|
|
96
|
-
// Allow pin position values to be rounded to 4 d.p
|
|
97
|
-
const [x, y] = pin.start;
|
|
98
|
-
const useX = Math.round(x * 10000) / 10000;
|
|
99
|
-
const useY = Math.round(y * 10000 / 10000);
|
|
100
|
-
|
|
101
|
-
if (pin) {
|
|
102
|
-
return {
|
|
103
|
-
x: useX,
|
|
104
|
-
y: useY,
|
|
105
|
-
angle: pin.angle,
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
protected drawBounds(group: G): void {
|
|
111
|
-
const bbox = this.drawing.getBoundingBox();
|
|
112
|
-
|
|
113
|
-
group.circle(3)
|
|
114
|
-
.translate(-3 / 2, -3 / 2)
|
|
115
|
-
.fill('red')
|
|
116
|
-
.stroke('none');
|
|
117
|
-
|
|
118
|
-
group.rect(bbox.width, bbox.height)
|
|
119
|
-
.translate(bbox.start[0], bbox.start[1])
|
|
120
|
-
.fill('none')
|
|
121
|
-
.stroke({
|
|
122
|
-
width: 1,
|
|
123
|
-
color: '#ccc',
|
|
124
|
-
})
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
protected drawBody(group: G): void {
|
|
128
|
-
// Draws the symbol body
|
|
129
|
-
|
|
130
|
-
const paths = this.drawing.getPaths();
|
|
131
|
-
paths.forEach(pathInfo => {
|
|
132
|
-
const {path, lineColor, fillColor, lineWidth} = pathInfo;
|
|
133
|
-
group.path(path)
|
|
134
|
-
.stroke({
|
|
135
|
-
width: lineWidth,
|
|
136
|
-
color: lineColor,
|
|
137
|
-
})
|
|
138
|
-
.fill(fillColor)
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
protected drawPins(group: G): void {
|
|
143
|
-
// Draw pins
|
|
144
|
-
group.path(this.drawing.getPinsPath())
|
|
145
|
-
.stroke({
|
|
146
|
-
width: defaultSymbolLineWidth,
|
|
147
|
-
color: '#333',
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
protected drawLabels(group: G): void {
|
|
152
|
-
const labels = this.drawing.getLabels();
|
|
153
|
-
|
|
154
|
-
labels.forEach(label => {
|
|
155
|
-
const tmpLabel = label as Label;
|
|
156
|
-
|
|
157
|
-
const {
|
|
158
|
-
fontSize = 10,
|
|
159
|
-
anchor = HorizontalAlign.Left,
|
|
160
|
-
vanchor = VerticalAlign.Bottom,
|
|
161
|
-
fontWeight = 'regular',
|
|
162
|
-
angle: labelAngle = 0,
|
|
163
|
-
} = tmpLabel.style ?? {};
|
|
164
|
-
|
|
165
|
-
let anchorStyle = 'start';
|
|
166
|
-
let dominantBaseline = 'auto';
|
|
167
|
-
|
|
168
|
-
let useAnchor = anchor;
|
|
169
|
-
let useDominantBaseline = vanchor;
|
|
170
|
-
const isRotation180 = Math.abs(this.angle) === 180;
|
|
171
|
-
|
|
172
|
-
if (isRotation180) {
|
|
173
|
-
// Special case to flip the text instead of rotating
|
|
174
|
-
useAnchor = this.flipTextAnchor(anchor);
|
|
175
|
-
useDominantBaseline = this.flipDominantBaseline(vanchor);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
switch(useAnchor){
|
|
179
|
-
case HorizontalAlign.Left:
|
|
180
|
-
anchorStyle = 'start';
|
|
181
|
-
break;
|
|
182
|
-
|
|
183
|
-
case HorizontalAlign.Middle:
|
|
184
|
-
anchorStyle = 'middle';
|
|
185
|
-
break;
|
|
186
|
-
|
|
187
|
-
case HorizontalAlign.Right:
|
|
188
|
-
anchorStyle = 'end';
|
|
189
|
-
break;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
switch(useDominantBaseline){
|
|
193
|
-
case VerticalAlign.Top:
|
|
194
|
-
dominantBaseline = 'hanging';
|
|
195
|
-
break;
|
|
196
|
-
|
|
197
|
-
case VerticalAlign.Middle:
|
|
198
|
-
dominantBaseline = 'middle';
|
|
199
|
-
break;
|
|
200
|
-
|
|
201
|
-
case VerticalAlign.Bottom:
|
|
202
|
-
dominantBaseline = 'text-top';
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const position = tmpLabel.getLabelPosition();
|
|
207
|
-
const useFont = defaultFont;
|
|
208
|
-
|
|
209
|
-
const textContainer = group.group();
|
|
210
|
-
const text = textContainer.text(tmpLabel.text)
|
|
211
|
-
.fill('#333')
|
|
212
|
-
.font({
|
|
213
|
-
family: useFont,
|
|
214
|
-
size: fontSize,
|
|
215
|
-
anchor: anchorStyle,
|
|
216
|
-
'dominant-baseline': dominantBaseline,
|
|
217
|
-
weight: fontWeight,
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
let translateX: number, translateY: number;
|
|
221
|
-
let useRotateAngle = 0;
|
|
222
|
-
|
|
223
|
-
if (isRotation180){
|
|
224
|
-
translateX = -position[0];
|
|
225
|
-
translateY = -position[1];
|
|
226
|
-
useRotateAngle = 0;
|
|
227
|
-
} else {
|
|
228
|
-
translateX = position[0];
|
|
229
|
-
translateY = position[1];
|
|
230
|
-
useRotateAngle = this.angle;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
text.rotate(labelAngle);
|
|
234
|
-
textContainer.translate(translateX, translateY)
|
|
235
|
-
.rotate(useRotateAngle, -translateX, -translateY);
|
|
236
|
-
|
|
237
|
-
// For debug, show the origin of the text container
|
|
238
|
-
// textContainer.circle(2).fill('red');
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
flipTextAnchor(value: HorizontalAlign): HorizontalAlign {
|
|
243
|
-
if (value === HorizontalAlign.Left) {
|
|
244
|
-
return HorizontalAlign.Right
|
|
245
|
-
} else if (value === HorizontalAlign.Right) {
|
|
246
|
-
return HorizontalAlign.Left;
|
|
247
|
-
} else {
|
|
248
|
-
return HorizontalAlign.Middle;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
flipDominantBaseline(value: VerticalAlign): VerticalAlign {
|
|
253
|
-
if (value === VerticalAlign.Top) {
|
|
254
|
-
return VerticalAlign.Bottom;
|
|
255
|
-
} else if (value === VerticalAlign.Bottom) {
|
|
256
|
-
return VerticalAlign.Top;
|
|
257
|
-
} else {
|
|
258
|
-
return VerticalAlign.Middle;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
setLabelValue(labelId: string, labelValue: string): void {
|
|
263
|
-
this.labelTexts.set(labelId, labelValue);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
getLabelValue(labelId: string): string {
|
|
267
|
-
if (this.labelTexts.has(labelId)) {
|
|
268
|
-
return this.labelTexts.get(labelId);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
export function SymbolFactory(name: string): SymbolGraphic | null {
|
|
274
|
-
switch (name) {
|
|
275
|
-
case 'point':
|
|
276
|
-
return new SymbolPointHidden();
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
export class SymbolPointHidden extends SymbolGraphic {
|
|
281
|
-
generateDrawing(): void {
|
|
282
|
-
const drawing = new SymbolDrawing();
|
|
283
|
-
drawing.addPin(1, 0, 0, 0, 0);
|
|
284
|
-
|
|
285
|
-
this.drawing = drawing;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
export class SymbolText extends SymbolGraphic {
|
|
290
|
-
|
|
291
|
-
text: string;
|
|
292
|
-
fontSize = 10;
|
|
293
|
-
fontWeight = 'regular';
|
|
294
|
-
|
|
295
|
-
constructor(text: string){
|
|
296
|
-
super();
|
|
297
|
-
this.text = text;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
generateDrawing(): void {
|
|
301
|
-
const drawing = new SymbolDrawing();
|
|
302
|
-
drawing.addLabel(0, 0, this.text, {
|
|
303
|
-
fontSize: this.fontSize,
|
|
304
|
-
anchor: HorizontalAlign.Middle,
|
|
305
|
-
fontWeight: this.fontWeight,
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
this.drawing = drawing;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
export class SymbolPlaceholder extends SymbolGraphic {
|
|
313
|
-
// This is used if the drawing object is defined within
|
|
314
|
-
// circuitscript code itself.
|
|
315
|
-
generateDrawing(): void {
|
|
316
|
-
const drawing = this.drawing as SymbolDrawingCommands;
|
|
317
|
-
|
|
318
|
-
drawing.log("=== start generate drawing ===");
|
|
319
|
-
|
|
320
|
-
drawing.clear();
|
|
321
|
-
drawing.angle = this._angle;
|
|
322
|
-
const commands = drawing.getCommands();
|
|
323
|
-
|
|
324
|
-
drawing.log('id: ', drawing.id, 'angle: ', this._angle, "commands:", commands.length);
|
|
325
|
-
|
|
326
|
-
commands.forEach(([commandName, positionParams, keywordParams]) => {
|
|
327
|
-
switch (commandName) {
|
|
328
|
-
case PlaceHolderCommands.rect:
|
|
329
|
-
drawing.log('add rect', ...positionParams);
|
|
330
|
-
drawing.addRect(...positionParams);
|
|
331
|
-
break;
|
|
332
|
-
|
|
333
|
-
case PlaceHolderCommands.hline:
|
|
334
|
-
drawing.log('add hline', ...positionParams);
|
|
335
|
-
drawing.addHLine(...positionParams);
|
|
336
|
-
break;
|
|
337
|
-
|
|
338
|
-
case PlaceHolderCommands.vline:
|
|
339
|
-
drawing.log('add vline', ...positionParams);
|
|
340
|
-
drawing.addVLine(...positionParams);
|
|
341
|
-
break;
|
|
342
|
-
|
|
343
|
-
case PlaceHolderCommands.line:
|
|
344
|
-
drawing.log('add line', ...positionParams);
|
|
345
|
-
drawing.addLine(...positionParams);
|
|
346
|
-
break;
|
|
347
|
-
|
|
348
|
-
case PlaceHolderCommands.path:
|
|
349
|
-
drawing.addPath(...positionParams);
|
|
350
|
-
break;
|
|
351
|
-
|
|
352
|
-
case PlaceHolderCommands.lineWidth:
|
|
353
|
-
drawing.addSetLineWidth(...positionParams);
|
|
354
|
-
break;
|
|
355
|
-
|
|
356
|
-
case PlaceHolderCommands.fill:
|
|
357
|
-
drawing.addSetFillColor(...positionParams);
|
|
358
|
-
break;
|
|
359
|
-
|
|
360
|
-
case PlaceHolderCommands.lineColor:
|
|
361
|
-
drawing.addSetLineColor(...positionParams);
|
|
362
|
-
break;
|
|
363
|
-
|
|
364
|
-
case PlaceHolderCommands.arc:
|
|
365
|
-
drawing.addArc(...positionParams);
|
|
366
|
-
break;
|
|
367
|
-
|
|
368
|
-
case PlaceHolderCommands.circle:
|
|
369
|
-
// circle params: center x, center y, radius
|
|
370
|
-
drawing.addArc(...positionParams, 0, 360);
|
|
371
|
-
break;
|
|
372
|
-
|
|
373
|
-
case PlaceHolderCommands.triangle:
|
|
374
|
-
drawing.addTriangle(...positionParams);
|
|
375
|
-
break;
|
|
376
|
-
|
|
377
|
-
case PlaceHolderCommands.pin:
|
|
378
|
-
case PlaceHolderCommands.hpin:
|
|
379
|
-
case PlaceHolderCommands.vpin:
|
|
380
|
-
{
|
|
381
|
-
this.drawPinParams(drawing, commandName,
|
|
382
|
-
keywordParams, positionParams);
|
|
383
|
-
break;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
case PlaceHolderCommands.label: {
|
|
387
|
-
const keywords = ['fontSize', 'anchor', 'vanchor', 'angle'];
|
|
388
|
-
|
|
389
|
-
// Create the style object
|
|
390
|
-
const style = {};
|
|
391
|
-
keywords.forEach(item => {
|
|
392
|
-
if (keywordParams.has(item)) {
|
|
393
|
-
style[item] = keywordParams.get(item);
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
|
|
397
|
-
positionParams = [...positionParams];
|
|
398
|
-
positionParams.push(style);
|
|
399
|
-
|
|
400
|
-
const labelId = positionParams[0];
|
|
401
|
-
|
|
402
|
-
const tmpPositionParams = [...positionParams];
|
|
403
|
-
|
|
404
|
-
const tmpLabelValue = this.getLabelValue(labelId);
|
|
405
|
-
if (tmpLabelValue !== undefined) {
|
|
406
|
-
tmpPositionParams[3] = tmpLabelValue;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
drawing.log('add label', JSON.stringify(tmpPositionParams));
|
|
410
|
-
drawing.addLabelId(...tmpPositionParams);
|
|
411
|
-
break;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
drawing.log("=== end generate drawing ===");
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
drawPinParams(drawing: SymbolDrawingCommands,
|
|
420
|
-
commandName: string, keywordParams: Map<string, any>,
|
|
421
|
-
positionParams: any[]): void {
|
|
422
|
-
|
|
423
|
-
drawing.log('add pin', ...positionParams);
|
|
424
|
-
|
|
425
|
-
const keywordDisplayPinId = 'display_pin_id';
|
|
426
|
-
let displayPinId = true;
|
|
427
|
-
|
|
428
|
-
if (keywordParams.has(keywordDisplayPinId)) {
|
|
429
|
-
if (keywordParams.get(keywordDisplayPinId) === 0) {
|
|
430
|
-
displayPinId = false;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
let pinNameParam: string | null = null;
|
|
435
|
-
if (typeof positionParams[1] === 'string') {
|
|
436
|
-
// If the type of the second position is a string, then
|
|
437
|
-
// use the string value as the pin name
|
|
438
|
-
pinNameParam = positionParams[1];
|
|
439
|
-
positionParams = [positionParams[0], ...positionParams.slice(2)];
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// create the next point
|
|
443
|
-
const startX = positionParams[1];
|
|
444
|
-
const startY = positionParams[2];
|
|
445
|
-
|
|
446
|
-
if (commandName === PlaceHolderCommands.vpin) {
|
|
447
|
-
const magnitude = positionParams[3];
|
|
448
|
-
positionParams = [
|
|
449
|
-
positionParams[0],
|
|
450
|
-
startX,
|
|
451
|
-
startY,
|
|
452
|
-
startX,
|
|
453
|
-
startY + magnitude
|
|
454
|
-
];
|
|
455
|
-
} else if (commandName === PlaceHolderCommands.hpin) {
|
|
456
|
-
const magnitude = positionParams[3];
|
|
457
|
-
positionParams = [
|
|
458
|
-
positionParams[0],
|
|
459
|
-
startX,
|
|
460
|
-
startY,
|
|
461
|
-
startX + magnitude,
|
|
462
|
-
startY
|
|
463
|
-
];
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
drawing.addPin(...positionParams);
|
|
467
|
-
|
|
468
|
-
// Add a label for the pinId and pinName
|
|
469
|
-
const latestPin = this.drawing.pins[this.drawing.pins.length - 1];
|
|
470
|
-
const [pinId, , angle] = latestPin;
|
|
471
|
-
const [, , , endX, endY] = positionParams;
|
|
472
|
-
|
|
473
|
-
let pinNameAlignment = HorizontalAlign.Left;
|
|
474
|
-
let pinNameOffsetX = 4;
|
|
475
|
-
|
|
476
|
-
let pinIdOffsetX = 0;
|
|
477
|
-
let pinIdAlignment = HorizontalAlign.Left;
|
|
478
|
-
|
|
479
|
-
let pinIdVAlignment = VerticalAlign.Bottom;
|
|
480
|
-
let pinIdOffsetY = -2;
|
|
481
|
-
|
|
482
|
-
switch (angle) {
|
|
483
|
-
case 0:
|
|
484
|
-
pinNameAlignment = HorizontalAlign.Left;
|
|
485
|
-
pinNameOffsetX = 4;
|
|
486
|
-
pinIdAlignment = HorizontalAlign.Right;
|
|
487
|
-
pinIdOffsetX = -2;
|
|
488
|
-
break;
|
|
489
|
-
case 90:
|
|
490
|
-
case 180:
|
|
491
|
-
pinNameAlignment = HorizontalAlign.Right;
|
|
492
|
-
pinNameOffsetX = -4;
|
|
493
|
-
pinIdAlignment = HorizontalAlign.Left;
|
|
494
|
-
pinIdOffsetX = 2;
|
|
495
|
-
break;
|
|
496
|
-
case 270:
|
|
497
|
-
pinNameAlignment = HorizontalAlign.Left;
|
|
498
|
-
pinNameOffsetX = 4;
|
|
499
|
-
pinIdAlignment = HorizontalAlign.Left;
|
|
500
|
-
pinIdOffsetX = 2;
|
|
501
|
-
pinIdOffsetY = 2;
|
|
502
|
-
pinIdVAlignment = VerticalAlign.Top;
|
|
503
|
-
break;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
if (angle === 0 || angle === 90 || angle === 180 || angle === 270) {
|
|
507
|
-
const usePinName = pinNameParam ?? "";
|
|
508
|
-
|
|
509
|
-
// Draw the pinName
|
|
510
|
-
usePinName !== "" && drawing.addLabel(
|
|
511
|
-
endX + pinNameOffsetX, endY, usePinName, {
|
|
512
|
-
fontSize: 10,
|
|
513
|
-
anchor: pinNameAlignment,
|
|
514
|
-
vanchor: VerticalAlign.Middle,
|
|
515
|
-
});
|
|
516
|
-
|
|
517
|
-
// Draw pin Id
|
|
518
|
-
displayPinId && drawing.addLabel(
|
|
519
|
-
endX + pinIdOffsetX, endY + pinIdOffsetY, pinId.toString(), {
|
|
520
|
-
fontSize: 8,
|
|
521
|
-
anchor: pinIdAlignment,
|
|
522
|
-
vanchor: pinIdVAlignment,
|
|
523
|
-
});
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
constructor(drawing: SymbolDrawing) {
|
|
528
|
-
super();
|
|
529
|
-
this.drawing = drawing;
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
export enum PlaceHolderCommands {
|
|
534
|
-
arc = 'arc',
|
|
535
|
-
circle = 'circle',
|
|
536
|
-
rect = 'rect',
|
|
537
|
-
triangle = 'triangle',
|
|
538
|
-
pin = 'pin',
|
|
539
|
-
hpin = 'hpin',
|
|
540
|
-
vpin = 'vpin',
|
|
541
|
-
hline = 'hline',
|
|
542
|
-
vline = 'vline',
|
|
543
|
-
line = 'line',
|
|
544
|
-
label = 'label',
|
|
545
|
-
path = 'path',
|
|
546
|
-
lineWidth = 'lineWidth',
|
|
547
|
-
fill = 'fill',
|
|
548
|
-
lineColor = 'lineColor'
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
export class SymbolCustom extends SymbolGraphic {
|
|
552
|
-
|
|
553
|
-
pinDefinition: SymbolPinDefintion[] = [];
|
|
554
|
-
|
|
555
|
-
bodyWidth = 100;
|
|
556
|
-
|
|
557
|
-
pinLength = 20;
|
|
558
|
-
|
|
559
|
-
width = 100;
|
|
560
|
-
height = 100;
|
|
561
|
-
|
|
562
|
-
pinSpacing = 20;
|
|
563
|
-
|
|
564
|
-
pinTextPadding = 5;
|
|
565
|
-
|
|
566
|
-
pins: SymbolPinLayout[] = [];
|
|
567
|
-
|
|
568
|
-
_cacheLeftPins: SymbolPinDefintion[];
|
|
569
|
-
_cacheRightPins: SymbolPinDefintion[];
|
|
570
|
-
|
|
571
|
-
constructor(pinDefinition: SymbolPinDefintion[]) {
|
|
572
|
-
super();
|
|
573
|
-
|
|
574
|
-
// define the left and right pins only for now
|
|
575
|
-
this.pinDefinition = pinDefinition;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
generateDrawing(): void {
|
|
579
|
-
// Determine the size based on the definition
|
|
580
|
-
|
|
581
|
-
const leftPins = this.pinDefinition.filter(item => {
|
|
582
|
-
return item.side === SymbolPinSide.Left;
|
|
583
|
-
});
|
|
584
|
-
|
|
585
|
-
const rightPins = this.pinDefinition.filter(item => {
|
|
586
|
-
return item.side === SymbolPinSide.Right;
|
|
587
|
-
});
|
|
588
|
-
|
|
589
|
-
const maxLeftPins = Math.max(...leftPins.map(item => item.position)) + 1;
|
|
590
|
-
const maxRightPins = Math.max(...rightPins.map(item => item.position)) + 1;
|
|
591
|
-
|
|
592
|
-
const drawing = new SymbolDrawing();
|
|
593
|
-
drawing.angle = this._angle;
|
|
594
|
-
|
|
595
|
-
const bodyWidth = this.bodyWidth;
|
|
596
|
-
const bodyHeight = (1 + Math.max(maxLeftPins, maxRightPins)) * this.pinSpacing;
|
|
597
|
-
|
|
598
|
-
// drawing.addSetFillColor(bodyColor);
|
|
599
|
-
|
|
600
|
-
drawing.addRect(0, 0, bodyWidth, bodyHeight);
|
|
601
|
-
|
|
602
|
-
// Setup the pins
|
|
603
|
-
const leftPinStart = -bodyWidth / 2;
|
|
604
|
-
const rightPinStart = bodyWidth / 2;
|
|
605
|
-
const pinStartY = -bodyHeight / 2;
|
|
606
|
-
|
|
607
|
-
leftPins.forEach(pin => {
|
|
608
|
-
const position = pin.position;
|
|
609
|
-
const pinY = pinStartY + (position + 1) * this.pinSpacing // Includes the offset too
|
|
610
|
-
drawing.addPin(pin.pinId, leftPinStart - this.pinLength, pinY, leftPinStart, pinY);
|
|
611
|
-
|
|
612
|
-
drawing.addLabel(leftPinStart + 4, pinY, pin.text, {
|
|
613
|
-
fontSize: 10,
|
|
614
|
-
anchor: HorizontalAlign.Left,
|
|
615
|
-
vanchor: VerticalAlign.Middle,
|
|
616
|
-
});
|
|
617
|
-
|
|
618
|
-
// Add the pin number
|
|
619
|
-
drawing.addLabel(leftPinStart - 2 , pinY - 2, pin.pinId.toString(), {
|
|
620
|
-
fontSize: 8,
|
|
621
|
-
anchor: HorizontalAlign.Right,
|
|
622
|
-
vanchor: VerticalAlign.Bottom,
|
|
623
|
-
});
|
|
624
|
-
});
|
|
625
|
-
|
|
626
|
-
rightPins.forEach(pin => {
|
|
627
|
-
const position = pin.position;
|
|
628
|
-
const pinY = pinStartY + (position + 1) * this.pinSpacing // Includes the offset too
|
|
629
|
-
drawing.addPin(pin.pinId, rightPinStart + this.pinLength, pinY, rightPinStart, pinY);
|
|
630
|
-
|
|
631
|
-
drawing.addLabel(rightPinStart - 4, pinY, pin.text, {
|
|
632
|
-
fontSize: 10,
|
|
633
|
-
anchor: HorizontalAlign.Right,
|
|
634
|
-
vanchor: VerticalAlign.Middle,
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
// Add the pin number
|
|
638
|
-
drawing.addLabel(rightPinStart + 2 , pinY - 2, pin.pinId.toString(), {
|
|
639
|
-
fontSize: 8,
|
|
640
|
-
anchor: HorizontalAlign.Left,
|
|
641
|
-
vanchor: VerticalAlign.Bottom,
|
|
642
|
-
});
|
|
643
|
-
});
|
|
644
|
-
|
|
645
|
-
const instanceName = this.getLabelValue("refdes");
|
|
646
|
-
instanceName && drawing.addLabel(-bodyWidth/2, -bodyHeight/2 - 4, instanceName, {
|
|
647
|
-
fontSize: 10,
|
|
648
|
-
anchor: HorizontalAlign.Left,
|
|
649
|
-
});
|
|
650
|
-
|
|
651
|
-
const acceptedMPNKeys = ['MPN', 'mpn', 'manufacturer_pn'];
|
|
652
|
-
|
|
653
|
-
acceptedMPNKeys.some(key => {
|
|
654
|
-
const labelValue = this.getLabelValue(key);
|
|
655
|
-
if (labelValue !== undefined){
|
|
656
|
-
drawing.addLabel(-bodyWidth/2, bodyHeight/2 + 4, labelValue, {
|
|
657
|
-
fontSize: 10,
|
|
658
|
-
anchor: HorizontalAlign.Left,
|
|
659
|
-
vanchor: VerticalAlign.Top,
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
});
|
|
663
|
-
|
|
664
|
-
this.drawing = drawing;
|
|
665
|
-
this._cacheLeftPins = leftPins;
|
|
666
|
-
this._cacheRightPins = rightPins;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
calculateSize(): void {
|
|
670
|
-
// This width also includes the pin length
|
|
671
|
-
this.width = this.bodyWidth + 2 * this.pinLength;
|
|
672
|
-
this.height = (1 + Math.max(this._cacheLeftPins.length,
|
|
673
|
-
this._cacheRightPins.length)) * this.pinSpacing;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
export class SymbolDrawing {
|
|
680
|
-
|
|
681
|
-
items: (Feature | GeometryProp)[] = [];
|
|
682
|
-
|
|
683
|
-
// pinId, feature, angle
|
|
684
|
-
pins: [number, Feature, number][] = [];
|
|
685
|
-
|
|
686
|
-
angle = 0;
|
|
687
|
-
|
|
688
|
-
mainOrigin:[number, number] = [0, 0];
|
|
689
|
-
|
|
690
|
-
logger: Logger = null;
|
|
691
|
-
|
|
692
|
-
clear(): void {
|
|
693
|
-
this.items = [];
|
|
694
|
-
this.pins = [];
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
log(...params: any[]): void {
|
|
698
|
-
this.logger && this.logger.add(params.join(' '));
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
addLine(startX: number, startY: number, endX: number, endY: number): SymbolDrawing {
|
|
702
|
-
this.items.push(
|
|
703
|
-
Geometry.segment([startX, startY], [endX, endY])
|
|
704
|
-
);
|
|
705
|
-
|
|
706
|
-
return this;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
addPin(pinId: number, startX: number, startY: number,
|
|
710
|
-
endX: number, endY: number): SymbolDrawing {
|
|
711
|
-
|
|
712
|
-
// Determine the pin angle based on vector with start point
|
|
713
|
-
// going to end point. The angle is relative to the x-axis.
|
|
714
|
-
// 270
|
|
715
|
-
// 180 -- start --> 0
|
|
716
|
-
// 90
|
|
717
|
-
|
|
718
|
-
let angle = 0;
|
|
719
|
-
if (startX === endX) {
|
|
720
|
-
if (startY > endY) {
|
|
721
|
-
angle = 270;
|
|
722
|
-
} else if (startY < endY) {
|
|
723
|
-
angle = 90;
|
|
724
|
-
}
|
|
725
|
-
} else {
|
|
726
|
-
if (startX < endX) {
|
|
727
|
-
angle = 0;
|
|
728
|
-
} else if (startX > endX) {
|
|
729
|
-
angle = 180;
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
this.pins.push([
|
|
734
|
-
pinId,
|
|
735
|
-
Geometry.segment([startX, startY], [endX, endY]),
|
|
736
|
-
angle
|
|
737
|
-
]);
|
|
738
|
-
|
|
739
|
-
return this;
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
addVLine(startX: number, startY: number, value: number): SymbolDrawing {
|
|
743
|
-
this.items.push(
|
|
744
|
-
Geometry.segment([startX, startY], [startX, startY + value])
|
|
745
|
-
);
|
|
746
|
-
return this;
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
addHLine(startX: number, startY: number, value: number): SymbolDrawing {
|
|
750
|
-
this.items.push(
|
|
751
|
-
Geometry.segment([startX, startY], [startX + value, startY])
|
|
752
|
-
);
|
|
753
|
-
return this;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
addRect(centerX: number, centerY: number,width: number, height: number): SymbolDrawing {
|
|
757
|
-
const width2 = width/2;
|
|
758
|
-
const height2 = height/2;
|
|
759
|
-
|
|
760
|
-
this.items.push(
|
|
761
|
-
Geometry.polygon([
|
|
762
|
-
[centerX - width2, centerY - height2],
|
|
763
|
-
[centerX + width2, centerY - height2],
|
|
764
|
-
[centerX + width2, centerY + height2],
|
|
765
|
-
[centerX - width2, centerY + height2],
|
|
766
|
-
[centerX - width2, centerY - height2]
|
|
767
|
-
])
|
|
768
|
-
);
|
|
769
|
-
|
|
770
|
-
return this;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
addTriangle(startX: number, startY: number, endX: number, endY: number, width: number): SymbolDrawing {
|
|
774
|
-
const line = Geometry.line(
|
|
775
|
-
startX, startY,
|
|
776
|
-
endX, endY);
|
|
777
|
-
|
|
778
|
-
const normLine = line.norm;
|
|
779
|
-
const dx1 = normLine.x * width / 2;
|
|
780
|
-
const dy1 = normLine.y * width / 2;
|
|
781
|
-
const dx2 = normLine.x * -width / 2;
|
|
782
|
-
const dy2 = normLine.y * -width / 2;
|
|
783
|
-
|
|
784
|
-
this.items.push(
|
|
785
|
-
Geometry.polygon([
|
|
786
|
-
[dx1 + startX, dy1 + startY],
|
|
787
|
-
[dx2 + startX, dy2 + startY],
|
|
788
|
-
[endX, endY],
|
|
789
|
-
[dx1 + startX, dy1 + startY],
|
|
790
|
-
])
|
|
791
|
-
);
|
|
792
|
-
|
|
793
|
-
return this;
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
addRect2(x: number, y: number, x2: number, y2: number): SymbolDrawing {
|
|
797
|
-
this.items.push(
|
|
798
|
-
Geometry.polygon([
|
|
799
|
-
[x, y],
|
|
800
|
-
[x2, y],
|
|
801
|
-
[x2, y2],
|
|
802
|
-
[x, y2],
|
|
803
|
-
[x, y]
|
|
804
|
-
])
|
|
805
|
-
);
|
|
806
|
-
|
|
807
|
-
return this;
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
addLabel(x: number, y: number, textValue: string, style: LabelStyle): SymbolDrawing {
|
|
811
|
-
this.items.push(
|
|
812
|
-
Geometry.label(null, x, y, textValue, style)
|
|
813
|
-
)
|
|
814
|
-
|
|
815
|
-
return this;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
addLabelId(id: string, x: number, y: number, textValue: string, style: LabelStyle,): SymbolDrawing {
|
|
819
|
-
this.items.push(
|
|
820
|
-
Geometry.label(id, x, y, textValue, style)
|
|
821
|
-
)
|
|
822
|
-
|
|
823
|
-
return this;
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
addPath(...pathParts:any): SymbolDrawing {
|
|
827
|
-
const parts = pathParts.reduce((accum, tmp) => {
|
|
828
|
-
if (typeof tmp === "string"){
|
|
829
|
-
accum = accum.concat(tmp.split(" "));
|
|
830
|
-
} else if (typeof tmp === "number"){
|
|
831
|
-
accum.push(tmp);
|
|
832
|
-
}
|
|
833
|
-
return accum;
|
|
834
|
-
}, [] as (number|string)[]);
|
|
835
|
-
|
|
836
|
-
const geomObjects = [];
|
|
837
|
-
let currentObj: [x: number, y: number][] = null;
|
|
838
|
-
|
|
839
|
-
for (let i = 0; i < parts.length; i++) {
|
|
840
|
-
const command = parts[i];
|
|
841
|
-
if (command === 'M') {
|
|
842
|
-
// Start a new object
|
|
843
|
-
if (currentObj !== null) {
|
|
844
|
-
geomObjects.push(currentObj);
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
const x = Number(parts[i + 1]);
|
|
848
|
-
const y = Number(parts[i + 2]);
|
|
849
|
-
|
|
850
|
-
currentObj = [[x, y]];
|
|
851
|
-
|
|
852
|
-
i += 2;
|
|
853
|
-
|
|
854
|
-
} else if (command === 'L') {
|
|
855
|
-
const x = Number(parts[i + 1]);
|
|
856
|
-
const y = Number(parts[i + 2]);
|
|
857
|
-
currentObj.push([x, y]);
|
|
858
|
-
|
|
859
|
-
i += 2;
|
|
860
|
-
|
|
861
|
-
} else if (command === 'Z'){
|
|
862
|
-
// Return back to first point in path
|
|
863
|
-
const firstPoint = currentObj[0];
|
|
864
|
-
currentObj.push(firstPoint);
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
if (currentObj !== null){
|
|
869
|
-
geomObjects.push(currentObj);
|
|
870
|
-
currentObj = null;
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
geomObjects.forEach(coords => {
|
|
874
|
-
const [first] = coords;
|
|
875
|
-
const last = coords[coords.length - 1];
|
|
876
|
-
|
|
877
|
-
if (first[0] === last[0] && first[1] === last[1]){
|
|
878
|
-
// If both are the same, then this is a polygon
|
|
879
|
-
this.items.push(Geometry.polygon(coords));
|
|
880
|
-
} else {
|
|
881
|
-
this.items.push(Geometry.multiline(coords));
|
|
882
|
-
}
|
|
883
|
-
})
|
|
884
|
-
|
|
885
|
-
return this;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
addSetLineWidth(value: number): SymbolDrawing {
|
|
889
|
-
this.items.push(new GeometryProp('lineWidth', value));
|
|
890
|
-
return this;
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
addSetLineColor(value: string): SymbolDrawing {
|
|
894
|
-
this.items.push(new GeometryProp('lineColor', value));
|
|
895
|
-
return this;
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
addSetFillColor(value: string): SymbolDrawing {
|
|
899
|
-
this.items.push(new GeometryProp('fillColor', value));
|
|
900
|
-
return this;
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
addArc(x: number, y: number, radius: number,
|
|
904
|
-
startAngle: number, endAngle: number): SymbolDrawing {
|
|
905
|
-
|
|
906
|
-
// Angles in degrees, convert to radians
|
|
907
|
-
startAngle = startAngle * Math.PI / 180;
|
|
908
|
-
endAngle = endAngle * Math.PI / 180;
|
|
909
|
-
|
|
910
|
-
this.items.push(
|
|
911
|
-
Geometry.arc([x, y], radius, startAngle, endAngle, true));
|
|
912
|
-
|
|
913
|
-
return this;
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
getPaths(): {path: string,
|
|
917
|
-
fillColor: string,
|
|
918
|
-
lineColor: string,
|
|
919
|
-
lineWidth: number}[] {
|
|
920
|
-
|
|
921
|
-
let currentFill = "#fff";
|
|
922
|
-
let currentLineWidth = 1;
|
|
923
|
-
let currentLineColor = '#333';
|
|
924
|
-
|
|
925
|
-
const pathItems = [];
|
|
926
|
-
|
|
927
|
-
this.items.forEach(item => {
|
|
928
|
-
if (!(item instanceof Label)){
|
|
929
|
-
if (item instanceof GeometryProp){
|
|
930
|
-
if (item.name === 'lineWidth'){
|
|
931
|
-
currentLineWidth = item.value as number;
|
|
932
|
-
} else if (item.name === 'lineColor'){
|
|
933
|
-
currentLineColor = item.value as string;
|
|
934
|
-
} else if (item.name === 'fillColor'){
|
|
935
|
-
currentFill = item.value as string;
|
|
936
|
-
}
|
|
937
|
-
} else {
|
|
938
|
-
const rotatedPath = Geometry.groupRotate([item], this.angle,
|
|
939
|
-
this.mainOrigin);
|
|
940
|
-
|
|
941
|
-
const {path, isClosedPolygon} =
|
|
942
|
-
this.featuresToPath(rotatedPath);
|
|
943
|
-
|
|
944
|
-
pathItems.push({
|
|
945
|
-
path: path,
|
|
946
|
-
lineWidth: currentLineWidth,
|
|
947
|
-
lineColor: currentLineColor,
|
|
948
|
-
fillColor: isClosedPolygon ? currentFill : 'none',
|
|
949
|
-
});
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
});
|
|
953
|
-
|
|
954
|
-
return pathItems;
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
getPinsPath(): string {
|
|
958
|
-
const features = this.pins.map(item => item[1]);
|
|
959
|
-
const withAngle = Geometry.groupRotate(features, this.angle, this.mainOrigin);
|
|
960
|
-
const { path } = this.featuresToPath(withAngle);
|
|
961
|
-
return path;
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
getLabels(): Label[] {
|
|
965
|
-
return this.items.filter(item => item instanceof Label) as Label[];
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
private featuresToPath(items: Feature[]):
|
|
969
|
-
{path: string, isClosedPolygon: boolean} {
|
|
970
|
-
return Geometry.featuresToPath(items);
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
getBoundingBox(excludeLabels = false): {
|
|
974
|
-
width: number, height: number,
|
|
975
|
-
start: SimplePoint, end: SimplePoint
|
|
976
|
-
} {
|
|
977
|
-
// If excludeLabels is true, then do not add labels to the list
|
|
978
|
-
// of items to measure the boundaries.
|
|
979
|
-
|
|
980
|
-
const pinFeatures = this.pins.map(pin => {
|
|
981
|
-
return pin[1];
|
|
982
|
-
});
|
|
983
|
-
|
|
984
|
-
const drawingFeatures = this.items.reduce((accum, item) => {
|
|
985
|
-
if (!excludeLabels || (excludeLabels && !(item instanceof Label))){
|
|
986
|
-
if (!(item instanceof GeometryProp)){
|
|
987
|
-
accum.push(item);
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
return accum;
|
|
992
|
-
|
|
993
|
-
}, [] as Feature[]);
|
|
994
|
-
|
|
995
|
-
const measureItems = [...drawingFeatures, ...pinFeatures];
|
|
996
|
-
|
|
997
|
-
const withAngle = Geometry.groupRotate(measureItems, this.angle, this.mainOrigin);
|
|
998
|
-
|
|
999
|
-
return Geometry.groupBounds(withAngle);
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
getPinPosition(pinId: number): { start: [number, number], end: [number, number], angle: number } {
|
|
1003
|
-
const pin = this.pins.find(item => {
|
|
1004
|
-
return item[0] === pinId;
|
|
1005
|
-
});
|
|
1006
|
-
|
|
1007
|
-
if (pin) {
|
|
1008
|
-
const [pinId, feature, angle] = pin;
|
|
1009
|
-
|
|
1010
|
-
// Apply angle to feature
|
|
1011
|
-
|
|
1012
|
-
const withAngle = Geometry.rotateDegs(feature, this.angle, this.mainOrigin);
|
|
1013
|
-
const coords = Geometry.getCoords(withAngle);
|
|
1014
|
-
|
|
1015
|
-
return {
|
|
1016
|
-
start: coords[0],
|
|
1017
|
-
end: coords[1],
|
|
1018
|
-
angle,
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
export type SubExpressionCommand = [commandName: string,
|
|
1025
|
-
positionParams: any[],
|
|
1026
|
-
keywordParams: Map<string, any>];
|
|
1027
|
-
|
|
1028
|
-
export class SymbolDrawingCommands extends SymbolDrawing {
|
|
1029
|
-
|
|
1030
|
-
id = "";
|
|
1031
|
-
private commands: SubExpressionCommand[];
|
|
1032
|
-
|
|
1033
|
-
constructor(commands: SubExpressionCommand[]){
|
|
1034
|
-
super();
|
|
1035
|
-
this.commands = commands;
|
|
1036
|
-
this.id = Math.random().toString().slice(2);
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
getCommands(): SubExpressionCommand[] {
|
|
1040
|
-
return this.commands;
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
clone(): SymbolDrawingCommands {
|
|
1044
|
-
// Force a deep clone
|
|
1045
|
-
const tmpCommands: SubExpressionCommand[] = this.commands.map(item => {
|
|
1046
|
-
if (item[0] === PlaceHolderCommands.label) {
|
|
1047
|
-
const commandName = item[0];
|
|
1048
|
-
const positionParams = item[1];
|
|
1049
|
-
const keywordParams = item[2];
|
|
1050
|
-
|
|
1051
|
-
const newMap = new Map<string, any>();
|
|
1052
|
-
for (const [key, value] of keywordParams) {
|
|
1053
|
-
newMap.set(key, value);
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
return [commandName, positionParams, newMap];
|
|
1057
|
-
} else {
|
|
1058
|
-
return [...item];
|
|
1059
|
-
}
|
|
1060
|
-
});
|
|
1061
|
-
return new SymbolDrawingCommands(tmpCommands);
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
type SimplePoint = [x: number, y: number];
|
|
1066
|
-
|
|
1067
|
-
type SymbolPinLayout = {
|
|
1068
|
-
pinId: number,
|
|
1069
|
-
angle: number,
|
|
1070
|
-
text: string,
|
|
1071
|
-
start: {
|
|
1072
|
-
x: number, y: number
|
|
1073
|
-
},
|
|
1074
|
-
end: {
|
|
1075
|
-
x: number, y: number
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
export type SymbolPinDefintion = {
|
|
1080
|
-
side: string,
|
|
1081
|
-
pinId: number,
|
|
1082
|
-
text: string, // Display value at the pin
|
|
1083
|
-
position: number,
|
|
1084
|
-
}
|
|
1085
|
-
|