From 6373322b84ea151feba667c964e9e5fd6eac25fc Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 3 Jul 2013 11:38:01 +0200 Subject: New ReadFromPerl() method --- xs/src/TriangleMesh.cpp | 32 ++++++++++ xs/src/TriangleMesh.hpp | 1 + xs/src/admesh/stl.h | 10 +++- xs/src/admesh/stlinit.c | 155 ++++++++++++++++++++++++------------------------ xs/t/01_trianglemesh.t | 16 ++++- xs/xsp/TriangleMesh.xsp | 1 + 6 files changed, 137 insertions(+), 78 deletions(-) (limited to 'xs') diff --git a/xs/src/TriangleMesh.cpp b/xs/src/TriangleMesh.cpp index 7219f85fa..462a93347 100644 --- a/xs/src/TriangleMesh.cpp +++ b/xs/src/TriangleMesh.cpp @@ -10,6 +10,38 @@ TriangleMesh::ReadSTLFile(char* input_file) { stl_open(&stl, input_file); } +void TriangleMesh::ReadFromPerl(SV* vertices, SV* facets) +{ + stl_initialize(&stl); + stl.stats.type = inmemory; + + // count facets and allocate memory + AV* facets_av = (AV*)SvRV(facets); + stl.stats.number_of_facets = av_len(facets_av)+1; + stl.stats.original_num_facets = stl.stats.number_of_facets; + stl_allocate(&stl); + + // read geometry + AV* vertices_av = (AV*)SvRV(vertices); + for (unsigned int i = 0; i < stl.stats.number_of_facets; i++) { + AV* facet_av = (AV*)SvRV(*av_fetch(facets_av, i, 0)); + stl_facet facet; + facet.normal.x = NULL; + facet.normal.y = NULL; + facet.normal.z = NULL; + for (unsigned int v = 0; v <= 2; v++) { + AV* vertex_av = (AV*)SvRV(*av_fetch(vertices_av, SvIV(*av_fetch(facet_av, v, 0)), 0)); + facet.vertex[v].x = SvNV(*av_fetch(vertex_av, 0, 0)); + facet.vertex[v].y = SvNV(*av_fetch(vertex_av, 1, 0)); + facet.vertex[v].z = SvNV(*av_fetch(vertex_av, 2, 0)); + } + facet.extra[0] = NULL; + facet.extra[1] = NULL; + + stl.facet_start[i] = facet; + } +} + void TriangleMesh::Repair() { int i; diff --git a/xs/src/TriangleMesh.hpp b/xs/src/TriangleMesh.hpp index e8cb5d3b6..78e62cf9a 100644 --- a/xs/src/TriangleMesh.hpp +++ b/xs/src/TriangleMesh.hpp @@ -13,6 +13,7 @@ class TriangleMesh TriangleMesh(); ~TriangleMesh(); void ReadSTLFile(char* input_file); + void ReadFromPerl(SV* vertices, SV* facets); void Repair(); void WriteOBJFile(char* output_file); AV* ToPerl(); diff --git a/xs/src/admesh/stl.h b/xs/src/admesh/stl.h index 92f14000f..1cfe5f2bc 100644 --- a/xs/src/admesh/stl.h +++ b/xs/src/admesh/stl.h @@ -55,7 +55,7 @@ typedef struct }stl_facet; #define SIZEOF_STL_FACET 50 -typedef enum {binary, ascii} stl_type; +typedef enum {binary, ascii, inmemory} stl_type; typedef struct { @@ -172,3 +172,11 @@ extern void stl_calculate_normal(float normal[], stl_facet *facet); extern void stl_normalize_vector(float v[]); extern void stl_calculate_volume(stl_file *stl); +extern void stl_initialize(stl_file *stl); +static void stl_count_facets(stl_file *stl, char *file); +extern void stl_allocate(stl_file *stl); +static void stl_read(stl_file *stl, int first_facet, int first); +static void stl_facet_stats(stl_file *stl, stl_facet facet, int first); +static void stl_reallocate(stl_file *stl); +static int stl_get_little_int(FILE *fp); +static float stl_get_little_float(FILE *fp); diff --git a/xs/src/admesh/stlinit.c b/xs/src/admesh/stlinit.c index cd6a8e074..7d8b9e65a 100644 --- a/xs/src/admesh/stlinit.c +++ b/xs/src/admesh/stlinit.c @@ -31,17 +31,11 @@ #define SEEK_END 2 #endif -static void stl_initialize(stl_file *stl, char *file); -static void stl_allocate(stl_file *stl); -static void stl_read(stl_file *stl, int first_facet, int first); -static void stl_reallocate(stl_file *stl); -static int stl_get_little_int(FILE *fp); -static float stl_get_little_float(FILE *fp); - void stl_open(stl_file *stl, char *file) { - stl_initialize(stl, file); + stl_initialize(stl); + stl_count_facets(stl, file); stl_allocate(stl); stl_read(stl, 0, 1); fclose(stl->fp); @@ -75,17 +69,9 @@ stl_get_little_float(FILE *fp) } -static void -stl_initialize(stl_file *stl, char *file) +void +stl_initialize(stl_file *stl) { - long file_size; - int header_num_facets; - int num_facets; - int i, j; - unsigned char chtest[128]; - int num_lines = 1; - char *error_msg; - stl->stats.degenerate_facets = 0; stl->stats.edges_fixed = 0; stl->stats.facets_added = 0; @@ -101,8 +87,19 @@ stl_initialize(stl_file *stl, char *file) stl->facet_start = NULL; stl->v_indices = NULL; stl->v_shared = NULL; +} - +static void +stl_count_facets(stl_file *stl, char *file) +{ + long file_size; + int header_num_facets; + int num_facets; + int i, j; + unsigned char chtest[128]; + int num_lines = 1; + char *error_msg; + /* Open the file */ stl->fp = fopen(file, "r"); if(stl->fp == NULL) @@ -189,7 +186,7 @@ stl_initialize(stl_file *stl, char *file) stl->stats.original_num_facets = stl->stats.number_of_facets; } -static void +void stl_allocate(stl_file *stl) { /* Allocate memory for the entire .STL file */ @@ -210,7 +207,8 @@ stl_open_merge(stl_file *stl, char *file) int first_facet; first_facet = stl->stats.number_of_facets; - stl_initialize(stl, file); + stl_initialize(stl); + stl_count_facets(stl, file); stl_reallocate(stl); stl_read(stl, first_facet, 0); } @@ -236,12 +234,7 @@ stl_read(stl_file *stl, int first_facet, int first) { stl_facet facet; int i; - float diff_x; - float diff_y; - float diff_z; - float max_diff; - if(stl->stats.type == binary) { fseek(stl->fp, HEADER_SIZE, SEEK_SET); @@ -291,59 +284,69 @@ stl_read(stl_file *stl, int first_facet, int first) /* Write the facet into memory. */ stl->facet_start[i] = facet; - /* while we are going through all of the facets, let's find the */ - /* maximum and minimum values for x, y, and z */ - - /* Initialize the max and min values the first time through*/ - if(first) - { - stl->stats.max.x = facet.vertex[0].x; - stl->stats.min.x = facet.vertex[0].x; - stl->stats.max.y = facet.vertex[0].y; - stl->stats.min.y = facet.vertex[0].y; - stl->stats.max.z = facet.vertex[0].z; - stl->stats.min.z = facet.vertex[0].z; - - diff_x = ABS(facet.vertex[0].x - facet.vertex[1].x); - diff_y = ABS(facet.vertex[0].y - facet.vertex[1].y); - diff_z = ABS(facet.vertex[0].z - facet.vertex[1].z); - max_diff = STL_MAX(diff_x, diff_y); - max_diff = STL_MAX(diff_z, max_diff); - stl->stats.shortest_edge = max_diff; - - first = 0; - } - /* now find the max and min values */ - stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[0].x); - stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[0].x); - stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[0].y); - stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[0].y); - stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[0].z); - stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[0].z); - - stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[1].x); - stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[1].x); - stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[1].y); - stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[1].y); - stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[1].z); - stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[1].z); - - stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[2].x); - stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[2].x); - stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[2].y); - stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[2].y); - stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[2].z); - stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[2].z); + stl_facet_stats(stl, facet, first); } - stl->stats.size.x = stl->stats.max.x - stl->stats.min.x; - stl->stats.size.y = stl->stats.max.y - stl->stats.min.y; - stl->stats.size.z = stl->stats.max.z - stl->stats.min.z; - stl->stats.bounding_diameter = - sqrt(stl->stats.size.x * stl->stats.size.x + - stl->stats.size.y * stl->stats.size.y + - stl->stats.size.z * stl->stats.size.z); + stl->stats.size.x = stl->stats.max.x - stl->stats.min.x; + stl->stats.size.y = stl->stats.max.y - stl->stats.min.y; + stl->stats.size.z = stl->stats.max.z - stl->stats.min.z; + stl->stats.bounding_diameter = sqrt( + stl->stats.size.x * stl->stats.size.x + + stl->stats.size.y * stl->stats.size.y + + stl->stats.size.z * stl->stats.size.z + ); } +void +stl_facet_stats(stl_file *stl, stl_facet facet, int first) +{ + float diff_x; + float diff_y; + float diff_z; + float max_diff; + /* while we are going through all of the facets, let's find the */ + /* maximum and minimum values for x, y, and z */ + + /* Initialize the max and min values the first time through*/ + if (first) { + stl->stats.max.x = facet.vertex[0].x; + stl->stats.min.x = facet.vertex[0].x; + stl->stats.max.y = facet.vertex[0].y; + stl->stats.min.y = facet.vertex[0].y; + stl->stats.max.z = facet.vertex[0].z; + stl->stats.min.z = facet.vertex[0].z; + + diff_x = ABS(facet.vertex[0].x - facet.vertex[1].x); + diff_y = ABS(facet.vertex[0].y - facet.vertex[1].y); + diff_z = ABS(facet.vertex[0].z - facet.vertex[1].z); + max_diff = STL_MAX(diff_x, diff_y); + max_diff = STL_MAX(diff_z, max_diff); + stl->stats.shortest_edge = max_diff; + + first = 0; + } + + /* now find the max and min values */ + stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[0].x); + stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[0].x); + stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[0].y); + stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[0].y); + stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[0].z); + stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[0].z); + + stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[1].x); + stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[1].x); + stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[1].y); + stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[1].y); + stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[1].z); + stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[1].z); + + stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[2].x); + stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[2].x); + stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[2].y); + stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[2].y); + stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[2].z); + stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[2].z); +} void stl_close(stl_file *stl) diff --git a/xs/t/01_trianglemesh.t b/xs/t/01_trianglemesh.t index 97e98fcce..8d3c5dd0d 100644 --- a/xs/t/01_trianglemesh.t +++ b/xs/t/01_trianglemesh.t @@ -4,9 +4,23 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 1; +use Test::More tests => 3; is Slic3r::TriangleMesh::XS::hello_world(), 'Hello world!', 'hello world'; +my $cube = { + vertices => [ [20,20,0], [20,0,0], [0,0,0], [0,20,0], [20,20,20], [0,20,20], [0,0,20], [20,0,20] ], + facets => [ [0,1,2], [0,2,3], [4,5,6], [4,6,7], [0,4,7], [0,7,1], [1,7,6], [1,6,2], [2,6,5], [2,5,3], [4,0,3], [4,3,5] ], +}; + +{ + my $m = Slic3r::TriangleMesh::XS->new; + $m->ReadFromPerl($cube->{vertices}, $cube->{facets}); + $m->Repair; + my ($vertices, $facets) = @{$m->ToPerl}; + is_deeply $vertices, $cube->{vertices}, 'vertices arrayref roundtrip'; + is_deeply $facets, $cube->{facets}, 'facets arrayref roundtrip'; +} + __END__ diff --git a/xs/xsp/TriangleMesh.xsp b/xs/xsp/TriangleMesh.xsp index 82aa55024..be0d5b25e 100644 --- a/xs/xsp/TriangleMesh.xsp +++ b/xs/xsp/TriangleMesh.xsp @@ -8,6 +8,7 @@ TriangleMesh(); ~TriangleMesh(); void ReadSTLFile(char* input_file); + void ReadFromPerl(SV* vertices, SV* facets); void Repair(); void WriteOBJFile(char* output_file); AV* ToPerl(); -- cgit v1.2.3