schematic-symbols 0.0.98 → 0.0.100

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/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.98",
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()