schematic-symbols 0.0.99 → 0.0.100

Sign up to get free protection for your applications and to get access to all the features.
package/drawing/arc.ts CHANGED
@@ -6,6 +6,7 @@ export function approximateArc(
6
6
  rx: number,
7
7
  ry: number,
8
8
  largeArcFlag: number,
9
+ sweepFlag: number,
9
10
  x2: number,
10
11
  y2: number,
11
12
  ): Point[] {
@@ -22,7 +23,8 @@ export function approximateArc(
22
23
  0.03 *
23
24
  Math.abs(Math.sin(t * Math.PI)) *
24
25
  Math.min(rx, ry) *
25
- (largeArcFlag ? 1 : -1)
26
+ (largeArcFlag ? 1 : -1) *
27
+ (sweepFlag ? -1 : 1)
26
28
  points.push({ x, y: y + curveY })
27
29
  }
28
30
  return points
package/drawing/getSvg.ts CHANGED
@@ -1,16 +1,24 @@
1
+ import { makeAnchorYUpPositive, makeYUpPositive } from "./utils/makeYUpPositive"
1
2
  import { mapColor } from "./mapColor"
2
3
  import { pathToSvgD } from "./pathToSvgD"
3
4
  import type { Point, Port, SchSymbol, TextPrimitive } from "./types"
4
5
 
5
- function createDiamondElement(center: Point, size = 0.05): string {
6
+ function createDiamondElement(
7
+ center: Point,
8
+ size = 0.05,
9
+ yUpPositive: boolean = true,
10
+ ): string {
6
11
  const { x, y } = center
7
12
  const halfSize = size / 2
8
- return `<path d="M ${x} ${y - halfSize} L ${x + halfSize} ${y} L ${x} ${
9
- y + halfSize
10
- } L ${x - halfSize} ${y} Z" fill="green" />`
13
+ return `<path d="M ${x} ${makeYUpPositive(y, yUpPositive) - halfSize} L ${x + halfSize} ${makeYUpPositive(y, yUpPositive)} L ${x} ${
14
+ makeYUpPositive(y, yUpPositive) + halfSize
15
+ } L ${x - halfSize} ${makeYUpPositive(y, yUpPositive)} Z" fill="green" />`
11
16
  }
12
17
 
13
- function createTextElement(primitive: TextPrimitive): {
18
+ function createTextElement(
19
+ primitive: TextPrimitive,
20
+ { yUpPositive }: { yUpPositive?: boolean },
21
+ ): {
14
22
  text: string
15
23
  anchor: string
16
24
  } {
@@ -58,16 +66,19 @@ function createTextElement(primitive: TextPrimitive): {
58
66
  }
59
67
 
60
68
  return {
61
- text: `<text x="${x}" y="${y}" dx="${dx}" dy="${dy}" text-anchor="${textAnchor}" style="font: ${
69
+ text: `<text x="${x}" y="${makeYUpPositive(y, yUpPositive)}" dx="${dx}" dy="${dy}" text-anchor="${textAnchor}" style="font: ${
62
70
  fontSize ?? 0.1
63
71
  }px monospace; fill: ${mapColor("primary")}">${text}</text>`,
64
72
  anchor: `<rect x="${x - 0.025 / 2}" y="${
65
- y - 0.025 / 2
73
+ makeYUpPositive(y, yUpPositive) - 0.025 / 2
66
74
  }" width="0.025" height="0.025" fill="blue" />`,
67
75
  }
68
76
  }
69
77
 
70
- function createPortElement(port: Port): string {
78
+ function createPortElement(
79
+ port: Port,
80
+ { yUpPositive }: { yUpPositive?: boolean },
81
+ ): string {
71
82
  const { x, y, labels } = port
72
83
  const rectSize = 0.05
73
84
  const labelFontSize = 0.08
@@ -75,10 +86,10 @@ function createPortElement(port: Port): string {
75
86
 
76
87
  return `
77
88
  <rect x="${x - rectSize / 2}" y="${
78
- y - rectSize / 2
89
+ makeYUpPositive(y, yUpPositive) - rectSize / 2
79
90
  }" width="${rectSize}" height="${rectSize}" fill="red" />
80
91
  <text x="${x - labelFontSize / 2}" y="${
81
- y + rectSize + labelFontSize / 2
92
+ makeYUpPositive(y, yUpPositive) + rectSize + labelFontSize / 2
82
93
  }" text-anchor="middle" style="font: ${labelFontSize}px monospace; fill: #833;">${label}</text>
83
94
  `
84
95
  }
@@ -92,19 +103,19 @@ export function getInnerSvg(
92
103
  const svgElements = primitives.map((primitive) => {
93
104
  switch (primitive.type) {
94
105
  case "path":
95
- return `<path d="${pathToSvgD(
96
- primitive.points,
97
- primitive.closed,
98
- )}" fill="${
106
+ return `<path d="${pathToSvgD(primitive.points, {
107
+ closed: primitive.closed,
108
+ yUpPositive: true,
109
+ })}" fill="${
99
110
  primitive.fill ? mapColor(primitive.color) : "none"
100
111
  }" stroke="${mapColor(
101
112
  primitive.color,
102
113
  )}" stroke-width="0.02" stroke-linecap="round" stroke-linejoin="round" />`
103
114
  case "text":
104
- const textElements = createTextElement(primitive)
115
+ const textElements = createTextElement(primitive, { yUpPositive: true })
105
116
  return textElements.text + (debug ? textElements.anchor : "")
106
117
  case "circle":
107
- return `<circle cx="${primitive.x}" cy="${primitive.y}" r="${
118
+ return `<circle cx="${primitive.x}" cy="${makeYUpPositive(primitive.y, true)}" r="${
108
119
  primitive.radius
109
120
  }" fill="${primitive.fill ? mapColor(primitive.color) : "none"}" ${
110
121
  !primitive.fill
@@ -112,7 +123,7 @@ export function getInnerSvg(
112
123
  : ""
113
124
  } />`
114
125
  case "box":
115
- return `<rect x="${primitive.x}" y="${primitive.y}" width="${
126
+ return `<rect x="${primitive.x}" y="${makeYUpPositive(primitive.y)}" width="${
116
127
  primitive.width
117
128
  }" height="${primitive.height}" fill="${mapColor("primary")}" />`
118
129
  default:
@@ -120,7 +131,9 @@ export function getInnerSvg(
120
131
  }
121
132
  })
122
133
 
123
- const portElements = ports.map(createPortElement).join("\n ")
134
+ const portElements = ports
135
+ .map((p) => createPortElement(p, { yUpPositive: true }))
136
+ .join("\n ")
124
137
 
125
138
  const centerDiamond = createDiamondElement(symbol.center)
126
139
 
@@ -140,7 +153,7 @@ export function getSvg(
140
153
  const h = size.height * bufferMultiple
141
154
  const viewBox = {
142
155
  x: symbol.center.x - w / 2,
143
- y: symbol.center.y - h / 2,
156
+ y: makeYUpPositive(symbol.center.y, true) - h / 2,
144
157
  width: w,
145
158
  height: h,
146
159
  }
@@ -1,8 +1,21 @@
1
1
  import type { Point } from "drawing"
2
+ import { makeYUpPositive } from "./utils/makeYUpPositive"
2
3
 
3
- export function pathToSvgD(points: Point[], closed: boolean = false): string {
4
+ export function pathToSvgD(
5
+ points: Point[],
6
+ {
7
+ closed = false,
8
+ yUpPositive = true,
9
+ }: {
10
+ closed?: boolean
11
+ yUpPositive?: boolean
12
+ },
13
+ ): string {
4
14
  const pathCommands = points
5
- .map((point, index) => `${index === 0 ? "M" : "L"}${point.x},${point.y}`)
15
+ .map(
16
+ (point, index) =>
17
+ `${index === 0 ? "M" : "L"}${point.x},${makeYUpPositive(point.y, yUpPositive)}`,
18
+ )
6
19
  .join(" ")
7
20
 
8
21
  return closed ? `${pathCommands} Z` : pathCommands
@@ -8,29 +8,29 @@ import type {
8
8
  } from "./types"
9
9
 
10
10
  // Update rotateAnchor to handle all anchor rotations based on orientation
11
- const rotateAnchor = (
11
+ const rotateRightFacingAnchor = (
12
12
  anchor: NinePointAnchor,
13
- orientation: "up" | "down" | "left" | "right" = "right",
13
+ newOrientation: "up" | "down" | "left" | "right" = "right",
14
14
  ): NinePointAnchor => {
15
- switch (orientation) {
16
- case "up":
15
+ switch (newOrientation) {
16
+ case "down":
17
17
  switch (anchor) {
18
18
  case "middle_top":
19
- return "middle_left"
20
- case "middle_bottom":
21
19
  return "middle_right"
20
+ case "middle_bottom":
21
+ return "middle_left"
22
22
  case "middle_left":
23
23
  return "middle_bottom"
24
24
  case "middle_right":
25
25
  return "middle_top"
26
26
  }
27
27
  break
28
- case "down":
28
+ case "up":
29
29
  switch (anchor) {
30
30
  case "middle_top":
31
- return "middle_right"
32
- case "middle_bottom":
33
31
  return "middle_left"
32
+ case "middle_bottom":
33
+ return "middle_right"
34
34
  case "middle_left":
35
35
  return "middle_top"
36
36
  case "middle_right":
@@ -213,21 +213,24 @@ export const flipSymbolOverYAxis = (
213
213
  }
214
214
  }
215
215
 
216
- export const rotateSymbol = (
216
+ export const rotateRightFacingSymbol = (
217
217
  symbol: SchSymbol,
218
- orientation?: "up" | "down" | "left" | "right",
219
- overrides?: Partial<SchSymbol>,
218
+ opts: {
219
+ newOrientation?: "up" | "down" | "left" | "right"
220
+ overrides?: Partial<SchSymbol>
221
+ },
220
222
  ): SchSymbol => {
223
+ const { newOrientation, overrides } = opts
221
224
  // Assuming the default orientation is "right"
222
225
  const angleMap = {
223
- up: -Math.PI / 2,
226
+ up: Math.PI / 2,
224
227
  right: 0,
225
- down: Math.PI / 2,
228
+ down: -Math.PI / 2,
226
229
  left: -Math.PI,
227
230
  }
228
231
 
229
232
  const transform = rotate(
230
- orientation ? angleMap[orientation] : Math.PI / 2,
233
+ newOrientation ? angleMap[newOrientation] : Math.PI / 2,
231
234
  symbol.center.x,
232
235
  symbol.center.y,
233
236
  )
@@ -250,9 +253,9 @@ export const rotateSymbol = (
250
253
  y: primitive.y,
251
254
  }) as Point
252
255
 
253
- primitive.anchor = rotateAnchor(
256
+ primitive.anchor = rotateRightFacingAnchor(
254
257
  primitive.anchor,
255
- orientation ?? "right",
258
+ newOrientation ?? "right",
256
259
  )
257
260
 
258
261
  return {
@@ -298,14 +301,27 @@ export const rotateSymbol = (
298
301
  ports: rotatedPorts,
299
302
  size: {
300
303
  width:
301
- orientation === "up" || orientation === "down"
304
+ newOrientation === "up" || newOrientation === "down"
302
305
  ? size.width
303
306
  : size.height,
304
307
  height:
305
- orientation === "up" || orientation === "down"
308
+ newOrientation === "up" || newOrientation === "down"
306
309
  ? size.height
307
310
  : size.width,
308
311
  },
309
312
  ...overrides,
310
313
  }
311
314
  }
315
+
316
+ /**
317
+ * @deprecated use rotateRightFacingSymbol instead
318
+ */
319
+ export const rotateSymbol = (
320
+ symbol: SchSymbol,
321
+ orientation: "up" | "down" | "left" | "right" = "down",
322
+ overrides: Partial<SchSymbol> = {},
323
+ ): SchSymbol =>
324
+ rotateRightFacingSymbol(symbol, {
325
+ newOrientation: orientation,
326
+ overrides,
327
+ })
@@ -58,6 +58,7 @@ export function svgPathToPoints(pathString: string): Point[] {
58
58
  rx,
59
59
  ry,
60
60
  largeArcFlag,
61
+ sweepFlag,
61
62
  x,
62
63
  y,
63
64
  )
@@ -0,0 +1,46 @@
1
+ import { NinePointAnchor } from "drawing/types"
2
+
3
+ /**
4
+ * In Inkscape and Websites, Y-up is NEGATIVE- meaning e.g. y=10 is BELOW y=0.
5
+ *
6
+ * Our symbols are defined with Y-up POSITIVE, meaning e.g. y=10 is ABOVE y=0.
7
+ *
8
+ * This function helps flip y positions so that you can convert from schematic
9
+ * symbol coordinates to SVG coordinates.
10
+ */
11
+ export const makeYUpPositive = (y: number, yUpPositive: boolean = true) => {
12
+ return yUpPositive ? -y : y
13
+ }
14
+
15
+ /**
16
+ * This function gives an intermediate anchor flip that can be used to determine
17
+ * how anchors should be interpreted when flipping in the Y-axis.
18
+ *
19
+ * It converts top_left -> bottom_left etc.
20
+ *
21
+ * y=1 top_left -------
22
+ * y=0 | |
23
+ * y=-1 -------------
24
+ *
25
+ * Y-up Negative
26
+ *
27
+ * y=-1 -------------
28
+ * y=0 | |
29
+ * y=1 bottom_left --
30
+ */
31
+ export const flipAnchorOverYAxis = (anchor: NinePointAnchor) => {
32
+ if (anchor === "top_left") return "bottom_left"
33
+ if (anchor === "top_right") return "bottom_right"
34
+ if (anchor === "bottom_left") return "top_left"
35
+ if (anchor === "bottom_right") return "top_right"
36
+ if (anchor === "middle_top") return "middle_bottom"
37
+ if (anchor === "middle_bottom") return "middle_top"
38
+ return anchor
39
+ }
40
+
41
+ export const makeAnchorYUpPositive = (
42
+ anchor: NinePointAnchor,
43
+ yUpPositive: boolean = true,
44
+ ) => {
45
+ return yUpPositive ? flipAnchorOverYAxis(anchor) : anchor
46
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "schematic-symbols",
3
3
  "main": "./dist/index.js",
4
- "version": "0.0.99",
4
+ "version": "0.0.100",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -12,14 +12,14 @@ export default defineSymbol({
12
12
  text: "{REF}",
13
13
  x: 0,
14
14
  y: -0.3594553499999995,
15
- anchor: "middle_bottom",
15
+ anchor: "middle_top",
16
16
  },
17
17
  {
18
18
  type: "text",
19
19
  text: "{VAL}",
20
20
  x: 0,
21
21
  y: 0.35,
22
- anchor: "middle_top",
22
+ anchor: "middle_bottom",
23
23
  },
24
24
  ] as any,
25
25
  ports: [
@@ -1,26 +1,8 @@
1
- import { rotateSymbol } from "drawing/rotateSymbol"
2
- import dc_voltmeter_horz from "./ac_voltmeter_horz"
3
- import { Primitive } from "drawing/types"
1
+ import { rotateRightFacingSymbol } from "drawing/rotateSymbol"
2
+ import ac_voltmeter_horz from "./ac_voltmeter_horz"
4
3
 
5
- const {
6
- 2: letter,
7
- 3: path1,
8
- 4: path2,
9
- 5: path3,
10
- 6: path4,
11
- ...rest
12
- } = dc_voltmeter_horz.primitives
13
-
14
- function isPrimitive(value: any): value is Primitive {
15
- return typeof value === "object"
16
- }
17
-
18
- const rotatedSymbol = rotateSymbol({
19
- ...dc_voltmeter_horz,
20
- primitives: Object.values(rest).filter(isPrimitive),
4
+ const rotatedSymbol = rotateRightFacingSymbol(ac_voltmeter_horz, {
5
+ newOrientation: "up",
21
6
  })
22
7
 
23
- export default {
24
- ...rotatedSymbol,
25
- primitives: [...rotatedSymbol.primitives, letter, path1, path2, path3, path4],
26
- }
8
+ export default rotatedSymbol
@@ -1,17 +1,10 @@
1
- import { rotateSymbol } from "drawing/rotateSymbol"
1
+ import { rotateRightFacingSymbol, rotateSymbol } from "drawing/rotateSymbol"
2
2
  import avalanche_diode_horz from "./avalanche_diode_horz"
3
3
 
4
4
  import type { TextPrimitive } from "drawing"
5
5
 
6
- const rotated = rotateSymbol(avalanche_diode_horz)
7
- const ref = rotated.primitives.find(
8
- (p) => p.type === "text" && p.text === "{REF}",
9
- )! as TextPrimitive
10
- const val = rotated.primitives.find(
11
- (p) => p.type === "text" && p.text === "{VAL}",
12
- )! as TextPrimitive
13
-
14
- ref.anchor = "middle_left"
15
- val.anchor = "middle_right"
6
+ const rotated = rotateRightFacingSymbol(avalanche_diode_horz, {
7
+ newOrientation: "down",
8
+ })
16
9
 
17
10
  export default rotated
@@ -1,4 +1,6 @@
1
- import { rotateSymbol } from "drawing/rotateSymbol"
1
+ import { rotateRightFacingSymbol } from "drawing/rotateSymbol"
2
2
  import battery_horz from "./battery_horz"
3
3
 
4
- export default rotateSymbol(battery_horz)
4
+ export default rotateRightFacingSymbol(battery_horz, {
5
+ newOrientation: "up",
6
+ })
@@ -14,14 +14,14 @@ export default defineSymbol({
14
14
  text: "{REF}",
15
15
  x: -0.012864500000000056,
16
16
  y: -0.4150086999999978,
17
- anchor: "middle_bottom",
17
+ anchor: "middle_top",
18
18
  },
19
19
  {
20
20
  type: "text",
21
21
  text: "{VAL}",
22
22
  x: -0.003850500000000423,
23
23
  y: 0.4250087000000011,
24
- anchor: "middle_top",
24
+ anchor: "middle_bottom",
25
25
  },
26
26
  ] as any,
27
27
  ports: [
@@ -1,20 +1,10 @@
1
1
  import { defineSymbol } from "drawing/defineSymbol"
2
2
  import svgJson from "assets/generated/diode.json"
3
- import { Primitive } from "drawing/types"
3
+ import { modifySymbol } from "scripts/lib/modify-symbol/modify-symbol"
4
4
 
5
- const { paths, texts, bounds, refblocks, circles } = svgJson
6
-
7
- export default defineSymbol({
8
- primitives: [
9
- ...Object.values(paths),
10
- ...Object.values(circles),
11
- { ...texts.top1, anchor: "middle_bottom" },
12
- { ...texts.bottom1, anchor: "middle_top" },
13
- ] as Primitive[],
14
- ports: [
15
- { ...refblocks.left1, labels: ["1"] }, // TODO add more "standard" labels
16
- { ...refblocks.right1, labels: ["2"] }, // TODO add more "standard" labels
17
- ],
18
- size: { width: bounds.width, height: bounds.height },
19
- center: { x: bounds.centerX, y: bounds.centerY },
20
- })
5
+ export default modifySymbol(svgJson)
6
+ .labelPort("left1", ["1", "pos"])
7
+ .labelPort("right1", ["2", "neg"])
8
+ .changeTextAnchor("{REF}", "middle_bottom")
9
+ .changeTextAnchor("{VAL}", "middle_top")
10
+ .build()
@@ -11,7 +11,7 @@ export default defineSymbol({
11
11
  type: "text",
12
12
  text: "{VAL}",
13
13
  x: 0,
14
- y: 0.2,
14
+ y: -0.2,
15
15
  anchor: "middle_top",
16
16
  },
17
17
  ] as any,
@@ -15,20 +15,20 @@ export const horizontalSymbol = defineSymbol({
15
15
  type: "text",
16
16
  text: "{REF}", // REF label for horizontal
17
17
  x: -0.1, // Adjust this for the horizontal positioning of REF
18
- y: -0.8, // Adjust this for the vertical positioning of REF
18
+ y: 0.8, // Adjust this for the vertical positioning of REF
19
19
  anchor: "middle_bottom", // Horizontal anchor for REF
20
20
  },
21
21
  {
22
22
  type: "text",
23
23
  text: "{VAL}", // VAL label for horizontal
24
24
  x: -0.1, // Adjust for horizontal positioning of VAL
25
- y: -0.1, // Adjust for vertical positioning of VAL
25
+ y: 0.1, // Adjust for vertical positioning of VAL
26
26
  anchor: "middle_top", // Horizontal anchor for VAL
27
27
  },
28
28
  ] as Primitive[],
29
29
  ports: [{ ...refblocks.top1, labels: ["1"] }],
30
- size: { width: bounds.width, height: bounds.height },
31
- center: { x: bounds.centerX - 0.09, y: bounds.centerY - 0.45 },
30
+ size: { width: 1, height: 1 },
31
+ center: { x: 0, y: 0.4 },
32
32
  })
33
33
 
34
34
  // Vertical orientation symbol
@@ -1,34 +1,7 @@
1
1
  import { defineSymbol } from "drawing/defineSymbol"
2
2
  import svgJson from "assets/generated/ground.json"
3
3
  import { Primitive } from "drawing/types"
4
- import { rotateSymbol } from "drawing/rotateSymbol"
4
+ import groundHorz from "./ground_horz"
5
+ import { modifySymbol } from "scripts/lib/modify-symbol/modify-symbol"
5
6
 
6
- // Extract paths, bounds, etc.
7
- const { paths, circles, bounds, refblocks } = svgJson
8
-
9
- export const verticalSymbol = defineSymbol({
10
- primitives: [
11
- ...Object.values(paths),
12
- ...Object.values(circles),
13
- {
14
- type: "text",
15
- text: "{REF}", // REF label for vertical
16
- x: -0.015, // Adjust this for the horizontal positioning of REF
17
- y: -0.75, // Adjust this for the vertical positioning of REF
18
- anchor: "middle_bottom", // Vertical anchor for REF
19
- },
20
- {
21
- type: "text",
22
- text: "{VAL}", // VAL label for vertical
23
- x: -0.015, // Adjust for horizontal positioning of VAL
24
- y: -0.12, // Adjust for vertical positioning of VAL
25
- anchor: "middle_top", // Vertical anchor for VAL
26
- },
27
- ] as Primitive[],
28
- ports: [{ ...refblocks.top1, labels: ["1"] }],
29
- size: { width: bounds.width, height: bounds.height },
30
- center: { x: bounds.centerX, y: bounds.centerY - 0.45 },
31
- })
32
-
33
- // Export vertical symbol (rotated 90 degrees from original)
34
- export default rotateSymbol(verticalSymbol)
7
+ export default modifySymbol(groundHorz).rotateRightFacingSymbol("down").build()
@@ -1,19 +1,10 @@
1
1
  import { defineSymbol } from "drawing/defineSymbol"
2
2
  import svgJson from "assets/generated/schottky_diode.json"
3
+ import { modifySymbol } from "scripts/lib/modify-symbol/modify-symbol"
3
4
 
4
- const { paths, texts, bounds, refblocks, circles } = svgJson
5
-
6
- export default defineSymbol({
7
- primitives: [
8
- ...Object.values(paths),
9
- ...Object.values(circles),
10
- { ...texts.top1, anchor: "middle_bottom" },
11
- { ...texts.bottom1, anchor: "middle_top" },
12
- ] as any,
13
- ports: [
14
- { ...refblocks.left1, labels: ["1"] }, // TODO add more "standard" labels
15
- { ...refblocks.right1, labels: ["2"] }, // TODO add more "standard" labels
16
- ],
17
- size: { width: bounds.width, height: bounds.height },
18
- center: { x: bounds.centerX, y: bounds.centerY },
19
- })
5
+ export default modifySymbol(svgJson)
6
+ .labelPort("left1", ["1", "pos"])
7
+ .labelPort("right1", ["2", "neg"])
8
+ .changeTextAnchor("{VAL}", "middle_bottom")
9
+ .changeTextAnchor("{REF}", "middle_top")
10
+ .build()