-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlines_functions.h
488 lines (382 loc) · 14 KB
/
lines_functions.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
// functions for working with lines (open polys)
//////////////////////////////////////////////////
// findprims() - Returns the primitive lines that connect two points.
// findprim() - Returns a single primitive line that connects two points.
function int[] findprims(int geo; string primgrp; int pt01; int pt02){
int prims[];
int hedge = pointhedge(geo, pt01, pt02); //pts[0];
if (hedge == -1)
hedge = pointhedge(geo, pt02, pt01);
if (hedge == -1) return prims;
int prim = hedge_prim(geo, hedge);
if (prim >= 0) append(prims, prim);
for (int nh = hedge_nextequiv(geo, hedge); nh != hedge; nh = hedge_nextequiv(geo, nh)){
prim = hedge_prim(geo, nh);
if (prim >= 0)
append(prims, prim);
}
return prims;
}
// getting prims without primgroup
function int[] findprims(int geo; int pt01; int pt02){
string primgrp = '';
int prims[] = findprims(geo, primgrp, pt01, pt02);
return prims;
}
// finding one prim with primgroup
function int findprim(int geo; string primgrp; int pt01; int pt02){
int prims[] = findprims(geo, primgrp, pt01, pt02);
if (len(prims) == 0)
return -1;
else
return prims[0];
}
// finding one prim without primgroup
function int findprim(int geo; int pt01; int pt02){
string primgrp = '';
int prims[] = findprims(geo, primgrp, pt01, pt02);
if (len(prims) == 0)
return -1;
else
return prims[0];
}
/////////////////////////////////////////
// Removing Duplicated Lines (Lines that connect the same two points).
// This is done by iterating over primitives and using findprims().
function void removeduplines(int geo; int primnum){
int pts[] = primpoints(geo, primnum);
int prims[] = findprims(geo, pts[0], pts[1]);
prims = sort(prims);
if (primnum != prims[0]) return;
foreach(int prim; prims){
if (prim == primnum) continue;
removeprim(geo, prim, 0);
}
}
// Get neighboring primitives for a polyline (a line with two points).
function int[] polyline_neighbours(int geo; int primnum){
int pts[] = primpoints(geo, primnum);
int neis0[] = neighbours(geo, pts[0]);
int neis1[] = neighbours(geo, pts[1]);
removevalue(neis0, pts[1]);
removevalue(neis1, pts[0]);
int neiprims[];
foreach(int nei; neis0){
int edge = pointedge(geo, pts[0], nei);
if (edge == -1) continue;
int prim = hedge_prim(geo, edge);
if (find(neiprims, prim) < 0){
append(neiprims, prim);
}
}
foreach(int nei; neis1){
int edge = pointedge(geo, pts[1], nei);
if (edge == -1) continue;
int prim = hedge_prim(geo, edge);
if (find(neiprims, prim) < 0){
append(neiprims, prim);
}
}
removevalue(neiprims, primnum);
return neiprims;
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// Simple connectivity check for polylines with a constraint point group.
// Finds connected polylines "split" at constraint points.
// Works at the Detail level.
// Constraint points break the original line into segments.
// Uses polyline_neighbours() to find connected lines,
// ignoring lines where in between is constraint points.
// Can be faster by using the Connectivity node to create initial classes,
// then iterating over the pieces instead of all geometry at the Detail level.
function int[] polyline_neighbours(int geo; int primnum; string constrgrp){
int pts[] = primpoints(geo, primnum);
int neis0[] = neighbours(geo, pts[0]);
int neis1[] = neighbours(geo, pts[1]);
removevalue(neis0, pts[1]);
removevalue(neis1, pts[0]);
if (inpointgroup(0, constrgrp, pts[0]))
neis0 = array();
if (inpointgroup(0, constrgrp, pts[1]))
neis1 = array();
int neiprims[];
foreach(int nei; neis0){
int edge = pointedge(geo, pts[0], nei);
if (edge == -1) continue;
int prim = hedge_prim(geo, edge);
if (find(neiprims, prim) < 0){
append(neiprims, prim);
}
}
foreach(int nei; neis1){
int edge = pointedge(geo, pts[1], nei);
if (edge == -1) continue;
int prim = hedge_prim(geo, edge);
if (find(neiprims, prim) < 0){
append(neiprims, prim);
}
}
removevalue(neiprims, primnum);
return neiprims;
}
int primCount = nprimitives(0);
int componentID = 0; // Unique ID for each connected component
// Create an array to store component assignments for points
int ids[] = array();
resize(ids, primCount, -1);
// storing constraint group
string constrgroup = chs('constrgroup');
// Flood fill function to assign component ID
function void floodFill(int startPrim, compID; int ids[]; string constrptgroup) {
int stack[] = array(startPrim); // Stack to keep track of points to visit
while(len(stack) > 0) {
int curr = pop(stack); // Get the last point from the stack
if (ids[curr] != -1) continue; // Skip if already visited
ids[curr] = compID; // Assign component ID to current point
// Find neighboring points connected by edges
int neighbors[] = polyline_neighbours(0, curr, constrptgroup);
foreach(int nb; neighbors) {
if (ids[nb] == -1) { // Only visit unvisited neighbors
append(stack, nb); // Add neighbor to stack for future visits
}
}
}
}
// Iterate over all points and apply flood fill where necessary
for (int prim = 0; prim < primCount; prim++) {
if (ids[prim] == -1) {
floodFill(prim, componentID, ids, constrgroup); // Pass ids as an argument
componentID++; // Increment component ID for the next connected piece
}
}
// Finally, assign the IDs back to points
i[]@ids = ids;
////////////////////////////////////////////
// After the Detail Wrangle, use a Primitive Wrangle to assign the class attribute
int ids[] = detail(0, "ids");
i@class = ids[@primnum];
//////////////////////////////////////////////
//////////////////////////////////////////////
// ### Near Line Primitives to Primitive - nearprims()
// Finds the nearest line primitives to a given primitive.
// This should be updated to utilize the pcsegment() function.
function int[] nearprims(int geo; int prim; float rad){
int nearprims[] = array();
int pts[] = primpoints(geo, prim);
vector pos01 = point(geo, "P", pts[0]);
vector pos02 = point(geo, "P", pts[1]);
int num = 1e15;
int pts01[] = pcfind(geo, "P", pos01, rad, num);
int pts02[] = pcfind(geo, "P", pos02, rad, num);
foreach(int pt01; pts01){
// if (pt01 == pts[0]) continue;
foreach(int pt02; pts02){
// if (pt02 == pts[1]) continue;
int nprims[] = findprims(geo, pt01, pt02);
foreach(int nprim; nprims){
if (nprim >= 0 && prim != nprim){
append(nearprims, nprim);
}
}
}
}
return nearprims;
}
// VERTICES
////////////////////////////////////////
// Vertex by Point and Prm - pointprimvertex()
function int pointprimvertex(int geo; int ptnum; int primnum){
int vtxs01[] = pointvertices(geo, ptnum);
int vtxs02[] = primvertices(geo, primnum);
foreach(int vtx; vtxs01){
if (find(vtxs02, vtx) >= 0){
return vtx;
}
}
return -1;
}
///////////////////////////////////////////////
// Near Vertices by UV - nearverticesbyuv()
function int[] nearverticesbyuv(int geo; float targetuv; int primnum; float maxuvdist){
int vtxs[] = primvertices(geo, primnum);
int linearvtxs[] = array();
float dists[] = array();
foreach(int vtx; vtxs){
int linearvtx = primvertex(geo, primnum, vtx);
float uv = vertexcurveparam(geo, linearvtx);
float dist = abs(targetuv - uv);
if (dist <= maxuvdist){
append(linearvtxs, linearvtx);
append(dists, dist);
}
}
int idxs[] = argsort(dists);
return reorder(linearvtxs, idxs);
}
function int nearvertexbyuv(int geo; float targetuv; int primnum; float maxuvdist){
int vtxs[] = nearverticesbyuv(geo, targetuv, primnum, maxuvdist);
if (len(vtxs) > 0)
return vtxs[0];
else
return -1;
}
function int nearvertexbyuv(int geo; float targetuv; int primnum){
float maxuv = 2.0;
int vtx = nearvertexbyuv(geo, targetuv, primnum, maxuv);
return vtx;
}
///////////////////////////////////////////
// Points array from UV - pointsfromuv()
// GET ARRAY OF POINTS FROM U parametric values (START/END)
function void pointsfromuv(int geo; int primnum; vector2 uvw; int pts[]){
int vtxs[] = primvertices(geo, primnum);
float uvs[] = array(clamp(uvw[0], 0, 1), clamp(uvw[1], 0, 1));
uvs = sort(uvs);
foreach(int vtx; vtxs){
float uv = vertexcurveparam(geo, vtx);
int pt = vertexpoint(geo, vtx);
if (uv >= uvs[0] && uv <= uvs[1] && find(pts, pt) < 0){
append(pts, pt);
}
}
}
// SEPARATE UVW (TWO FLOATS)
function void pointsfromuv(int geo; int primnum; float start; float end; int pts[]){
vector2 uv = set(start, end);
pointsfromuv(geo, primnum, uv, pts);
}
// RETURN ARRAY OF POINTS
function int[] pointsfromuv(int geo; int primnum; vector2 uvw){
int pts[];
pointsfromuv(geo, primnum, uvw, pts);
return pts;
}
function int[] pointsfromuv(int geo; int primnum; float start; float end){
int pts[];
vector2 uvw = set(start, end);
pointsfromuv(geo, primnum, uvw, pts);
return pts;
}
///////////////////////////////////
// ### UV From Points - uvfrompoint()
// Get curve uv by primitive and point
function float uvfrompoint(int geo; int ptnum; int primnum){
int vtx = pointprimvertex(geo, ptnum, primnum);
return vertexcurveparam(geo, vtx);
}
////////////////////////////////////
// ### UVs From Points - uvsfrompoints()
// Returns an array of all uv ranges that lie between the points
function void uvsfrompoints_all(int geo; int pts[]; int primnum; vector2 uvranges[]; string ptgrps[]){
int allpts[] = primpoints(geo, primnum);
if (allpts[-1] == allpts[0]) // remove duplicated index from end
removeindex(allpts, -1);
float uvstart = 2.0;
float uvend = -1.0;
string ptgrp = '';
foreach(int idx; int pt; allpts){
float uv = uvfrompoint(geo, pt, primnum);
if (find(pts, pt) >= 0){
if (uvstart > uv || uvend < uv){
ptgrp += itoa(pt) + ',';
if (uvstart > uv) uvstart = uv;
if (uvend < uv) uvend = uv;
}
}else{
if (uvstart != 2.0 && uvend != -1.0){
append(uvranges, set(uvstart, uvend));
if (ptgrp[-1] == ',')
ptgrp = ptgrp[:-1];
append(ptgrps, ptgrp);
}
uvstart = 2.0;
uvend = -1.0;
ptgrp = '';
}
}
if (uvstart != 2.0 && uvend != -1.0)
append(uvranges, set(uvstart, uvend));
}
// RETURN ONE OR TWO UV RANGE FROM POINTS ARRAY
// return corner uvs. Will make two uvs, if it hits the edge (uvend = 1.0)
function void uvsfrompoints_main(int geo; int pts[]; int primnum; vector2 uvranges[]; string ptgrps[]){
int allpts[] = primpoints(geo, primnum);
if (allpts[-1] == allpts[0]) // remove duplicated index from end
removeindex(allpts, -1);
float uvstart = 2.0;
float uvend = -1.0;
string ptgrp = '';
foreach(int idx; int pt; allpts){
float uv = uvfrompoint(geo, pt, primnum);
if (find(pts, pt) >= 0){
if (uvstart > uv || uvend < uv){
ptgrp += itoa(pt) + ',';
if (uvstart > uv) uvstart = uv;
if (uvend < uv) uvend = uv;
}
}
if (uvend == 1.0){
append(uvranges, set(uvstart, uvend));
if (ptgrp[-1] == ',')
ptgrp = ptgrp[:-1];
append(ptgrps, ptgrp);
uvstart = 2.0;
uvend = -1.0;
ptgrp = '';
}
}
if (uvstart != 2.0 && uvend != -1.0)
append(uvranges, set(uvstart, uvend));
}
// NO MODE
function void uvsfrompoints(int geo; int pts[]; int primnum; vector2 uvranges[]; string ptgrps[]){
uvsfrompoints_main(geo, pts, primnum, uvranges, ptgrps);
}
// WITH MODE
function void uvsfrompoints(int geo; int pts[]; int primnum; vector2 uvranges[]; string ptgrps[]; string mode){
if (mode == 'all')
uvsfrompoints_all(geo, pts, primnum, uvranges, ptgrps);
else
uvsfrompoints_main(geo, pts, primnum, uvranges, ptgrps);
}
////// RETURN UVRANGES[]
function vector2[] uvsfrompoints(int geo; int pts[]; int primnum; string ptgrps[]; string mode){
vector2 uvranges[];
if (mode == 'all')
uvsfrompoints_all(geo, pts, primnum, uvranges, ptgrps);
else
uvsfrompoints_main(geo, pts, primnum, uvranges, ptgrps);
return uvranges;
}
// NO MODE
function vector2[] uvsfrompoints(int geo; int pts[]; int primnum; string ptgrps[]){
vector2 uvranges[];
string mode = 'main';
if (mode == 'all')
uvsfrompoints_all(geo, pts, primnum, uvranges, ptgrps);
else
uvsfrompoints_main(geo, pts, primnum, uvranges, ptgrps);
return uvranges;
}
/////// RETURN UVRANGES[] WITHOUT PTGRPS[]
function vector2[] uvsfrompoints(int geo; int pts[]; int primnum; string mode){
vector2 uvranges[];
string ptgrps[];
if (mode == 'all')
uvsfrompoints_all(geo, pts, primnum, uvranges, ptgrps);
else
uvsfrompoints_main(geo, pts, primnum, uvranges, ptgrps);
return uvranges;
}
// NO MODE
function vector2[] uvsfrompoints(int geo; int pts[]; int primnum){
vector2 uvranges[];
string ptgrps[];
string mode = 'main';
if (mode == 'all')
uvsfrompoints_all(geo, pts, primnum, uvranges, ptgrps);
else
uvsfrompoints_main(geo, pts, primnum, uvranges, ptgrps);
return uvranges;
}