Skip to content

Commit a239e3e

Browse files
committed
Triangle-walk, draw triangles
1 parent 9a1ee8b commit a239e3e

File tree

8 files changed

+252
-55
lines changed

8 files changed

+252
-55
lines changed

app.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,32 @@ func (a *App) SetLastVideoSource(id, label string) {
269269
a.updateLastVideoSource(id, label)
270270
}
271271

272+
func (a *App) GetTriangles() []Triangle {
273+
a.mu.Lock()
274+
defer a.mu.Unlock()
275+
276+
// Grab the first available interpolator (all share the same geometry)
277+
for _, interp := range a.linearInterpolators {
278+
numEdges := len(interp.tri.Triangles)
279+
numTriangles := numEdges / 3
280+
triangles := make([]Triangle, 0, numTriangles)
281+
for i := 0; i < numTriangles; i++ {
282+
idx := i * 3
283+
a := interp.points[interp.tri.Triangles[idx]]
284+
b := interp.points[interp.tri.Triangles[idx+1]]
285+
c := interp.points[interp.tri.Triangles[idx+2]]
286+
triangles = append(triangles, Triangle{
287+
Ax: a.X, Ay: a.Y,
288+
Bx: b.X, By: b.Y,
289+
Cx: c.X, Cy: c.Y,
290+
})
291+
}
292+
return triangles
293+
}
294+
295+
return []Triangle{}
296+
}
297+
272298
func (a *App) Log(message string) {
273299
LogInfo("[Frontend] %s", message)
274300
}

frontend/src/App.svelte

