csg 0.0.2 → 0.0.3

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.
Files changed (9) hide show
  1. checksums.yaml +7 -0
  2. data/Makefile +7 -1
  3. data/src/bsp.c +78 -15
  4. data/src/bsp.h +4 -2
  5. data/src/commands.c +105 -0
  6. data/src/commands.h +17 -0
  7. data/src/poly.c +61 -3
  8. data/src/poly.h +10 -1
  9. metadata +11 -13
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0156d8c17eb3aa465dccdec30ce073b111c15f31
4
+ data.tar.gz: ffc2a35116bdd1cdd181943ae3e40ef51fcf5e88
5
+ SHA512:
6
+ metadata.gz: 9dce1d39a95353b489193bcfa6427127e87b99e2de342e0d571e65678a6c0785dc9b86a53b0f4a5f4e8058a3c8d0050979e7b54002c04275d051cd845073dfe2
7
+ data.tar.gz: c4f6ec8bf5905402348f7daec9d3db3994aeb237bf9eb49d5057eaa5bd7ab7ce7c9ecda037c5e2274e6aa448c9d0a9fd9877822fafc2daee535543e8cd2667ff
data/Makefile CHANGED
@@ -26,7 +26,7 @@ clean:
26
26
  test:
27
27
  @make -C tests clean test
28
28
 
29
- .PHONY: all clean test libcsg
29
+ .PHONY: all clean test libcsg loc
30
30
 
31
31
  $(TARGET): $(TARGET).o $(OBJS)
32
32
  $(CC) $(CFLAGS) $^ $(LIBS) -o $@.new
@@ -39,3 +39,9 @@ libcsg: $(LIB_TARGET)
39
39
 
40
40
  %.o: %.c
41
41
  $(CC) -fPIC $(CFLAGS) -o $@ -c $^
42
+
43
+ loc:
44
+ @echo "=> Source:"
45
+ find src/ -name '*.[ch]' -not -name 'dbg.*' | xargs wc -l csgtool.c
46
+ @echo "=> Tests:"
47
+ find tests/ -name '*.[ch]' -not -path '*clar*' | xargs wc -l
data/src/bsp.c CHANGED
@@ -69,7 +69,9 @@ int bsp_subdivide(poly_t *divider, poly_t *poly,
69
69
  poly_t **coplanar_front, int *n_cp_front,
70
70
  poly_t **coplanar_back, int *n_cp_back,
71
71
  poly_t **front, int *n_front,
72
- poly_t **back, int *n_back) {
72
+ poly_t **back, int *n_back,
73
+ poly_t **unused, int *n_unused,
74
+ poly_t **created, int *n_created) {
73
75
  switch(poly_classify_poly(divider, poly)) {
74
76
  case FRONT:
75
77
  front[*n_front] = poly;
@@ -99,6 +101,21 @@ int bsp_subdivide(poly_t *divider, poly_t *poly,
99
101
 
100
102
  back[*n_back] = b;
101
103
  *n_back += 1;
104
+
105
+ // Do we care about telling the caller about polygons
106
+ // who's pointers are not in any of the "real" lists?
107
+ if(unused != NULL) {
108
+ unused[*n_unused] = poly;
109
+ *n_unused += 1;
110
+ }
111
+
112
+ // How about polygons that we just made?
113
+ if(created != NULL) {
114
+ created[*n_created] = f;
115
+ *n_created += 1;
116
+ created[*n_created] = b;
117
+ *n_created += 1;
118
+ }
102
119
  break;
103
120
  }
104
121
  }
@@ -122,7 +139,7 @@ bsp_node_t *bsp_build(bsp_node_t *node, klist_t(poly) *polygons, int copy) {
122
139
  polys[i] = poly;
123
140
  }
124
141
 
125
- check((node = bsp_build_array(node, polys, polygons->size)),
142
+ check((node = bsp_build_array(node, polys, polygons->size, copy)),
126
143
  "Failed to build node from list(%p) of %zd polys", polygons, polygons->size);
127
144
  free(polys);
128
145
 
@@ -131,7 +148,8 @@ error:
131
148
  if(polys) free(polys);
132
149
  return NULL;
133
150
  }
134
- bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys) {
151
+
152
+ bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys, int free_unused) {
135
153
  int rc = 0;
136
154
 
137
155
  // Polygon lists and counters
@@ -142,6 +160,14 @@ bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys)
142
160
  poly_t **front_p = NULL;
