circuit-to-svg 0.0.254 → 0.0.255

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/index.js CHANGED
@@ -627,7 +627,9 @@ function createSvgObjectsFromPcbFabricationNoteDimension(dimension, ctx) {
627
627
  arrow_size,
628
628
  layer,
629
629
  pcb_component_id,
630
- pcb_fabrication_note_dimension_id
630
+ pcb_fabrication_note_dimension_id,
631
+ offset_distance,
632
+ offset_direction
631
633
  } = dimension;
632
634
  if (layerFilter && layer && layer !== layerFilter) return [];
633
635
  if (!from || !to || typeof from !== "object" || typeof to !== "object") {
@@ -658,17 +660,30 @@ function createSvgObjectsFromPcbFabricationNoteDimension(dimension, ctx) {
658
660
  return [];
659
661
  }
660
662
  const perpendicular = { x: -direction.y, y: direction.x };
663
+ const hasOffsetDirection = offset_direction && typeof offset_direction.x === "number" && typeof offset_direction.y === "number";
664
+ const normalizedOffsetDirection = hasOffsetDirection ? normalize({ x: offset_direction.x, y: offset_direction.y }) : { x: 0, y: 0 };
665
+ const offsetMagnitude = typeof offset_distance === "number" ? offset_distance : 0;
666
+ const offsetVector = {
667
+ x: normalizedOffsetDirection.x * offsetMagnitude,
668
+ y: normalizedOffsetDirection.y * offsetMagnitude
669
+ };
670
+ const applyOffset = (point) => ({
671
+ x: point.x + offsetVector.x,
672
+ y: point.y + offsetVector.y
673
+ });
674
+ const fromOffset = applyOffset(from);
675
+ const toOffset = applyOffset(to);
661
676
  const arrowHalfWidth = arrowSize / 2;
662
677
  const fromBase = {
663
- x: from.x + direction.x * arrowSize,
664
- y: from.y + direction.y * arrowSize
678
+ x: fromOffset.x + direction.x * arrowSize,
679
+ y: fromOffset.y + direction.y * arrowSize
665
680
  };
666
681
  const toBase = {
667
- x: to.x - direction.x * arrowSize,
668
- y: to.y - direction.y * arrowSize
682
+ x: toOffset.x - direction.x * arrowSize,
683
+ y: toOffset.y - direction.y * arrowSize
669
684
  };
670
685
  const fromTriangle = [
671
- toScreen(from),
686
+ toScreen(fromOffset),
672
687
  toScreen({
673
688
  x: fromBase.x + perpendicular.x * arrowHalfWidth,
674
689
  y: fromBase.y + perpendicular.y * arrowHalfWidth
@@ -679,7 +694,7 @@ function createSvgObjectsFromPcbFabricationNoteDimension(dimension, ctx) {
679
694
  })
680
695
  ];
681
696
  const toTriangle = [
682
- toScreen(to),
697
+ toScreen(toOffset),
683
698
  toScreen({
684
699
  x: toBase.x + perpendicular.x * arrowHalfWidth,
685
700
  y: toBase.y + perpendicular.y * arrowHalfWidth
@@ -696,9 +711,34 @@ function createSvgObjectsFromPcbFabricationNoteDimension(dimension, ctx) {
696
711
  const [lineEndX, lineEndY] = applyToPoint6(transform, [toBase.x, toBase.y]);
697
712
  const strokeWidth = arrowSize / 5 * Math.abs(transform.a);
698
713
  const lineColor = color || "rgba(255,255,255,0.5)";
714
+ const extensionDirection = hasOffsetDirection && (Math.abs(normalizedOffsetDirection.x) > Number.EPSILON || Math.abs(normalizedOffsetDirection.y) > Number.EPSILON) ? normalizedOffsetDirection : perpendicular;
715
+ const extensionLength = offsetMagnitude + arrowSize;
716
+ const createExtensionLine = (anchor) => {
717
+ const endPoint = {
718
+ x: anchor.x + extensionDirection.x * extensionLength,
719
+ y: anchor.y + extensionDirection.y * extensionLength
720
+ };
721
+ const [startX, startY] = applyToPoint6(transform, [anchor.x, anchor.y]);
722
+ const [endX, endY] = applyToPoint6(transform, [endPoint.x, endPoint.y]);
723
+ return {
724
+ name: "path",
725
+ type: "element",
726
+ value: "",
727
+ attributes: {
728
+ d: `M ${startX} ${startY} L ${endX} ${endY}`,
729
+ stroke: lineColor,
730
+ fill: "none",
731
+ "stroke-width": strokeWidth.toString(),
732
+ "stroke-linecap": "round",
733
+ class: "pcb-fabrication-note-dimension-extension"
734
+ },
735
+ children: []
736
+ };
737
+ };
738
+ const extensionSegments = [createExtensionLine(from), createExtensionLine(to)];
699
739
  const midPoint = {
700
- x: (from.x + to.x) / 2,
701
- y: (from.y + to.y) / 2
740
+ x: (from.x + to.x) / 2 + offsetVector.x,
741
+ y: (from.y + to.y) / 2 + offsetVector.y
702
742
  };
703
743
  const textOffset = arrowSize * 1.5;
704
744
  const textPoint = {
@@ -706,8 +746,25 @@ function createSvgObjectsFromPcbFabricationNoteDimension(dimension, ctx) {
706
746
  y: midPoint.y + perpendicular.y * textOffset
707
747
  };
708
748
  const [textX, textY] = applyToPoint6(transform, [textPoint.x, textPoint.y]);
749
+ const [screenFromX, screenFromY] = applyToPoint6(transform, [
750
+ fromOffset.x,
751
+ fromOffset.y
752
+ ]);
753
+ const [screenToX, screenToY] = applyToPoint6(transform, [
754
+ toOffset.x,
755
+ toOffset.y
756
+ ]);
757
+ const screenDirection = normalize({
758
+ x: screenToX - screenFromX,
759
+ y: screenToY - screenFromY
760
+ });
761
+ let textAngle = Math.atan2(screenDirection.y, screenDirection.x) * 180 / Math.PI;
762
+ if (textAngle > 90 || textAngle < -90) {
763
+ textAngle += 180;
764
+ }
709
765
  const transformedFontSize = font_size * Math.abs(transform.a);
710
766
  const children = [
767
+ ...extensionSegments,
711
768
  {
712
769
  name: "path",
713
770
  type: "element",
@@ -758,7 +815,8 @@ function createSvgObjectsFromPcbFabricationNoteDimension(dimension, ctx) {
758
815
  "font-family": "Arial, sans-serif",
759
816
  "text-anchor": "middle",
760
817
  "dominant-baseline": "central",
761
- class: "pcb-fabrication-note-dimension-text"
818
+ class: "pcb-fabrication-note-dimension-text",
819
+ transform: `rotate(${textAngle} ${textX} ${textY})`
762
820
  },
763
821
  children: [
764
822
  {
@@ -1049,7 +1107,16 @@ function toPath2(points) {
1049
1107
  }
1050
1108
  function createSvgObjectsFromPcbNoteDimension(dimension, ctx) {
1051
1109
  const { transform } = ctx;
1052
- const { from, to, text, font_size = 1, color, arrow_size } = dimension;
1110
+ const {
1111
+ from,
1112
+ to,
1113
+ text,
1114
+ font_size = 1,
1115
+ color,
1116
+ arrow_size,
1117
+ offset_distance,
1118
+ offset_direction
1119
+ } = dimension;
1053
1120
  if (!from || !to) {
1054
1121
  console.error("Invalid pcb_note_dimension endpoints", { from, to });
1055
1122
  return [];
@@ -1063,17 +1130,30 @@ function createSvgObjectsFromPcbNoteDimension(dimension, ctx) {
1063
1130
  return [];
1064
1131
  }
1065
1132
  const perpendicular = { x: -direction.y, y: direction.x };
1133
+ const hasOffsetDirection = offset_direction && typeof offset_direction.x === "number" && typeof offset_direction.y === "number";
1134
+ const normalizedOffsetDirection = hasOffsetDirection ? normalize2({ x: offset_direction.x, y: offset_direction.y }) : { x: 0, y: 0 };
1135
+ const offsetMagnitude = typeof offset_distance === "number" ? offset_distance : 0;
1136
+ const offsetVector = {
1137
+ x: normalizedOffsetDirection.x * offsetMagnitude,
1138
+ y: normalizedOffsetDirection.y * offsetMagnitude
1139
+ };
1140
+ const applyOffset = (point) => ({
1141
+ x: point.x + offsetVector.x,
1142
+ y: point.y + offsetVector.y
1143
+ });
1144
+ const fromOffset = applyOffset(from);
1145
+ const toOffset = applyOffset(to);
1066
1146
  const arrowHalfWidth = arrow_size / 2;
1067
1147
  const fromBase = {
1068
- x: from.x + direction.x * arrow_size,
1069
- y: from.y + direction.y * arrow_size
1148
+ x: fromOffset.x + direction.x * arrow_size,
1149
+ y: fromOffset.y + direction.y * arrow_size
1070
1150
  };
1071
1151
  const toBase = {
1072
- x: to.x - direction.x * arrow_size,
1073
- y: to.y - direction.y * arrow_size
1152
+ x: toOffset.x - direction.x * arrow_size,
1153
+ y: toOffset.y - direction.y * arrow_size
1074
1154
  };
1075
1155
  const fromTriangle = [
1076
- toScreen(from),
1156
+ toScreen(fromOffset),
1077
1157
  toScreen({
1078
1158
  x: fromBase.x + perpendicular.x * arrowHalfWidth,
1079
1159
  y: fromBase.y + perpendicular.y * arrowHalfWidth
@@ -1084,7 +1164,7 @@ function createSvgObjectsFromPcbNoteDimension(dimension, ctx) {
1084
1164
  })
1085
1165
  ];
1086
1166
  const toTriangle = [
1087
- toScreen(to),
1167
+ toScreen(toOffset),
1088
1168
  toScreen({
1089
1169
  x: toBase.x + perpendicular.x * arrowHalfWidth,
1090
1170
  y: toBase.y + perpendicular.y * arrowHalfWidth
@@ -1101,9 +1181,34 @@ function createSvgObjectsFromPcbNoteDimension(dimension, ctx) {
1101
1181
  const [lineEndX, lineEndY] = applyToPoint7(transform, [toBase.x, toBase.y]);
1102
1182
  const strokeWidth = arrow_size / 5 * Math.abs(transform.a);
1103
1183
  const lineColor = color || colorMap.board.user_2;
1184
+ const extensionDirection = hasOffsetDirection && (Math.abs(normalizedOffsetDirection.x) > Number.EPSILON || Math.abs(normalizedOffsetDirection.y) > Number.EPSILON) ? normalizedOffsetDirection : perpendicular;
1185
+ const extensionLength = offsetMagnitude + arrow_size;
1186
+ const createExtensionLine = (anchor) => {
1187
+ const endPoint = {
1188
+ x: anchor.x + extensionDirection.x * extensionLength,
1189
+ y: anchor.y + extensionDirection.y * extensionLength
1190
+ };
1191
+ const [startX, startY] = applyToPoint7(transform, [anchor.x, anchor.y]);
1192
+ const [endX, endY] = applyToPoint7(transform, [endPoint.x, endPoint.y]);
1193
+ return {
1194
+ name: "path",
1195
+ type: "element",
1196
+ value: "",
1197
+ attributes: {
1198
+ d: `M ${startX} ${startY} L ${endX} ${endY}`,
1199
+ stroke: lineColor,
1200
+ fill: "none",
1201
+ "stroke-width": strokeWidth.toString(),
1202
+ "stroke-linecap": "round",
1203
+ class: "pcb-note-dimension-extension"
1204
+ },
1205
+ children: []
1206
+ };
1207
+ };
1208
+ const extensionSegments = [createExtensionLine(from), createExtensionLine(to)];
1104
1209
  const midPoint = {
1105
- x: (from.x + to.x) / 2,
1106
- y: (from.y + to.y) / 2
1210
+ x: (from.x + to.x) / 2 + offsetVector.x,
1211
+ y: (from.y + to.y) / 2 + offsetVector.y
1107
1212
  };
1108
1213
  const textOffset = arrow_size * 1.5;
1109
1214
  const textPoint = {
@@ -1111,8 +1216,25 @@ function createSvgObjectsFromPcbNoteDimension(dimension, ctx) {
1111
1216
  y: midPoint.y + perpendicular.y * textOffset
1112
1217
  };
1113
1218
  const [textX, textY] = applyToPoint7(transform, [textPoint.x, textPoint.y]);
1219
+ const [screenFromX, screenFromY] = applyToPoint7(transform, [
1220
+ fromOffset.x,
1221
+ fromOffset.y
1222
+ ]);
1223
+ const [screenToX, screenToY] = applyToPoint7(transform, [
1224
+ toOffset.x,
1225
+ toOffset.y
1226
+ ]);
1227
+ const screenDirection = normalize2({
1228
+ x: screenToX - screenFromX,
1229
+ y: screenToY - screenFromY
1230
+ });
1231
+ let textAngle = Math.atan2(screenDirection.y, screenDirection.x) * 180 / Math.PI;
1232
+ if (textAngle > 90 || textAngle < -90) {
1233
+ textAngle += 180;
1234
+ }
1114
1235
  const transformedFontSize = font_size * Math.abs(transform.a);
1115
1236
  const children = [
1237
+ ...extensionSegments,
1116
1238
  {
1117
1239
  name: "path",
1118
1240
  type: "element",
@@ -1163,7 +1285,8 @@ function createSvgObjectsFromPcbNoteDimension(dimension, ctx) {
1163
1285
  "font-family": "Arial, sans-serif",
1164
1286
  "text-anchor": "middle",
1165
1287
  "dominant-baseline": "central",
1166
- class: "pcb-note-dimension-text"
1288
+ class: "pcb-note-dimension-text",
1289
+ transform: `rotate(${textAngle} ${textX} ${textY})`
1167
1290
  },
1168
1291
  children: [
1169
1292
  {
@@ -3348,7 +3471,7 @@ function getSoftwareUsedString(circuitJson) {
3348
3471
  var package_default = {
3349
3472
  name: "circuit-to-svg",
3350
3473
  type: "module",
3351
- version: "0.0.253",
3474
+ version: "0.0.254",
3352
3475
  description: "Convert Circuit JSON to SVG",
3353
3476
  main: "dist/index.js",
3354
3477
  files: [
@@ -3372,7 +3495,7 @@ var package_default = {
3372
3495
  "bun-match-svg": "^0.0.12",
3373
3496
  esbuild: "^0.20.2",
3374
3497
  "performance-now": "^2.1.0",
3375
- "circuit-json": "^0.0.288",
3498
+ "circuit-json": "^0.0.292",
3376
3499
  react: "19.1.0",
3377
3500
  "react-cosmos": "7.0.0",
3378
3501
  "react-cosmos-plugin-vite": "7.0.0",