Lines changed: 120 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
MousePos,
2323
Point,
2424
SACNConfig,
25+
Triangle,
2526
} from "./types";
2627
import {
2728
calcPan,
@@ -62,6 +63,9 @@
6263
6364
let showMousePosition = false;
6465
let showCalibrationPoints = false;
66+
let showTriangles = false;
67+
let triangles = writable<Triangle[]>([]);
68+
let activeTriangleIndex: number | null = null;
6569
let showFixtureConfiguration = false;
6670
let showSACNConfiguration = false;
6771
let showSettingsMenu = false;
@@ -81,7 +85,7 @@
8185
fixtures,
8286
get(calibrationPoints),
8387
);
84-
App.SetFixtures(goFixtures);
88+
App.SetFixtures(goFixtures).then(fetchTriangles);
8589
});
8690
8791
calibrationPoints.subscribe((calibrationPoints) => {
@@ -90,7 +94,7 @@
9094
9195
let goCalibrationPoints: { [id: string]: main.CalibrationPoint } =
9296
convertCalibrationPointsToGo(calibrationPoints);
93-
App.SetCalibrationPoints(goCalibrationPoints);
97+
App.SetCalibrationPoints(goCalibrationPoints).then(fetchTriangles);
9498
});
9599
96100
onMount(() => {
@@ -232,14 +236,6 @@
232236
});
233237
});
234238
235-
const toggleShowMousePosition = () => {
236-
showMousePosition = !showMousePosition;
237-
};
238-
239-
const toggleShowCalibrationPoints = () => {
240-
showCalibrationPoints = !showCalibrationPoints;
241-
};
242-
243239
const toggleShowFixtureConfiguration = () => {
244240
showFixtureConfiguration = !showFixtureConfiguration;
245241
};
@@ -252,6 +248,33 @@
252248
showSettingsMenu = !showSettingsMenu;
253249
};
254250
251+
async function fetchTriangles() {
252+
try {
253+
activeTriangleIndex = null;
254+
const result = await App.GetTriangles();
255+
triangles.set(
256+
(result || []).map((t: any) => ({
257+
ax: t.Ax, ay: t.Ay,
258+
bx: t.Bx, by: t.By,
259+
cx: t.Cx, cy: t.Cy,
260+
}))
261+
);
262+
} catch (err) {
263+
App.Log(`Failed to fetch triangles: ${err}`);
264+
}
265+
}
266+
267+
function pointInTriangle(px: number, py: number, t: Triangle): boolean {
268+
const d1 = (px - t.bx) * (t.ay - t.by) - (t.ax - t.bx) * (py - t.by);
269+
const d2 = (px - t.cx) * (t.by - t.cy) - (t.bx - t.cx) * (py - t.cy);
270+
const d3 = (px - t.ax) * (t.cy - t.ay) - (t.cx - t.ax) * (py - t.ay);
271+
272+
const hasNeg = (d1 < 0) || (d2 < 0) || (d3 < 0);
273+
const hasPos = (d1 > 0) || (d2 > 0) || (d3 > 0);
274+
275+
return !(hasNeg && hasPos);
276+
}
277+
255278
function getNewCalibrationName() {
256279
calibrationPointCounter.update((value) => {
257280
return value + 1;
@@ -682,6 +705,18 @@
682705
683706
mousePos.set({ x, y });
684707
708+
if (showTriangles) {
709+
const tris = get(triangles);
710+
let found: number | null = null;
711+
for (let i = 0; i < tris.length; i++) {
712+
if (pointInTriangle(x, y, tris[i])) {
713+
found = i;
714+
break;
715+
}
716+
}
717+
activeTriangleIndex = found;
718+
}
719+
685720
if (
686721
get(currentlyCalibrating) !== null &&
687722
!calibrateForOnePointSelectCalibrationPoint
@@ -808,6 +843,32 @@
808843
on:click={handleClickOnVideo}
809844
>
810845
<svg class="video-cover-svg">
846+
{#if showTriangles}
847+
{#each $triangles as tri, index}
848+
<line
849+
class="triangle-line {activeTriangleIndex === index ? 'triangle-active' : ''}"
850+
x1="{tri.ax * 100}%"
851+
y1="{tri.ay * 100}%"
852+
x2="{tri.bx * 100}%"
853+
y2="{tri.by * 100}%"
854+
></line>
855+
<line
856+
class="triangle-line {activeTriangleIndex === index ? 'triangle-active' : ''}"
857+
x1="{tri.bx * 100}%"
858+
y1="{tri.by * 100}%"
859+
x2="{tri.cx * 100}%"
860+
y2="{tri.cy * 100}%"
861+
></line>
862+
<line
863+
class="triangle-line {activeTriangleIndex === index ? 'triangle-active' : ''}"
864+
x1="{tri.cx * 100}%"
865+
y1="{tri.cy * 100}%"
866+
x2="{tri.ax * 100}%"
867+
y2="{tri.ay * 100}%"
868+
></line>
869+
{/each}
870+
{/if}
871+
811872
{#each $calibrationPointOutline as point, index}
812873
<line
813874
class="outline-line"
@@ -832,6 +893,13 @@
832893
></line>
833894
{/if}
834895
</svg>
896+
{#if showTriangles && activeTriangleIndex !== null && activeTriangleIndex < $triangles.length}
897+
{@const tri = $triangles[activeTriangleIndex]}
898+
<div
899+
class="triangle-fill"
900+
style="clip-path: polygon({tri.ax * 100}% {tri.ay * 100}%, {tri.bx * 100}% {tri.by * 100}%, {tri.cx * 100}% {tri.cy * 100}%);"
901+
></div>
902+
{/if}
835903
{#if showCalibrationPoints}
836904
{#each Object.values($calibrationPoints) as calibrationPoint (calibrationPoint.id)}
837905
<div
@@ -966,16 +1034,18 @@
9661034
Remove Calibration Point
9671035
</button>
9681036
<div class="settings-separator"></div>
969-
<button on:click={toggleShowMousePosition}
970-
>{showMousePosition
971-
? "Hide Mouse Position"
972-
: "Show Mouse Position"}</button
973-
>
974-
<button on:click={toggleShowCalibrationPoints}>
975-
{showCalibrationPoints
976-
? "Hide Calibration Points"
977-
: "Show Calibration Points"}
978-
</button>
1037+
<label class="checkbox-label">
1038+
<input type="checkbox" bind:checked={showMousePosition} />
1039+
Show Mouse Position
1040+
</label>
1041+
<label class="checkbox-label">
1042+
<input type="checkbox" bind:checked={showCalibrationPoints} />
1043+
Show Calibration Points
1044+
</label>
1045+
<label class="checkbox-label">
1046+
<input type="checkbox" bind:checked={showTriangles} />
1047+
Draw Triangles
1048+
</label>
9791049
</div>
9801050
<Info
9811051
bind:addingCalibrationPoint
@@ -1138,6 +1208,36 @@
11381208
box-sizing: border-box;
11391209
}
11401210
1211+
.triangle-line {
1212+
stroke: var(--accent-orange);
1213+
stroke-width: 2px;
1214+
stroke-opacity: 0.7;
1215+
}
1216+
1217+
.triangle-line.triangle-active {
1218+
stroke: var(--accent-blue);
1219+
stroke-width: 3px;
1220+
stroke-opacity: 1;
1221+
}
1222+
1223+
.triangle-fill {
1224+
position: absolute;
1225+
top: 0;
1226+
left: 0;
1227+
width: 100%;
1228+
height: 100%;
1229+
background: var(--accent-blue);
1230+
opacity: 0.15;
1231+
pointer-events: none;
1232+
}
1233+
1234+
.checkbox-label {
1235+
display: flex;
1236+
align-items: center;
1237+
gap: 8px;
1238+
cursor: pointer;
1239+
}
1240+
11411241
.settings-separator {
11421242
margin-top: 12px;
11431243
}

frontend/src/types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ export interface SACNConfig {
4747
destinations: string[];
4848
}
4949

50+
export interface Triangle {
51+
ax: number;
52+
ay: number;
53+
bx: number;
54+
by: number;
55+
cx: number;
56+
cy: number;
57+
}
58+
5059
export interface CalibratingFixture {
5160
fixture_id: string;
5261
calibration_point_id: string;

frontend/wailsjs/go/main/App.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export function GetLastSessionInfo():Promise<main.LastSessionInfo>;
1010

1111
export function GetSACNConfig():Promise<main.SACNConfig>;
1212

13+
export function GetTriangles():Promise<Array<main.Triangle>>;
14+
1315
export function LoadFile():Promise<string>;
1416

1517
export function LoadFileFromPath(arg1:string):Promise<string>;
@@ -30,4 +32,4 @@ export function SetPanTiltForFixture(arg1:string,arg2:number,arg3:number):Promis
3032

3133
export function SetSACNConfig(arg1:main.SACNConfig):Promise<void>;
3234

33-
export function TypeExporter(arg1:main.CalibrationPoint,arg2:main.CalibratedCalibrationPoint,arg3:main.Fixture,arg4:main.SACNConfig,arg5:main.DMXData,arg6:main.Point):Promise<void>;
35+
export function TypeExporter(arg1:main.CalibrationPoint,arg2:main.CalibratedCalibrationPoint,arg3:main.Fixture,arg4:main.SACNConfig,arg5:main.DMXData,arg6:main.Point,arg7:main.Triangle):Promise<void>;

frontend/wailsjs/go/main/App.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ export function GetSACNConfig() {
1818
return window['go']['main']['App']['GetSACNConfig']();
1919
}
2020

21+
export function GetTriangles() {
22+
return window['go']['main']['App']['GetTriangles']();
23+
}
24+
2125
export function LoadFile() {
2226
return window['go']['main']['App']['LoadFile']();
2327
}
@@ -58,6 +62,6 @@ export function SetSACNConfig(arg1) {
5862
return window['go']['main']['App']['SetSACNConfig'](arg1);
5963
}
6064

61-
export function TypeExporter(arg1, arg2, arg3, arg4, arg5, arg6) {
62-
return window['go']['main']['App']['TypeExporter'](arg1, arg2, arg3, arg4, arg5, arg6);
65+
export function TypeExporter(arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
66+
return window['go']['main']['App']['TypeExporter'](arg1, arg2, arg3, arg4, arg5, arg6, arg7);
6367
}

frontend/wailsjs/go/models.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,28 @@ export namespace main {
136136
this.Destinations = source["Destinations"];
137137
}
138138
}
139+
export class Triangle {
140+
Ax: number;
141+
Ay: number;
142+
Bx: number;
143+
By: number;
144+
Cx: number;
145+
Cy: number;
146+
147+
static createFrom(source: any = {}) {
148+
return new Triangle(source);
149+
}
150+
151+
constructor(source: any = {}) {
152+
if ('string' === typeof source) source = JSON.parse(source);
153+
this.Ax = source["Ax"];
154+
this.Ay = source["Ay"];
155+
this.Bx = source["Bx"];
156+
this.By = source["By"];
157+
this.Cx = source["Cx"];
158+
this.Cy = source["Cy"];
159+
}
160+
}
139161

140162
}
141163

0 commit comments

Comments
 (0)