New ReadFromPerl() method

xs
Alessandro Ranellucci 2013-07-03 11:38:01 +02:00
parent bb656ea72c
commit 6373322b84
6 changed files with 137 additions and 78 deletions

View File

@ -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;

View File

@ -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();

View File

@ -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);

View File

@ -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)

View File

@ -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__

View File

@ -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();