143
161
  poly_t **back_p = NULL;
144
162
 
163
+ // List and counter of unused polygons
164
+ // These will get freed after the build
165
+ // because they will not appear with identity
166
+ // in coplanar, front_p, or back_p if free_unused
167
+ // is true
168
+ int n_unused = 0;
169
+ poly_t **unused = NULL;
170
+
145
171
  // Iterators
146
172
  poly_t *poly = NULL;
147
173
  size_t poly_i = 0;
@@ -172,20 +198,34 @@ bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys)
172
198
  check_mem(coplanar = malloc(sizeof(poly_t*) * n_polys));
173
199
  check_mem(front_p = malloc(sizeof(poly_t*) * n_polys));
174
200
  check_mem(back_p = malloc(sizeof(poly_t*) * n_polys));
201
+ check_mem(unused = malloc(sizeof(poly_t*) * n_polys));
175
202
  for(; poly_i < n_polys; poly_i++) {
176
203
  poly = polygons[poly_i];
177
204
  rc = bsp_subdivide(node->divider, poly,
178
205
  coplanar, &n_coplanar,
179
206
  coplanar, &n_coplanar,
180
207
  front_p, &n_front,
181
- back_p, &n_back);
208
+ back_p, &n_back,
209
+ unused, &n_unused,
210
+ NULL, NULL);
182
211
  check(rc == 0, "Failed to subdivide: %p => %p", node->divider, poly);
183
212
  }
184
213
 
214
+ // Destroy the unused polygons now, if we're asked,
215
+ // otherwise we'll lose the references
216
+ int i = 0;
217
+ if(free_unused != 0) {
218
+ for(i = 0; i < n_unused; i++) {
219
+ free_poly(unused[i], 1);
220
+ }
221
+ }
222
+ // Free now and mark NULL to make sure it's not double free'd on `error:`
223
+ free(unused);
224
+ unused = NULL;
225
+
185
226
  // Store the coplanar nodes in this node's polygon list
186
227
  // and free the container, letting the list destructor
187
228
  // clean up
188
- int i = 0;
189
229
  for(i = 0; i < n_coplanar; i++) {
190
230
  *kl_pushp(poly, node->polygons) = coplanar[i];
191
231
  }
@@ -195,13 +235,13 @@ bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys)
195
235
  if((n_front > 0)) {
196
236
  if(node->front == NULL) node->front = alloc_bsp_node();
197
237
  check_mem(node->front);
198
- check(bsp_build_array(node->front, front_p, n_front) != NULL,
238
+ check(bsp_build_array(node->front, front_p, n_front, free_unused) != NULL,
199
239
  "Failed to build front tree of bsp_node_array(%p)", node);
200
240
  }
201
241
  if((n_back > 0)) {
202
242
  if(node->back == NULL) node->back = alloc_bsp_node();
203
243
  check_mem(node->back);
204
- check(bsp_build_array(node->back, back_p, n_back) != NULL,
244
+ check(bsp_build_array(node->back, back_p, n_back, free_unused) != NULL,
205
245
  "Failed to build back tree of bsp_node(%p)", node);
206
246
  }
207
247
  free(front_p);
@@ -213,6 +253,7 @@ error:
213
253
  if(coplanar) free(coplanar);
214
254
  if(back_p) free(back_p);
215
255
  if(front_p) free(front_p);
256
+ if(unused) free(unused);
216
257
  return NULL;
217
258
  }
218
259
 
@@ -316,24 +357,28 @@ klist_t(poly) *bsp_clip_polygon_array(bsp_node_t *node, poly_t **polygons, size_
316
357
  poly_t **poly_buffer = static_poly_buffer;
317
358
  poly_t **front_array = NULL;
318
359
  poly_t **back_array = NULL;
360
+ poly_t **created_array = NULL;
319
361
  int n_front = 0;
320
362
  int n_back = 0;
363
+ int n_created = 0;
321
364
 
322
365
  // Let's end this quick if there's nothing to do.
323
366
  if(n_polys == 0) return result;
324
367
 
325
368
  if(node->divider != NULL) {
326
- if((n_polys * 2) > STATIC_POLY_BUFFER_SIZE) {
327
- check_mem(poly_buffer = malloc((sizeof(poly_t*) * n_polys) * 2));
369
+ if((n_polys * 3) > STATIC_POLY_BUFFER_SIZE) {
370
+ check_mem(poly_buffer = malloc((sizeof(poly_t*) * n_polys) * 3));
328
371
  }
329
372
  front_array = poly_buffer;
330
373
  back_array = poly_buffer + n_polys;
374
+ created_array = poly_buffer + (n_polys * 2);
331
375
  // Sort this node's polygons into the front or back
332
376
  for(i = 0; i < n_polys; i++) {
333
377
  p = polygons[i];
334
378
  rc = bsp_subdivide(node->divider, p,
335
379
  front_array, &n_front, back_array, &n_back,
336
- front_array, &n_front, back_array, &n_back);
380
+ front_array, &n_front, back_array, &n_back,
381
+ NULL, NULL, created_array, &n_created);
337
382
  check(rc != -1, "Failed to subdivide poly %p", p);
338
383
  }
339
384
 
@@ -358,8 +403,15 @@ klist_t(poly) *bsp_clip_polygon_array(bsp_node_t *node, poly_t **polygons, size_
358
403
  check(result != NULL, "Failed to clip back tree");
359
404
  }
360
405
 
361
- if(poly_buffer != static_poly_buffer) free(poly_buffer);
406
+ // Free all the polygons in 'created_array` since they would have
407
+ // been cloned if they were important, and the input set is not our
408
+ // responsibility
409
+ for(int j = 0; j < n_created; j++) {
410
+ free_poly(created_array[j], 1);
411
+ }
412
+
362
413
  // Clean up the result halves, now that they're copied into `result`
414
+ if(poly_buffer != static_poly_buffer) free(poly_buffer);
363
415
  }
364
416
  else {
365
417
  // If we don't have a divider we just copy out the polygons
@@ -386,23 +438,27 @@ klist_t(poly) *bsp_clip_polygons(bsp_node_t *node, klist_t(poly) *polygons, klis
386
438
  poly_t **poly_buffer = static_poly_buffer;
387
439
  poly_t **front_array = NULL;
388
440
  poly_t **back_array = NULL;
441
+ poly_t **created_array = NULL;
389
442
  int n_front = 0;
390
443
  int n_back = 0;
444
+ int n_created = 0;
391
445
 
392
446
  // Let's end this quick if there's nothing to do.
393
447
  if(polygons->size == 0) return result;
394
448
 
395
449
  if(node->divider != NULL) {
396
- if((polygons->size * 2) > STATIC_POLY_BUFFER_SIZE) {
397
- check_mem(poly_buffer = malloc(sizeof(poly_t*) * polygons->size * 2));
450
+ if((polygons->size * 3) > STATIC_POLY_BUFFER_SIZE) {
451
+ check_mem(poly_buffer = malloc(sizeof(poly_t*) * polygons->size * 3));
398
452
  }
399
453
  front_array = poly_buffer;
400
454
  back_array = poly_buffer + polygons->size;
455
+ created_array = poly_buffer + (polygons->size * 2);
401
456
  // Sort this node's polygons into the front or back
402
457
  for(iter = kl_begin(polygons); iter != kl_end(polygons); iter = kl_next(iter)) {
403
458
  rc = bsp_subdivide(node->divider, kl_val(iter),
404
459
  front_array, &n_front, back_array, &n_back,
405
- front_array, &n_front, back_array, &n_back);
460
+ front_array, &n_front, back_array, &n_back,
461
+ NULL, NULL, created_array, &n_created);
406
462
  check(rc != -1, "Failed to subdivide poly %p", kl_val(iter));
407
463
  }
408
464
 
@@ -427,8 +483,15 @@ klist_t(poly) *bsp_clip_polygons(bsp_node_t *node, klist_t(poly) *polygons, klis
427
483
  check(result != NULL, "Failed to clip back tree");
428
484
  }
429
485
 
486
+ // Free all the polygons in 'created_array` since they would have
487
+ // been cloned if they were important, and the input set is not our
488
+ // responsibility
489
+ for(int j = 0; j < n_created; j++) {
490
+ free_poly(created_array[j], 1);
491
+ }
492
+
493
+
430
494
  if(poly_buffer != static_poly_buffer) free(poly_buffer);
431
- // Clean up the result halves, now that they're copied into `result`
432
495
  }
433
496
  else {
434
497
  // If we don't have a divider we just copy out the polygons
data/src/bsp.h CHANGED
@@ -33,10 +33,12 @@ int bsp_subdivide(poly_t *divider, poly_t *poly,
33
33
  poly_t **coplanar_front, int *n_cp_front,
34
34
  poly_t **coplanar_back, int *n_cp_back,
35
35
  poly_t **front, int *n_front,
36
- poly_t **back, int *n_back);
36
+ poly_t **back, int *n_back,
37
+ poly_t **unused, int *n_unused,
38
+ poly_t **created, int *n_created);
37
39
 
38
40
  bsp_node_t *bsp_build(bsp_node_t *node, klist_t(poly) *polygons, int copy);
39
- bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys);
41
+ bsp_node_t *bsp_build_array(bsp_node_t *node, poly_t **polygons, size_t n_polys, int free_unused);
40
42
  klist_t(poly) *bsp_to_polygons(bsp_node_t *tree, int make_triangles, klist_t(poly) *dst);
41
43
 
42
44
  bsp_node_t *bsp_invert(bsp_node_t *tree);
data/src/commands.c ADDED
@@ -0,0 +1,105 @@
1
+ #include <string.h>
2
+ #include "dbg.h"
3
+
4
+ #include "commands.h"
5
+ #include "stl.h"
6
+ #include "bsp.h"
7
+ #include "export.h"
8
+
9
+ typedef bsp_node_t* (*bsp_binary_op)(bsp_node_t *, bsp_node_t *);
10
+
11
+ // A generalization of a binary CSG operation being performed on an STL
12
+ // in `path1` and `path1` defined by an operation `op` from` bsp.h
13
+ // Result is freshly allocated, and needs to be freed with `free_bsp_tree()`
14
+ bsp_node_t* bsp_binary_operation(char *path1, char *path2, bsp_binary_op op) {
15
+ stl_object *file1 = NULL;
16
+ bsp_node_t *bsp1 = NULL;
17
+
18
+ stl_object *file2 = NULL;
19
+ bsp_node_t *bsp2 = NULL;
20
+
21
+ bsp_node_t *result = NULL;
22
+
23
+ // Read 1
24
+ file1 = stl_read_file(path1, 1);
25
+ check(file1 != NULL, "Failed to read .stl from '%s'", path1);
26
+ log_info("Loaded file: %s %d facets", path1, file1->facet_count);
27
+ bsp1 = stl_to_bsp(file1);
28
+ check_mem(bsp1);
29
+
30
+ // Read 2
31
+ file2 = stl_read_file(path2, 1);
32
+ check(file2 != NULL, "Failed to read .stl from '%s'", path2);
33
+ log_info("Loaded file: %s %d facets", path2, file2->facet_count);
34
+ bsp2 = stl_to_bsp(file2);
35
+ check_mem(bsp2);
36
+
37
+ // Operate
38
+ result = op(bsp1, bsp2);
39
+
40
+ if(file1 != NULL) stl_free(file1);
41
+ if(file2 != NULL) stl_free(file2);
42
+ if(bsp1 != NULL) free_bsp_tree(bsp1);
43
+ if(bsp2 != NULL) free_bsp_tree(bsp2);
44
+ return result;
45
+ error:
46
+ if(file1 != NULL) stl_free(file1);
47
+ if(file2 != NULL) stl_free(file2);
48
+ if(bsp1 != NULL) free_bsp_tree(bsp1);
49
+ if(bsp2 != NULL) free_bsp_tree(bsp2);
50
+ if(result != NULL) free_bsp_tree(result);
51
+ return NULL;
52
+ }
53
+
54
+ // Constructor for commands named after the CSG functions they perform.
55
+ // Produces a function named `cmd_<name>(int argc, char **argv) that reads
56
+ // two files and an optional output path and calls a matching function
57
+ // bsp_<name>(bsp_node_t*,bsp_node_t*) and writes the resulting mesh
58
+ // to disk as either `./out.stl` or the value of argv[2]
59
+ // Uses the above `bsp_binary_operation(..)` wrapper to do most of the
60
+ // heavy lifting.
61
+ #define MAKE_CSG_COMMAND(name) \
62
+ int cmd_##name(int argc, char **argv) { \
63
+ bsp_node_t *result = NULL; \
64
+ stl_object *out = NULL; \
65
+ char *out_path = "./out.stl"; \
66
+ \
67
+ check(argc >= 2, "At least two input files required."); \
68
+ if(argc > 2) out_path = argv[2]; \
69
+ \
70
+ result = bsp_binary_operation(argv[0], argv[1], bsp_##name); \
71
+ out = bsp_to_stl(result); \
72
+ log_info("Writing output to %s", out_path); \
73
+ check(stl_write_file(out, out_path) == 0, "Failed to write STL to %s", out_path); \
74
+ \
75
+ if(result != NULL) free_bsp_tree(result); \
76
+ if(out != NULL) stl_free(out); \
77
+ return 0; \
78
+ error: \
79
+ if(result != NULL) free_bsp_tree(result); \
80
+ if(out != NULL) stl_free(out); \
81
+ return -1; \
82
+ }
83
+
84
+ // Each MAKE_BSP_COMMAND(name) results in a function named
85
+ // cmd_<name>(int argc, argv) which calls bsp_<name>() with
86
+ // two trees built from files in argv[0] and argv[1]
87
+ MAKE_CSG_COMMAND(intersect);
88
+ MAKE_CSG_COMMAND(union);
89
+ MAKE_CSG_COMMAND(subtract);
90
+
91
+ // Available commands
92
+ const cmd_t commands[] = {
93
+ {"intersect", "Intersect two geometries", cmd_intersect},
94
+ {"subtract", "Subtract two geometries", cmd_subtract},
95
+ {"union", "Union two geometries", cmd_union},
96
+ {NULL, NULL, NULL}
97
+ };
98
+
99
+ // Search for a command by name.
100
+ cmd_fun_t cmd_find(const char *name) {
101
+ for(cmd_t *c = (cmd_t*)commands; c->name != NULL; c++) {
102
+ if(0 == strcmp(c->name, name)) return c->fun;
103
+ }
104
+ return NULL;
105
+ }
data/src/commands.h ADDED
@@ -0,0 +1,17 @@
1
+ #include <stdio.h>
2
+
3
+ #ifndef __COMMANDS_H
4
+ #define __COMMANDS_H
5
+
6
+ typedef int (*cmd_fun_t)(int argc, char **argv);
7
+
8
+ typedef struct s_cmd_t {
9
+ char *name;
10
+ char *description;
11
+ cmd_fun_t fun;
12
+ } cmd_t;
13
+
14
+ extern const cmd_t commands[];
15
+ cmd_fun_t cmd_find(const char *name);
16
+
17
+ #endif
data/src/poly.c CHANGED
@@ -13,11 +13,17 @@ error:
13
13
 
14
14
  void free_poly(poly_t *p, int free_self) {
15
15
  if(p == NULL) return;
16
+ if(poly_vertex_dynamic_p(p) == 1) {
17
+ if(p->vertices != NULL) free(p->vertices);
18
+ p->vertices = NULL;
19
+ }
16
20
  if(free_self) free(p);
17
21
  }
18
22
 
19
23
  poly_t *poly_init(poly_t *poly) {
20
24
  poly->vertex_count = 0;
25
+ poly->vertex_max = POLY_MAX_VERTS;
26
+ poly->vertices = poly->_vbuffer;
21
27
  return poly;
22
28
  }
23
29
 
@@ -25,8 +31,23 @@ poly_t *clone_poly(poly_t *poly) {
25
31
  poly_t *copy = NULL;
26
32
  check_mem(copy = alloc_poly());
27
33
  memcpy(copy, poly, sizeof(poly_t));
34
+
35
+ // Either point the clone at its own copied
36
+ // buffer, or copy over the dynamic vertex buffer
37
+ if(poly_vertex_dynamic_p(poly) == 0) {
38
+ copy->vertices = copy->_vbuffer;
39
+ }
40
+ else {
41
+ // We can lean on the `copy->*` memebers
42
+ // since they would have been memcpy'd over
43
+ copy->vertices = malloc(poly_vertex_max(copy) * sizeof(float3));
44
+ check_mem(copy->vertices);
45
+ memcpy(copy->vertices, poly->vertices, poly_vertex_max(copy) * sizeof(float3));
46
+ }
47
+
28
48
  return copy;
29
49
  error:
50
+ if(copy != NULL) free_poly(copy, 1);
30
51
  return NULL;
31
52
  }
32
53
 
@@ -53,10 +74,47 @@ int poly_vertex_count(poly_t *poly) {
53
74
  return poly->vertex_count;
54
75
  }
55
76
 
56
- // Add a vertex to the end of the polygon vertex list
77
+ int poly_vertex_max(poly_t *poly) {
78
+ return poly->vertex_max;
79
+ }
80
+
81
+ int poly_vertex_available(poly_t *poly) {
82
+ return poly->vertex_max - poly->vertex_count;
83
+ }
84
+
85
+ // Has the vertex buffer been dynamically allocated?
86
+ int poly_vertex_dynamic_p(poly_t *poly) {
87
+ return (poly->vertices != poly->_vbuffer) ? 1 : 0;
88
+ }
89
+
90
+ int poly_vertex_expand(poly_t *poly) {
91
+ // Not using realloc because the original buffer may be struct-owned
92
+ int new_size = poly->vertex_max * 2;
93
+ float3 *new_verts = malloc(new_size * sizeof(float3));
94
+ check_mem(new_verts);
95
+
96
+ memcpy(new_verts, poly->vertices, poly->vertex_max * sizeof(float3));
97
+ poly->vertex_max = new_size;
98
+
99
+ // Free the existing buffer if it's not part of the struct's space
100
+ if(poly_vertex_dynamic_p(poly) == 1) {
101
+ free(poly->vertices);
102
+ }
103
+
104
+ // Install the new vertex buffer
105
+ poly->vertices = new_verts;
106
+
107
+ return 0;
108
+ error:
109
+ if(new_verts != NULL) free(new_verts);
110
+ return -1;
111
+ }
112
+
113
+ // add a vertex to the end of the polygon vertex list
57
114
  int poly_push_vertex(poly_t *poly, float3 v) {
58
- // TODO: Don't assert, grow
59
- assert(poly->vertex_count < POLY_MAX_VERTS);
115
+ if(poly_vertex_available(poly) == 0) {
116
+ poly_vertex_expand(poly);
117
+ }
60
118
 
61
119
  // Dat assignment copy
62
120
  poly->vertices[poly->vertex_count][0] = v[0];
data/src/poly.h CHANGED
@@ -12,14 +12,19 @@
12
12
  #define BACK 2
13
13
  #define SPANNING 3
14
14
 
15
+ #ifndef POLY_MAX_VERTS
15
16
  #define POLY_MAX_VERTS 40
17
+ #endif
16
18
 
17
19
  typedef struct s_poly {
18
- float3 vertices[POLY_MAX_VERTS];
20
+ float3 *vertices;
19
21
  int vertex_count;
22
+ int vertex_max;
20
23
 
21
24
  float3 normal;
22
25
  float w;
26
+
27
+ float3 _vbuffer[POLY_MAX_VERTS];
23
28
  } poly_t;
24
29
 
25
30
  poly_t *alloc_poly(void);
@@ -32,6 +37,10 @@ int poly_update(poly_t *poly);
32
37
  poly_t *poly_invert(poly_t *poly);
33
38
 
34
39
  int poly_vertex_count(poly_t *poly);
40
+ int poly_vertex_max(poly_t *poly);
41
+ int poly_vertex_available(poly_t *poly);
42
+ int poly_vertex_dynamic_p(poly_t *poly);
43
+ int poly_vertex_expand(poly_t *poly);
35
44
  int poly_push_vertex(poly_t *poly, float3 v);
36
45
 
37
46
  int poly_classify_vertex(poly_t *poly, float3 v);
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
4
+ version: 0.0.3
6
5
  platform: ruby
7
6
  authors:
8
7
  - Yaroslav Shirokov
@@ -10,22 +9,20 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2013-07-11 00:00:00.000000000 Z
12
+ date: 2013-09-23 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: ffi
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
- - - ! '>='
18
+ - - '>='
21
19
  - !ruby/object:Gem::Version
22
20
  version: '0'
23
21
  type: :runtime
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
- - - ! '>='
25
+ - - '>='
29
26
  - !ruby/object:Gem::Version
30
27
  version: '0'
31
28
  description: A fast library for Constructive Solid Geometry
@@ -40,12 +37,14 @@ files:
40
37
  - Makefile
41
38
  - lib/csg.rb
42
39
  - src/bsp.c
40
+ - src/commands.c
43
41
  - src/dbg.c
44
42
  - src/export.c
45
43
  - src/poly.c
46
44
  - src/stl.c
47
45
  - src/vector.c
48
46
  - src/bsp.h
47
+ - src/commands.h
49
48
  - src/dbg.h
50
49
  - src/export.h
51
50
  - src/klist.h
@@ -55,26 +54,25 @@ files:
55
54
  - ext/Rakefile
56
55
  homepage: https://github.com/sshirokov/csgtool/
57
56
  licenses: []
57
+ metadata: {}
58
58
  post_install_message:
59
59
  rdoc_options: []
60
60
  require_paths:
61
61
  - lib
62
62
  required_ruby_version: !ruby/object:Gem::Requirement
63
- none: false
64
63
  requirements:
65
- - - ! '>='
64
+ - - '>='
66
65
  - !ruby/object:Gem::Version
67
66
  version: '0'
68
67
  required_rubygems_version: !ruby/object:Gem::Requirement
69
- none: false
70
68
  requirements:
71
- - - ! '>='
69
+ - - '>='
72
70
  - !ruby/object:Gem::Version
73
71
  version: '0'
74
72
  requirements: []
75
73
  rubyforge_project:
76
- rubygems_version: 1.8.23
74
+ rubygems_version: 2.0.3
77
75
  signing_key:
78
- specification_version: 3
76
+ specification_version: 4
79
77
  summary: A fast library for Constructive Solid Geometry
80
78
  test_files: []