New ReadFromPerl() method
This commit is contained in:
parent
bb656ea72c
commit
6373322b84
6 changed files with 137 additions and 78 deletions
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue