Merge pull request #2278 from hroncok/admesh98
Updated to admesh 0.98.1
This commit is contained in:
commit
945567d1f3
File diff suppressed because it is too large
Load Diff
@ -1,21 +1,23 @@
|
|||||||
/* ADMesh -- process triangulated solid meshes
|
/* ADMesh -- process triangulated solid meshes
|
||||||
* Copyright (C) 1995 Anthony D. Martin
|
* Copyright (C) 1995, 1996 Anthony D. Martin <amartin@engr.csulb.edu>
|
||||||
|
* Copyright (C) 2013, 2014 several contributors, see AUTHORS
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2, or (at your option)
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* any later version.
|
* (at your option) any later version.
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* Questions, comments, suggestions, etc to
|
||||||
* along with this program; if not, write to the Free Software
|
* https://github.com/admesh/admesh/issues
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* Questions, comments, suggestions, etc to <amartin@engr.csulb.edu>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -26,13 +28,11 @@
|
|||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
static void stl_reverse_facet(stl_file *stl, int facet_num);
|
static void stl_reverse_facet(stl_file *stl, int facet_num);
|
||||||
/* static float stl_calculate_area(stl_facet *facet); */
|
|
||||||
static void stl_reverse_vector(float v[]);
|
static void stl_reverse_vector(float v[]);
|
||||||
int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag);
|
int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stl_reverse_facet(stl_file *stl, int facet_num)
|
stl_reverse_facet(stl_file *stl, int facet_num) {
|
||||||
{
|
|
||||||
stl_vertex tmp_vertex;
|
stl_vertex tmp_vertex;
|
||||||
/* int tmp_neighbor;*/
|
/* int tmp_neighbor;*/
|
||||||
int neighbor[3];
|
int neighbor[3];
|
||||||
@ -85,8 +85,7 @@ stl_reverse_facet(stl_file *stl, int facet_num)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_fix_normal_directions(stl_file *stl)
|
stl_fix_normal_directions(stl_file *stl) {
|
||||||
{
|
|
||||||
char *norm_sw;
|
char *norm_sw;
|
||||||
/* int edge_num;*/
|
/* int edge_num;*/
|
||||||
/* int vnot;*/
|
/* int vnot;*/
|
||||||
@ -95,9 +94,7 @@ stl_fix_normal_directions(stl_file *stl)
|
|||||||
/* int next_facet;*/
|
/* int next_facet;*/
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
int checked_before = 0;
|
struct stl_normal {
|
||||||
struct stl_normal
|
|
||||||
{
|
|
||||||
int facet_num;
|
int facet_num;
|
||||||
struct stl_normal *next;
|
struct stl_normal *next;
|
||||||
};
|
};
|
||||||
@ -106,11 +103,12 @@ stl_fix_normal_directions(stl_file *stl)
|
|||||||
struct stl_normal *newn;
|
struct stl_normal *newn;
|
||||||
struct stl_normal *temp;
|
struct stl_normal *temp;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Initialize linked list. */
|
/* Initialize linked list. */
|
||||||
head = (stl_normal*)malloc(sizeof(struct stl_normal));
|
head = (struct stl_normal*)malloc(sizeof(struct stl_normal));
|
||||||
if(head == NULL) perror("stl_fix_normal_directions");
|
if(head == NULL) perror("stl_fix_normal_directions");
|
||||||
tail = (stl_normal*)malloc(sizeof(struct stl_normal));
|
tail = (struct stl_normal*)malloc(sizeof(struct stl_normal));
|
||||||
if(tail == NULL) perror("stl_fix_normal_directions");
|
if(tail == NULL) perror("stl_fix_normal_directions");
|
||||||
head->next = tail;
|
head->next = tail;
|
||||||
tail->next = tail;
|
tail->next = tail;
|
||||||
@ -121,44 +119,34 @@ stl_fix_normal_directions(stl_file *stl)
|
|||||||
|
|
||||||
|
|
||||||
facet_num = 0;
|
facet_num = 0;
|
||||||
//If normal vector is not within tolerance and backwards:
|
/* If normal vector is not within tolerance and backwards:
|
||||||
//Arbitrarily starts at face 0. If this one is wrong, we're screwed. Thankfully, the chances
|
Arbitrarily starts at face 0. If this one is wrong, we're screwed. Thankfully, the chances
|
||||||
// of it being wrong randomly are low if most of the triangles are right:
|
of it being wrong randomly are low if most of the triangles are right: */
|
||||||
if(stl_check_normal_vector(stl, 0, 0) == 2)
|
if(stl_check_normal_vector(stl, 0, 0) == 2)
|
||||||
stl_reverse_facet(stl, 0);
|
stl_reverse_facet(stl, 0);
|
||||||
|
|
||||||
//Say that we've fixed this facet:
|
/* Say that we've fixed this facet: */
|
||||||
norm_sw[facet_num] = 1;
|
norm_sw[facet_num] = 1;
|
||||||
/* edge_num = 0;
|
|
||||||
vnot = stl->neighbors_start[0].which_vertex_not[0];
|
|
||||||
*/
|
|
||||||
checked++;
|
checked++;
|
||||||
|
|
||||||
for(;;)
|
for(;;) {
|
||||||
{
|
/* Add neighbors_to_list.
|
||||||
/* Add neighbors_to_list. */
|
Add unconnected neighbors to the list:a */
|
||||||
//Add unconnected neighbors to the list:a
|
for(j = 0; j < 3; j++) {
|
||||||
for(j = 0; j < 3; j++)
|
|
||||||
{
|
|
||||||
/* Reverse the neighboring facets if necessary. */
|
/* Reverse the neighboring facets if necessary. */
|
||||||
if(stl->neighbors_start[facet_num].which_vertex_not[j] > 2)
|
if(stl->neighbors_start[facet_num].which_vertex_not[j] > 2) {
|
||||||
{
|
/* If the facet has a neighbor that is -1, it means that edge isn't shared by another facet */
|
||||||
// If the facet has a neighbor that is -1, it means that edge isn't shared by another
|
if(stl->neighbors_start[facet_num].neighbor[j] != -1) {
|
||||||
// facet.
|
|
||||||
if(stl->neighbors_start[facet_num].neighbor[j] != -1)
|
|
||||||
{
|
|
||||||
stl_reverse_facet
|
stl_reverse_facet
|
||||||
(stl, stl->neighbors_start[facet_num].neighbor[j]);
|
(stl, stl->neighbors_start[facet_num].neighbor[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//If this edge of the facet is connected:
|
/* If this edge of the facet is connected: */
|
||||||
if(stl->neighbors_start[facet_num].neighbor[j] != -1)
|
if(stl->neighbors_start[facet_num].neighbor[j] != -1) {
|
||||||
{
|
/* If we haven't fixed this facet yet, add it to the list: */
|
||||||
//If we haven't fixed this facet yet, add it to the list:
|
if(norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1) {
|
||||||
if(norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1)
|
|
||||||
{
|
|
||||||
/* Add node to beginning of list. */
|
/* Add node to beginning of list. */
|
||||||
newn = (stl_normal*)malloc(sizeof(struct stl_normal));
|
newn = (struct stl_normal*)malloc(sizeof(struct stl_normal));
|
||||||
if(newn == NULL) perror("stl_fix_normal_directions");
|
if(newn == NULL) perror("stl_fix_normal_directions");
|
||||||
newn->facet_num = stl->neighbors_start[facet_num].neighbor[j];
|
newn->facet_num = stl->neighbors_start[facet_num].neighbor[j];
|
||||||
newn->next = head->next;
|
newn->next = head->next;
|
||||||
@ -167,40 +155,28 @@ stl_fix_normal_directions(stl_file *stl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Get next facet to fix from top of list. */
|
/* Get next facet to fix from top of list. */
|
||||||
if(head->next != tail)
|
if(head->next != tail) {
|
||||||
{
|
|
||||||
facet_num = head->next->facet_num;
|
facet_num = head->next->facet_num;
|
||||||
if(norm_sw[facet_num] != 1) /* If facet is in list mutiple times */
|
if(norm_sw[facet_num] != 1) { /* If facet is in list mutiple times */
|
||||||
{
|
|
||||||
norm_sw[facet_num] = 1; /* Record this one as being fixed. */
|
norm_sw[facet_num] = 1; /* Record this one as being fixed. */
|
||||||
checked++;
|
checked++;
|
||||||
}
|
}
|
||||||
temp = head->next; /* Delete this facet from the list. */
|
temp = head->next; /* Delete this facet from the list. */
|
||||||
head->next = head->next->next;
|
head->next = head->next->next;
|
||||||
free(temp);
|
free(temp);
|
||||||
}
|
} else { /* if we ran out of facets to fix: */
|
||||||
else //if we ran out of facets to fix:
|
|
||||||
{
|
|
||||||
/* All of the facets in this part have been fixed. */
|
/* All of the facets in this part have been fixed. */
|
||||||
stl->stats.number_of_parts += 1;
|
stl->stats.number_of_parts += 1;
|
||||||
/* There are (checked-checked_before) facets */
|
if(checked >= stl->stats.number_of_facets) {
|
||||||
/* in part stl->stats.number_of_parts */
|
|
||||||
checked_before = checked;
|
|
||||||
if(checked >= stl->stats.number_of_facets)
|
|
||||||
{
|
|
||||||
/* All of the facets have been checked. Bail out. */
|
/* All of the facets have been checked. Bail out. */
|
||||||
break;
|
break;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* There is another part here. Find it and continue. */
|
/* There is another part here. Find it and continue. */
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
if(norm_sw[i] == 0) {
|
||||||
if(norm_sw[i] == 0)
|
/* This is the first facet of the next part. */
|
||||||
{ /* This is the first facet of the next part. */
|
|
||||||
facet_num = i;
|
facet_num = i;
|
||||||
if(stl_check_normal_vector(stl, i, 0) == 2)
|
if(stl_check_normal_vector(stl, i, 0) == 2) {
|
||||||
{
|
|
||||||
stl_reverse_facet(stl, i);
|
stl_reverse_facet(stl, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,8 +194,7 @@ stl_fix_normal_directions(stl_file *stl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag)
|
stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) {
|
||||||
{
|
|
||||||
/* Returns 0 if the normal is within tolerance */
|
/* Returns 0 if the normal is within tolerance */
|
||||||
/* Returns 1 if the normal is not within tolerance, but direction is OK */
|
/* Returns 1 if the normal is not within tolerance, but direction is OK */
|
||||||
/* Returns 2 if the normal is not within tolerance and backwards */
|
/* Returns 2 if the normal is not within tolerance and backwards */
|
||||||
@ -236,8 +211,7 @@ stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag)
|
|||||||
|
|
||||||
if( (ABS(normal[0] - facet->normal.x) < 0.001)
|
if( (ABS(normal[0] - facet->normal.x) < 0.001)
|
||||||
&& (ABS(normal[1] - facet->normal.y) < 0.001)
|
&& (ABS(normal[1] - facet->normal.y) < 0.001)
|
||||||
&& (ABS(normal[2] - facet->normal.z) < 0.001))
|
&& (ABS(normal[2] - facet->normal.z) < 0.001)) {
|
||||||
{
|
|
||||||
/* It is not really necessary to change the values here */
|
/* It is not really necessary to change the values here */
|
||||||
/* but just for consistency, I will. */
|
/* but just for consistency, I will. */
|
||||||
facet->normal.x = normal[0];
|
facet->normal.x = normal[0];
|
||||||
@ -253,10 +227,8 @@ stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag)
|
|||||||
stl_normalize_vector(test_norm);
|
stl_normalize_vector(test_norm);
|
||||||
if( (ABS(normal[0] - test_norm[0]) < 0.001)
|
if( (ABS(normal[0] - test_norm[0]) < 0.001)
|
||||||
&& (ABS(normal[1] - test_norm[1]) < 0.001)
|
&& (ABS(normal[1] - test_norm[1]) < 0.001)
|
||||||
&& (ABS(normal[2] - test_norm[2]) < 0.001))
|
&& (ABS(normal[2] - test_norm[2]) < 0.001)) {
|
||||||
{
|
if(normal_fix_flag) {
|
||||||
if(normal_fix_flag)
|
|
||||||
{
|
|
||||||
facet->normal.x = normal[0];
|
facet->normal.x = normal[0];
|
||||||
facet->normal.y = normal[1];
|
facet->normal.y = normal[1];
|
||||||
facet->normal.z = normal[2];
|
facet->normal.z = normal[2];
|
||||||
@ -268,11 +240,9 @@ stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag)
|
|||||||
stl_reverse_vector(test_norm);
|
stl_reverse_vector(test_norm);
|
||||||
if( (ABS(normal[0] - test_norm[0]) < 0.001)
|
if( (ABS(normal[0] - test_norm[0]) < 0.001)
|
||||||
&& (ABS(normal[1] - test_norm[1]) < 0.001)
|
&& (ABS(normal[1] - test_norm[1]) < 0.001)
|
||||||
&& (ABS(normal[2] - test_norm[2]) < 0.001))
|
&& (ABS(normal[2] - test_norm[2]) < 0.001)) {
|
||||||
{
|
|
||||||
/* Facet is backwards. */
|
/* Facet is backwards. */
|
||||||
if(normal_fix_flag)
|
if(normal_fix_flag) {
|
||||||
{
|
|
||||||
facet->normal.x = normal[0];
|
facet->normal.x = normal[0];
|
||||||
facet->normal.y = normal[1];
|
facet->normal.y = normal[1];
|
||||||
facet->normal.z = normal[2];
|
facet->normal.z = normal[2];
|
||||||
@ -280,8 +250,7 @@ stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag)
|
|||||||
}
|
}
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
if(normal_fix_flag)
|
if(normal_fix_flag) {
|
||||||
{
|
|
||||||
facet->normal.x = normal[0];
|
facet->normal.x = normal[0];
|
||||||
facet->normal.y = normal[1];
|
facet->normal.y = normal[1];
|
||||||
facet->normal.z = normal[2];
|
facet->normal.z = normal[2];
|
||||||
@ -291,8 +260,7 @@ stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stl_reverse_vector(float v[])
|
stl_reverse_vector(float v[]) {
|
||||||
{
|
|
||||||
v[0] *= -1;
|
v[0] *= -1;
|
||||||
v[1] *= -1;
|
v[1] *= -1;
|
||||||
v[2] *= -1;
|
v[2] *= -1;
|
||||||
@ -300,8 +268,7 @@ stl_reverse_vector(float v[])
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_calculate_normal(float normal[], stl_facet *facet)
|
stl_calculate_normal(float normal[], stl_facet *facet) {
|
||||||
{
|
|
||||||
float v1[3];
|
float v1[3];
|
||||||
float v2[3];
|
float v2[3];
|
||||||
|
|
||||||
@ -317,48 +284,14 @@ stl_calculate_normal(float normal[], stl_facet *facet)
|
|||||||
normal[2] = (float)((double)v1[0] * (double)v2[1]) - ((double)v1[1] * (double)v2[0]);
|
normal[2] = (float)((double)v1[0] * (double)v2[1]) - ((double)v1[1] * (double)v2[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void stl_normalize_vector(float v[]) {
|
||||||
static float
|
|
||||||
stl_calculate_area(stl_facet *facet)
|
|
||||||
{
|
|
||||||
float cross[3][3];
|
|
||||||
float sum[3];
|
|
||||||
float normal[3];
|
|
||||||
float area;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
cross[i][0] = ((facet->vertex[i].y * facet->vertex[(i + 1) % 3].z) -
|
|
||||||
(facet->vertex[i].z * facet->vertex[(i + 1) % 3].y));
|
|
||||||
cross[i][1] = ((facet->vertex[i].z * facet->vertex[(i + 1) % 3].x) -
|
|
||||||
(facet->vertex[i].x * facet->vertex[(i + 1) % 3].z));
|
|
||||||
cross[i][2] = ((facet->vertex[i].x * facet->vertex[(i + 1) % 3].y) -
|
|
||||||
(facet->vertex[i].y * facet->vertex[(i + 1) % 3].x));
|
|
||||||
}
|
|
||||||
|
|
||||||
sum[0] = cross[0][0] + cross[1][0] + cross[2][0];
|
|
||||||
sum[1] = cross[0][1] + cross[1][1] + cross[2][1];
|
|
||||||
sum[2] = cross[0][2] + cross[1][2] + cross[2][2];
|
|
||||||
|
|
||||||
stl_calculate_normal(normal, facet);
|
|
||||||
stl_normalize_vector(normal);
|
|
||||||
area = 0.5 * (normal[0] * sum[0] + normal[1] * sum[1] +
|
|
||||||
normal[2] * sum[2]);
|
|
||||||
return ABS(area);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void stl_normalize_vector(float v[])
|
|
||||||
{
|
|
||||||
double length;
|
double length;
|
||||||
double factor;
|
double factor;
|
||||||
float min_normal_length;
|
float min_normal_length;
|
||||||
|
|
||||||
length = sqrt((double)v[0] * (double)v[0] + (double)v[1] * (double)v[1] + (double)v[2] * (double)v[2]);
|
length = sqrt((double)v[0] * (double)v[0] + (double)v[1] * (double)v[1] + (double)v[2] * (double)v[2]);
|
||||||
min_normal_length = 0.000000000001;
|
min_normal_length = 0.000000000001;
|
||||||
if(length < min_normal_length)
|
if(length < min_normal_length) {
|
||||||
{
|
|
||||||
v[0] = 0.0;
|
v[0] = 0.0;
|
||||||
v[1] = 0.0;
|
v[1] = 0.0;
|
||||||
v[2] = 0.0;
|
v[2] = 0.0;
|
||||||
@ -371,24 +304,24 @@ void stl_normalize_vector(float v[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_fix_normal_values(stl_file *stl)
|
stl_fix_normal_values(stl_file *stl) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
if (stl->error) return;
|
||||||
{
|
|
||||||
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
stl_check_normal_vector(stl, i, 1);
|
stl_check_normal_vector(stl, i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_reverse_all_facets(stl_file *stl)
|
stl_reverse_all_facets(stl_file *stl) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
float normal[3];
|
float normal[3];
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
if (stl->error) return;
|
||||||
{
|
|
||||||
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
stl_reverse_facet(stl, i);
|
stl_reverse_facet(stl, i);
|
||||||
stl_calculate_normal(normal, &stl->facet_start[i]);
|
stl_calculate_normal(normal, &stl->facet_start[i]);
|
||||||
stl_normalize_vector(normal);
|
stl_normalize_vector(normal);
|
||||||
|
@ -1,31 +1,34 @@
|
|||||||
/* ADMesh -- process triangulated solid meshes
|
/* ADMesh -- process triangulated solid meshes
|
||||||
* Copyright (C) 1995, 1996 Anthony D. Martin
|
* Copyright (C) 1995, 1996 Anthony D. Martin <amartin@engr.csulb.edu>
|
||||||
|
* Copyright (C) 2013, 2014 several contributors, see AUTHORS
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2, or (at your option)
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* any later version.
|
* (at your option) any later version.
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* Questions, comments, suggestions, etc to
|
||||||
* along with this program; if not, write to the Free Software
|
* https://github.com/admesh/admesh/issues
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* Questions, comments, suggestions, etc to <amartin@engr.csulb.edu>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_invalidate_shared_vertices(stl_file *stl)
|
stl_invalidate_shared_vertices(stl_file *stl) {
|
||||||
{
|
if (stl->error) return;
|
||||||
|
|
||||||
if (stl->v_indices != NULL) {
|
if (stl->v_indices != NULL) {
|
||||||
free(stl->v_indices);
|
free(stl->v_indices);
|
||||||
stl->v_indices = NULL;
|
stl->v_indices = NULL;
|
||||||
@ -37,8 +40,7 @@ stl_invalidate_shared_vertices(stl_file *stl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_generate_shared_vertices(stl_file *stl)
|
stl_generate_shared_vertices(stl_file *stl) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
int first_facet;
|
int first_facet;
|
||||||
@ -50,7 +52,9 @@ stl_generate_shared_vertices(stl_file *stl)
|
|||||||
int next_facet;
|
int next_facet;
|
||||||
int reversed;
|
int reversed;
|
||||||
|
|
||||||
// make sure this function is idempotent and does not leak memory
|
if (stl->error) return;
|
||||||
|
|
||||||
|
/* make sure this function is idempotent and does not leak memory */
|
||||||
stl_invalidate_shared_vertices(stl);
|
stl_invalidate_shared_vertices(stl);
|
||||||
|
|
||||||
stl->v_indices = (v_indices_struct*)
|
stl->v_indices = (v_indices_struct*)
|
||||||
@ -62,25 +66,20 @@ stl_generate_shared_vertices(stl_file *stl)
|
|||||||
stl->stats.shared_malloced = stl->stats.number_of_facets / 2;
|
stl->stats.shared_malloced = stl->stats.number_of_facets / 2;
|
||||||
stl->stats.shared_vertices = 0;
|
stl->stats.shared_vertices = 0;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
|
||||||
stl->v_indices[i].vertex[0] = -1;
|
stl->v_indices[i].vertex[0] = -1;
|
||||||
stl->v_indices[i].vertex[1] = -1;
|
stl->v_indices[i].vertex[1] = -1;
|
||||||
stl->v_indices[i].vertex[2] = -1;
|
stl->v_indices[i].vertex[2] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
|
||||||
first_facet = i;
|
first_facet = i;
|
||||||
for(j = 0; j < 3; j++)
|
for(j = 0; j < 3; j++) {
|
||||||
{
|
if(stl->v_indices[i].vertex[j] != -1) {
|
||||||
if(stl->v_indices[i].vertex[j] != -1)
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(stl->stats.shared_vertices == stl->stats.shared_malloced)
|
if(stl->stats.shared_vertices == stl->stats.shared_malloced) {
|
||||||
{
|
|
||||||
stl->stats.shared_malloced += 1024;
|
stl->stats.shared_malloced += 1024;
|
||||||
stl->v_shared = (stl_vertex*)realloc(stl->v_shared,
|
stl->v_shared = (stl_vertex*)realloc(stl->v_shared,
|
||||||
stl->stats.shared_malloced * sizeof(stl_vertex));
|
stl->stats.shared_malloced * sizeof(stl_vertex));
|
||||||
@ -95,32 +94,22 @@ stl_generate_shared_vertices(stl_file *stl)
|
|||||||
facet_num = i;
|
facet_num = i;
|
||||||
vnot = (j + 2) % 3;
|
vnot = (j + 2) % 3;
|
||||||
|
|
||||||
for(;;)
|
for(;;) {
|
||||||
{
|
if(vnot > 2) {
|
||||||
if(vnot > 2)
|
if(direction == 0) {
|
||||||
{
|
|
||||||
if(direction == 0)
|
|
||||||
{
|
|
||||||
pivot_vertex = (vnot + 2) % 3;
|
pivot_vertex = (vnot + 2) % 3;
|
||||||
next_edge = pivot_vertex;
|
next_edge = pivot_vertex;
|
||||||
direction = 1;
|
direction = 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
pivot_vertex = (vnot + 1) % 3;
|
pivot_vertex = (vnot + 1) % 3;
|
||||||
next_edge = vnot % 3;
|
next_edge = vnot % 3;
|
||||||
direction = 0;
|
direction = 0;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if(direction == 0) {
|
||||||
{
|
|
||||||
if(direction == 0)
|
|
||||||
{
|
|
||||||
pivot_vertex = (vnot + 1) % 3;
|
pivot_vertex = (vnot + 1) % 3;
|
||||||
next_edge = vnot;
|
next_edge = vnot;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
pivot_vertex = (vnot + 2) % 3;
|
pivot_vertex = (vnot + 2) % 3;
|
||||||
next_edge = pivot_vertex;
|
next_edge = pivot_vertex;
|
||||||
}
|
}
|
||||||
@ -129,28 +118,20 @@ stl_generate_shared_vertices(stl_file *stl)
|
|||||||
stl->stats.shared_vertices;
|
stl->stats.shared_vertices;
|
||||||
|
|
||||||
next_facet = stl->neighbors_start[facet_num].neighbor[next_edge];
|
next_facet = stl->neighbors_start[facet_num].neighbor[next_edge];
|
||||||
if(next_facet == -1)
|
if(next_facet == -1) {
|
||||||
{
|
if(reversed) {
|
||||||
if(reversed)
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
direction = 1;
|
direction = 1;
|
||||||
vnot = (j + 1) % 3;
|
vnot = (j + 1) % 3;
|
||||||
reversed = 1;
|
reversed = 1;
|
||||||
facet_num = first_facet;
|
facet_num = first_facet;
|
||||||
}
|
}
|
||||||
}
|
} else if(next_facet != first_facet) {
|
||||||
else if(next_facet != first_facet)
|
|
||||||
{
|
|
||||||
vnot = stl->neighbors_start[facet_num].
|
vnot = stl->neighbors_start[facet_num].
|
||||||
which_vertex_not[next_edge];
|
which_vertex_not[next_edge];
|
||||||
facet_num = next_facet;
|
facet_num = next_facet;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,37 +141,35 @@ stl_generate_shared_vertices(stl_file *stl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_write_off(stl_file *stl, char *file)
|
stl_write_off(stl_file *stl, char *file) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = fopen(file, "w");
|
||||||
if(fp == NULL)
|
if(fp == NULL) {
|
||||||
{
|
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
||||||
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing",
|
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing",
|
||||||
file);
|
file);
|
||||||
perror(error_msg);
|
perror(error_msg);
|
||||||
free(error_msg);
|
free(error_msg);
|
||||||
exit(1);
|
stl->error = 1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "OFF\n");
|
fprintf(fp, "OFF\n");
|
||||||
fprintf(fp, "%d %d 0\n",
|
fprintf(fp, "%d %d 0\n",
|
||||||
stl->stats.shared_vertices, stl->stats.number_of_facets);
|
stl->stats.shared_vertices, stl->stats.number_of_facets);
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.shared_vertices; i++)
|
for(i = 0; i < stl->stats.shared_vertices; i++) {
|
||||||
{
|
|
||||||
fprintf(fp, "\t%f %f %f\n",
|
fprintf(fp, "\t%f %f %f\n",
|
||||||
stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z);
|
stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z);
|
||||||
}
|
}
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
|
||||||
fprintf(fp, "\t3 %d %d %d\n", stl->v_indices[i].vertex[0],
|
fprintf(fp, "\t3 %d %d %d\n", stl->v_indices[i].vertex[0],
|
||||||
stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
|
stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
|
||||||
}
|
}
|
||||||
@ -198,24 +177,24 @@ stl_write_off(stl_file *stl, char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_write_vrml(stl_file *stl, char *file)
|
stl_write_vrml(stl_file *stl, char *file) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = fopen(file, "w");
|
||||||
if(fp == NULL)
|
if(fp == NULL) {
|
||||||
{
|
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
||||||
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing",
|
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing",
|
||||||
file);
|
file);
|
||||||
perror(error_msg);
|
perror(error_msg);
|
||||||
free(error_msg);
|
free(error_msg);
|
||||||
exit(1);
|
stl->error = 1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "#VRML V1.0 ascii\n\n");
|
fprintf(fp, "#VRML V1.0 ascii\n\n");
|
||||||
@ -233,8 +212,7 @@ stl_write_vrml(stl_file *stl, char *file)
|
|||||||
fprintf(fp, "\t\tDEF STLVertices Coordinate3 {\n");
|
fprintf(fp, "\t\tDEF STLVertices Coordinate3 {\n");
|
||||||
fprintf(fp, "\t\t\tpoint [\n");
|
fprintf(fp, "\t\t\tpoint [\n");
|
||||||
|
|
||||||
for(i = 0; i < (stl->stats.shared_vertices - 1); i++)
|
for(i = 0; i < (stl->stats.shared_vertices - 1); i++) {
|
||||||
{
|
|
||||||
fprintf(fp, "\t\t\t\t%f %f %f,\n",
|
fprintf(fp, "\t\t\t\t%f %f %f,\n",
|
||||||
stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z);
|
stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z);
|
||||||
}
|
}
|
||||||
@ -244,8 +222,7 @@ stl_write_vrml(stl_file *stl, char *file)
|
|||||||
fprintf(fp, "\t\tDEF STLTriangles IndexedFaceSet {\n");
|
fprintf(fp, "\t\tDEF STLTriangles IndexedFaceSet {\n");
|
||||||
fprintf(fp, "\t\t\tcoordIndex [\n");
|
fprintf(fp, "\t\t\tcoordIndex [\n");
|
||||||
|
|
||||||
for(i = 0; i < (stl->stats.number_of_facets - 1); i++)
|
for(i = 0; i < (stl->stats.number_of_facets - 1); i++) {
|
||||||
{
|
|
||||||
fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", stl->v_indices[i].vertex[0],
|
fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", stl->v_indices[i].vertex[0],
|
||||||
stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
|
stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
|
||||||
}
|
}
|
||||||
@ -259,15 +236,19 @@ stl_write_vrml(stl_file *stl, char *file)
|
|||||||
|
|
||||||
void stl_write_obj (stl_file *stl, char *file) {
|
void stl_write_obj (stl_file *stl, char *file) {
|
||||||
int i;
|
int i;
|
||||||
|
FILE* fp;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
FILE* fp = fopen(file, "w");
|
fp = fopen(file, "w");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
char* error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
char* error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
||||||
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
|
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file);
|
||||||
perror(error_msg);
|
perror(error_msg);
|
||||||
free(error_msg);
|
free(error_msg);
|
||||||
exit(1);
|
stl->error = 1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < stl->stats.shared_vertices; i++) {
|
for (i = 0; i < stl->stats.shared_vertices; i++) {
|
||||||
|
@ -1,25 +1,34 @@
|
|||||||
/* ADMesh -- process triangulated solid meshes
|
/* ADMesh -- process triangulated solid meshes
|
||||||
* Copyright (C) 1995, 1996 Anthony D. Martin
|
* Copyright (C) 1995, 1996 Anthony D. Martin <amartin@engr.csulb.edu>
|
||||||
|
* Copyright (C) 2013, 2014 several contributors, see AUTHORS
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2, or (at your option)
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* any later version.
|
* (at your option) any later version.
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* Questions, comments, suggestions, etc to
|
||||||
* along with this program; if not, write to the Free Software
|
* https://github.com/admesh/admesh/issues
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* Questions, comments, suggestions, etc to <amartin@engr.csulb.edu>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef __admesh_stl__
|
||||||
|
#define __admesh_stl__
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STL_MAX(A,B) ((A)>(B)? (A):(B))
|
#define STL_MAX(A,B) ((A)>(B)? (A):(B))
|
||||||
#define STL_MIN(A,B) ((A)<(B)? (A):(B))
|
#define STL_MIN(A,B) ((A)<(B)? (A):(B))
|
||||||
#define ABS(X) ((X) < 0 ? -(X) : (X))
|
#define ABS(X) ((X) < 0 ? -(X) : (X))
|
||||||
@ -31,60 +40,52 @@
|
|||||||
#define ASCII_LINES_PER_FACET 7
|
#define ASCII_LINES_PER_FACET 7
|
||||||
#define SIZEOF_EDGE_SORT 24
|
#define SIZEOF_EDGE_SORT 24
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
float z;
|
float z;
|
||||||
}stl_vertex;
|
} stl_vertex;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
float z;
|
float z;
|
||||||
}stl_normal;
|
} stl_normal;
|
||||||
|
|
||||||
typedef char stl_extra[2];
|
typedef char stl_extra[2];
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
stl_normal normal;
|
stl_normal normal;
|
||||||
stl_vertex vertex[3];
|
stl_vertex vertex[3];
|
||||||
stl_extra extra;
|
stl_extra extra;
|
||||||
}stl_facet;
|
} stl_facet;
|
||||||
#define SIZEOF_STL_FACET 50
|
#define SIZEOF_STL_FACET 50
|
||||||
|
|
||||||
typedef enum {binary, ascii, inmemory} stl_type;
|
typedef enum {binary, ascii, inmemory} stl_type;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
stl_vertex p1;
|
stl_vertex p1;
|
||||||
stl_vertex p2;
|
stl_vertex p2;
|
||||||
int facet_number;
|
int facet_number;
|
||||||
}stl_edge;
|
} stl_edge;
|
||||||
|
|
||||||
typedef struct stl_hash_edge
|
typedef struct stl_hash_edge {
|
||||||
{
|
|
||||||
unsigned key[6];
|
unsigned key[6];
|
||||||
int facet_number;
|
int facet_number;
|
||||||
int which_edge;
|
int which_edge;
|
||||||
struct stl_hash_edge *next;
|
struct stl_hash_edge *next;
|
||||||
}stl_hash_edge;
|
} stl_hash_edge;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
int neighbor[3];
|
int neighbor[3];
|
||||||
char which_vertex_not[3];
|
char which_vertex_not[3];
|
||||||
}stl_neighbors;
|
} stl_neighbors;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
int vertex[3];
|
int vertex[3];
|
||||||
}v_indices_struct;
|
} v_indices_struct;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
char header[81];
|
char header[81];
|
||||||
stl_type type;
|
stl_type type;
|
||||||
int number_of_facets;
|
int number_of_facets;
|
||||||
@ -117,10 +118,9 @@ typedef struct
|
|||||||
int collisions;
|
int collisions;
|
||||||
int shared_vertices;
|
int shared_vertices;
|
||||||
int shared_malloced;
|
int shared_malloced;
|
||||||
}stl_stats;
|
} stl_stats;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
stl_facet *facet_start;
|
stl_facet *facet_start;
|
||||||
stl_edge *edge_start;
|
stl_edge *edge_start;
|
||||||
@ -131,7 +131,8 @@ typedef struct
|
|||||||
v_indices_struct *v_indices;
|
v_indices_struct *v_indices;
|
||||||
stl_vertex *v_shared;
|
stl_vertex *v_shared;
|
||||||
stl_stats stats;
|
stl_stats stats;
|
||||||
}stl_file;
|
char error;
|
||||||
|
} stl_file;
|
||||||
|
|
||||||
|
|
||||||
extern void stl_open(stl_file *stl, char *file);
|
extern void stl_open(stl_file *stl, char *file);
|
||||||
@ -139,8 +140,11 @@ extern void stl_close(stl_file *stl);
|
|||||||
extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file);
|
extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file);
|
||||||
extern void stl_print_edges(stl_file *stl, FILE *file);
|
extern void stl_print_edges(stl_file *stl, FILE *file);
|
||||||
extern void stl_print_neighbors(stl_file *stl, char *file);
|
extern void stl_print_neighbors(stl_file *stl, char *file);
|
||||||
|
extern void stl_put_little_int(FILE *fp, int value_in);
|
||||||
|
extern void stl_put_little_float(FILE *fp, float value_in);
|
||||||
extern void stl_write_ascii(stl_file *stl, const char *file, const char *label);
|
extern void stl_write_ascii(stl_file *stl, const char *file, const char *label);
|
||||||
extern void stl_write_binary(stl_file *stl, const char *file, const char *label);
|
extern void stl_write_binary(stl_file *stl, const char *file, const char *label);
|
||||||
|
extern void stl_write_binary_block(stl_file *stl, FILE *fp);
|
||||||
extern void stl_check_facets_exact(stl_file *stl);
|
extern void stl_check_facets_exact(stl_file *stl);
|
||||||
extern void stl_check_facets_nearby(stl_file *stl, float tolerance);
|
extern void stl_check_facets_nearby(stl_file *stl, float tolerance);
|
||||||
extern void stl_remove_unconnected_facets(stl_file *stl);
|
extern void stl_remove_unconnected_facets(stl_file *stl);
|
||||||
@ -154,6 +158,7 @@ extern void stl_fill_holes(stl_file *stl);
|
|||||||
extern void stl_fix_normal_directions(stl_file *stl);
|
extern void stl_fix_normal_directions(stl_file *stl);
|
||||||
extern void stl_fix_normal_values(stl_file *stl);
|
extern void stl_fix_normal_values(stl_file *stl);
|
||||||
extern void stl_reverse_all_facets(stl_file *stl);
|
extern void stl_reverse_all_facets(stl_file *stl);
|
||||||
|
extern void stl_translate(stl_file *stl, float x, float y, float z);
|
||||||
extern void stl_translate_relative(stl_file *stl, float x, float y, float z);
|
extern void stl_translate_relative(stl_file *stl, float x, float y, float z);
|
||||||
extern void stl_scale_versor(stl_file *stl, float versor[3]);
|
extern void stl_scale_versor(stl_file *stl, float versor[3]);
|
||||||
extern void stl_scale(stl_file *stl, float factor);
|
extern void stl_scale(stl_file *stl, float factor);
|
||||||
@ -174,11 +179,23 @@ extern void stl_calculate_normal(float normal[], stl_facet *facet);
|
|||||||
extern void stl_normalize_vector(float v[]);
|
extern void stl_normalize_vector(float v[]);
|
||||||
extern void stl_calculate_volume(stl_file *stl);
|
extern void stl_calculate_volume(stl_file *stl);
|
||||||
|
|
||||||
|
extern void stl_repair(stl_file *stl, int fixall_flag, int exact_flag, int tolerance_flag, float tolerance, int increment_flag, float increment, int nearby_flag, int iterations, int remove_unconnected_flag, int fill_holes_flag, int normal_directions_flag, int normal_values_flag, int reverse_all_flag, int verbose_flag);
|
||||||
|
|
||||||
extern void stl_initialize(stl_file *stl);
|
extern void stl_initialize(stl_file *stl);
|
||||||
static void stl_count_facets(stl_file *stl, char *file);
|
extern void stl_count_facets(stl_file *stl, char *file);
|
||||||
extern void stl_allocate(stl_file *stl);
|
extern void stl_allocate(stl_file *stl);
|
||||||
static void stl_read(stl_file *stl, int first_facet, int first);
|
extern void stl_read(stl_file *stl, int first_facet, int first);
|
||||||
extern void stl_facet_stats(stl_file *stl, stl_facet facet, int first);
|
extern void stl_facet_stats(stl_file *stl, stl_facet facet, int first);
|
||||||
extern void stl_reallocate(stl_file *stl);
|
extern void stl_reallocate(stl_file *stl);
|
||||||
extern void stl_add_facet(stl_file *stl, stl_facet *new_facet);
|
extern void stl_add_facet(stl_file *stl, stl_facet *new_facet);
|
||||||
extern void stl_get_size(stl_file *stl);
|
extern void stl_get_size(stl_file *stl);
|
||||||
|
|
||||||
|
extern void stl_clear_error(stl_file *stl);
|
||||||
|
extern int stl_get_error(stl_file *stl);
|
||||||
|
extern void stl_exit_on_error(stl_file *stl);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -1,26 +1,29 @@
|
|||||||
/* ADMesh -- process triangulated solid meshes
|
/* ADMesh -- process triangulated solid meshes
|
||||||
* Copyright (C) 1995, 1996 Anthony D. Martin
|
* Copyright (C) 1995, 1996 Anthony D. Martin <amartin@engr.csulb.edu>
|
||||||
|
* Copyright (C) 2013, 2014 several contributors, see AUTHORS
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2, or (at your option)
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* any later version.
|
* (at your option) any later version.
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* Questions, comments, suggestions, etc to
|
||||||
* along with this program; if not, write to the Free Software
|
* https://github.com/admesh/admesh/issues
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* Questions, comments, suggestions, etc to <amartin@engr.csulb.edu>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#if !defined(SEEK_SET)
|
#if !defined(SEEK_SET)
|
||||||
#define SEEK_SET 0
|
#define SEEK_SET 0
|
||||||
@ -28,18 +31,15 @@
|
|||||||
#define SEEK_END 2
|
#define SEEK_END 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void stl_put_little_int(FILE *fp, int value);
|
|
||||||
static void stl_put_little_float(FILE *fp, float value_in);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_print_edges(stl_file *stl, FILE *file)
|
stl_print_edges(stl_file *stl, FILE *file) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
int edges_allocated;
|
int edges_allocated;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
edges_allocated = stl->stats.number_of_facets * 3;
|
edges_allocated = stl->stats.number_of_facets * 3;
|
||||||
for(i = 0; i < edges_allocated; i++)
|
for(i = 0; i < edges_allocated; i++) {
|
||||||
{
|
|
||||||
fprintf(file, "%d, %f, %f, %f, %f, %f, %f\n",
|
fprintf(file, "%d, %f, %f, %f, %f, %f, %f\n",
|
||||||
stl->edge_start[i].facet_number,
|
stl->edge_start[i].facet_number,
|
||||||
stl->edge_start[i].p1.x, stl->edge_start[i].p1.y,
|
stl->edge_start[i].p1.x, stl->edge_start[i].p1.y,
|
||||||
@ -50,19 +50,22 @@ stl_print_edges(stl_file *stl, FILE *file)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_stats_out(stl_file *stl, FILE *file, char *input_file)
|
stl_stats_out(stl_file *stl, FILE *file, char *input_file) {
|
||||||
{
|
if (stl->error) return;
|
||||||
|
|
||||||
|
/* this is here for Slic3r, without our config.h
|
||||||
|
it won't use this part of the code anyway */
|
||||||
|
#ifndef VERSION
|
||||||
|
#define VERSION "unknown"
|
||||||
|
#endif
|
||||||
fprintf(file, "\n\
|
fprintf(file, "\n\
|
||||||
================= Results produced by ADMesh version 0.95 ================\n");
|
================= Results produced by ADMesh version " VERSION " ================\n");
|
||||||
fprintf(file, "\
|
fprintf(file, "\
|
||||||
Input file : %s\n", input_file);
|
Input file : %s\n", input_file);
|
||||||
if(stl->stats.type == binary)
|
if(stl->stats.type == binary) {
|
||||||
{
|
|
||||||
fprintf(file, "\
|
fprintf(file, "\
|
||||||
File type : Binary STL file\n");
|
File type : Binary STL file\n");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(file, "\
|
fprintf(file, "\
|
||||||
File type : ASCII STL file\n");
|
File type : ASCII STL file\n");
|
||||||
}
|
}
|
||||||
@ -100,7 +103,7 @@ Total disconnected facets : %5d %5d\n",
|
|||||||
stl->stats.connected_facets_3_edge);
|
stl->stats.connected_facets_3_edge);
|
||||||
|
|
||||||
fprintf(file,
|
fprintf(file,
|
||||||
"=== Processing Statistics === ===== Other Statistics =====\n");
|
"=== Processing Statistics === ===== Other Statistics =====\n");
|
||||||
fprintf(file, "\
|
fprintf(file, "\
|
||||||
Number of parts : %5d Volume : % f\n",
|
Number of parts : %5d Volume : % f\n",
|
||||||
stl->stats.number_of_parts, stl->stats.volume);
|
stl->stats.number_of_parts, stl->stats.volume);
|
||||||
@ -121,30 +124,29 @@ Normals fixed : %5d\n", stl->stats.normals_fixed);
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_write_ascii(stl_file *stl, const char *file, const char *label)
|
stl_write_ascii(stl_file *stl, const char *file, const char *label) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = fopen(file, "w");
|
||||||
if(fp == NULL)
|
if(fp == NULL) {
|
||||||
{
|
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
||||||
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing",
|
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing",
|
||||||
file);
|
file);
|
||||||
perror(error_msg);
|
perror(error_msg);
|
||||||
free(error_msg);
|
free(error_msg);
|
||||||
exit(1);
|
stl->error = 1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "solid %s\n", label);
|
fprintf(fp, "solid %s\n", label);
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
|
||||||
fprintf(fp, " facet normal % .8E % .8E % .8E\n",
|
fprintf(fp, " facet normal % .8E % .8E % .8E\n",
|
||||||
stl->facet_start[i].normal.x, stl->facet_start[i].normal.y,
|
stl->facet_start[i].normal.x, stl->facet_start[i].normal.y,
|
||||||
stl->facet_start[i].normal.z);
|
stl->facet_start[i].normal.z);
|
||||||
@ -168,27 +170,27 @@ stl_write_ascii(stl_file *stl, const char *file, const char *label)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_print_neighbors(stl_file *stl, char *file)
|
stl_print_neighbors(stl_file *stl, char *file) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = fopen(file, "w");
|
||||||
if(fp == NULL)
|
if(fp == NULL) {
|
||||||
{
|
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
||||||
sprintf(error_msg, "stl_print_neighbors: Couldn't open %s for writing",
|
sprintf(error_msg, "stl_print_neighbors: Couldn't open %s for writing",
|
||||||
file);
|
file);
|
||||||
perror(error_msg);
|
perror(error_msg);
|
||||||
free(error_msg);
|
free(error_msg);
|
||||||
exit(1);
|
stl->error = 1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
|
||||||
fprintf(fp, "%d, %d,%d, %d,%d, %d,%d\n",
|
fprintf(fp, "%d, %d,%d, %d,%d, %d,%d\n",
|
||||||
i,
|
i,
|
||||||
stl->neighbors_start[i].neighbor[0],
|
stl->neighbors_start[i].neighbor[0],
|
||||||
@ -201,12 +203,10 @@ stl_print_neighbors(stl_file *stl, char *file)
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
stl_put_little_int(FILE *fp, int value_in)
|
stl_put_little_int(FILE *fp, int value_in) {
|
||||||
{
|
|
||||||
int new_value;
|
int new_value;
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
int int_value;
|
int int_value;
|
||||||
char char_value[4];
|
char char_value[4];
|
||||||
} value;
|
} value;
|
||||||
@ -220,12 +220,10 @@ stl_put_little_int(FILE *fp, int value_in)
|
|||||||
fwrite(&new_value, sizeof(int), 1, fp);
|
fwrite(&new_value, sizeof(int), 1, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
stl_put_little_float(FILE *fp, float value_in)
|
stl_put_little_float(FILE *fp, float value_in) {
|
||||||
{
|
|
||||||
int new_value;
|
int new_value;
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
float float_value;
|
float float_value;
|
||||||
char char_value[4];
|
char char_value[4];
|
||||||
} value;
|
} value;
|
||||||
@ -239,35 +237,10 @@ stl_put_little_float(FILE *fp, float value_in)
|
|||||||
fwrite(&new_value, sizeof(int), 1, fp);
|
fwrite(&new_value, sizeof(int), 1, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_write_binary(stl_file *stl, const char *file, const char *label)
|
stl_write_binary_block(stl_file *stl, FILE *fp)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
|
||||||
int i;
|
int i;
|
||||||
char *error_msg;
|
|
||||||
|
|
||||||
|
|
||||||
/* Open the file */
|
|
||||||
fp = fopen(file, "wb");
|
|
||||||
if(fp == NULL)
|
|
||||||
{
|
|
||||||
error_msg = (char*)
|
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
|
||||||
sprintf(error_msg, "stl_write_binary: Couldn't open %s for writing",
|
|
||||||
file);
|
|
||||||
perror(error_msg);
|
|
||||||
free(error_msg);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "%s", label);
|
|
||||||
for(i = strlen(label); i < LABEL_SIZE; i++) putc(0, fp);
|
|
||||||
|
|
||||||
fseek(fp, LABEL_SIZE, SEEK_SET);
|
|
||||||
|
|
||||||
stl_put_little_int(fp, stl->stats.number_of_facets);
|
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++)
|
||||||
{
|
{
|
||||||
stl_put_little_float(fp, stl->facet_start[i].normal.x);
|
stl_put_little_float(fp, stl->facet_start[i].normal.x);
|
||||||
@ -285,13 +258,44 @@ stl_write_binary(stl_file *stl, const char *file, const char *label)
|
|||||||
fputc(stl->facet_start[i].extra[0], fp);
|
fputc(stl->facet_start[i].extra[0], fp);
|
||||||
fputc(stl->facet_start[i].extra[1], fp);
|
fputc(stl->facet_start[i].extra[1], fp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
stl_write_binary(stl_file *stl, const char *file, const char *label) {
|
||||||
|
FILE *fp;
|
||||||
|
int i;
|
||||||
|
char *error_msg;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
|
/* Open the file */
|
||||||
|
fp = fopen(file, "w");
|
||||||
|
if(fp == NULL) {
|
||||||
|
error_msg = (char*)
|
||||||
|
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
||||||
|
sprintf(error_msg, "stl_write_binary: Couldn't open %s for writing",
|
||||||
|
file);
|
||||||
|
perror(error_msg);
|
||||||
|
free(error_msg);
|
||||||
|
stl->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "%s", label);
|
||||||
|
for(i = strlen(label); i < LABEL_SIZE; i++) putc(0, fp);
|
||||||
|
|
||||||
|
fseek(fp, LABEL_SIZE, SEEK_SET);
|
||||||
|
|
||||||
|
stl_put_little_int(fp, stl->stats.number_of_facets);
|
||||||
|
|
||||||
|
stl_write_binary_block(stl, fp);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_write_vertex(stl_file *stl, int facet, int vertex)
|
stl_write_vertex(stl_file *stl, int facet, int vertex) {
|
||||||
{
|
if (stl->error) return;
|
||||||
printf(" vertex %d/%d % .8E % .8E % .8E\n", vertex, facet,
|
printf(" vertex %d/%d % .8E % .8E % .8E\n", vertex, facet,
|
||||||
stl->facet_start[facet].vertex[vertex].x,
|
stl->facet_start[facet].vertex[vertex].x,
|
||||||
stl->facet_start[facet].vertex[vertex].y,
|
stl->facet_start[facet].vertex[vertex].y,
|
||||||
@ -299,8 +303,8 @@ stl_write_vertex(stl_file *stl, int facet, int vertex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_write_facet(stl_file *stl, char *label, int facet)
|
stl_write_facet(stl_file *stl, char *label, int facet) {
|
||||||
{
|
if (stl->error) return;
|
||||||
printf("facet (%d)/ %s\n", facet, label);
|
printf("facet (%d)/ %s\n", facet, label);
|
||||||
stl_write_vertex(stl, facet, 0);
|
stl_write_vertex(stl, facet, 0);
|
||||||
stl_write_vertex(stl, facet, 1);
|
stl_write_vertex(stl, facet, 1);
|
||||||
@ -308,24 +312,21 @@ stl_write_facet(stl_file *stl, char *label, int facet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_write_edge(stl_file *stl, char *label, stl_hash_edge edge)
|
stl_write_edge(stl_file *stl, char *label, stl_hash_edge edge) {
|
||||||
{
|
if (stl->error) return;
|
||||||
printf("edge (%d)/(%d) %s\n", edge.facet_number, edge.which_edge, label);
|
printf("edge (%d)/(%d) %s\n", edge.facet_number, edge.which_edge, label);
|
||||||
if(edge.which_edge < 3)
|
if(edge.which_edge < 3) {
|
||||||
{
|
|
||||||
stl_write_vertex(stl, edge.facet_number, edge.which_edge % 3);
|
stl_write_vertex(stl, edge.facet_number, edge.which_edge % 3);
|
||||||
stl_write_vertex(stl, edge.facet_number, (edge.which_edge + 1) % 3);
|
stl_write_vertex(stl, edge.facet_number, (edge.which_edge + 1) % 3);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
stl_write_vertex(stl, edge.facet_number, (edge.which_edge + 1) % 3);
|
stl_write_vertex(stl, edge.facet_number, (edge.which_edge + 1) % 3);
|
||||||
stl_write_vertex(stl, edge.facet_number, edge.which_edge % 3);
|
stl_write_vertex(stl, edge.facet_number, edge.which_edge % 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_write_neighbor(stl_file *stl, int facet)
|
stl_write_neighbor(stl_file *stl, int facet) {
|
||||||
{
|
if (stl->error) return;
|
||||||
printf("Neighbors %d: %d, %d, %d ; %d, %d, %d\n", facet,
|
printf("Neighbors %d: %d, %d, %d ; %d, %d, %d\n", facet,
|
||||||
stl->neighbors_start[facet].neighbor[0],
|
stl->neighbors_start[facet].neighbor[0],
|
||||||
stl->neighbors_start[facet].neighbor[1],
|
stl->neighbors_start[facet].neighbor[1],
|
||||||
@ -336,8 +337,7 @@ stl_write_neighbor(stl_file *stl, int facet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_write_quad_object(stl_file *stl, char *file)
|
stl_write_quad_object(stl_file *stl, char *file) {
|
||||||
{
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
@ -348,17 +348,19 @@ stl_write_quad_object(stl_file *stl, char *file)
|
|||||||
stl_vertex uncon_3_color;
|
stl_vertex uncon_3_color;
|
||||||
stl_vertex color;
|
stl_vertex color;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = fopen(file, "w");
|
||||||
if(fp == NULL)
|
if(fp == NULL) {
|
||||||
{
|
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
||||||
sprintf(error_msg, "stl_write_quad_object: Couldn't open %s for writing",
|
sprintf(error_msg, "stl_write_quad_object: Couldn't open %s for writing",
|
||||||
file);
|
file);
|
||||||
perror(error_msg);
|
perror(error_msg);
|
||||||
free(error_msg);
|
free(error_msg);
|
||||||
exit(1);
|
stl->error = 1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
connect_color.x = 0.0;
|
connect_color.x = 0.0;
|
||||||
@ -375,25 +377,17 @@ stl_write_quad_object(stl_file *stl, char *file)
|
|||||||
uncon_3_color.z = 0.0;
|
uncon_3_color.z = 0.0;
|
||||||
|
|
||||||
fprintf(fp, "CQUAD\n");
|
fprintf(fp, "CQUAD\n");
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
|
||||||
j = ((stl->neighbors_start[i].neighbor[0] == -1) +
|
j = ((stl->neighbors_start[i].neighbor[0] == -1) +
|
||||||
(stl->neighbors_start[i].neighbor[1] == -1) +
|
(stl->neighbors_start[i].neighbor[1] == -1) +
|
||||||
(stl->neighbors_start[i].neighbor[2] == -1));
|
(stl->neighbors_start[i].neighbor[2] == -1));
|
||||||
if(j == 0)
|
if(j == 0) {
|
||||||
{
|
|
||||||
color = connect_color;
|
color = connect_color;
|
||||||
}
|
} else if(j == 1) {
|
||||||
else if(j == 1)
|
|
||||||
{
|
|
||||||
color = uncon_1_color;
|
color = uncon_1_color;
|
||||||
}
|
} else if(j == 2) {
|
||||||
else if(j == 2)
|
|
||||||
{
|
|
||||||
color = uncon_2_color;
|
color = uncon_2_color;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
color = uncon_3_color;
|
color = uncon_3_color;
|
||||||
}
|
}
|
||||||
fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n",
|
fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n",
|
||||||
@ -417,24 +411,24 @@ stl_write_quad_object(stl_file *stl, char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_write_dxf(stl_file *stl, char *file, char *label)
|
stl_write_dxf(stl_file *stl, char *file, char *label) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
fp = fopen(file, "w");
|
fp = fopen(file, "w");
|
||||||
if(fp == NULL)
|
if(fp == NULL) {
|
||||||
{
|
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
||||||
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing",
|
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing",
|
||||||
file);
|
file);
|
||||||
perror(error_msg);
|
perror(error_msg);
|
||||||
free(error_msg);
|
free(error_msg);
|
||||||
exit(1);
|
stl->error = 1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "999\n%s\n", label);
|
fprintf(fp, "999\n%s\n", label);
|
||||||
@ -445,8 +439,7 @@ stl_write_dxf(stl_file *stl, char *file, char *label)
|
|||||||
|
|
||||||
fprintf(fp, "0\nSECTION\n2\nENTITIES\n");
|
fprintf(fp, "0\nSECTION\n2\nENTITIES\n");
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
|
||||||
fprintf(fp, "0\n3DFACE\n8\n0\n");
|
fprintf(fp, "0\n3DFACE\n8\n0\n");
|
||||||
fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n",
|
fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n",
|
||||||
stl->facet_start[i].vertex[0].x, stl->facet_start[i].vertex[0].y,
|
stl->facet_start[i].vertex[0].x, stl->facet_start[i].vertex[0].y,
|
||||||
@ -466,3 +459,21 @@ stl_write_dxf(stl_file *stl, char *file, char *label)
|
|||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
stl_clear_error(stl_file *stl) {
|
||||||
|
stl->error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
stl_exit_on_error(stl_file *stl) {
|
||||||
|
if (!stl->error) return;
|
||||||
|
stl->error = 0;
|
||||||
|
stl_close(stl);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
stl_get_error(stl_file *stl) {
|
||||||
|
return stl->error;
|
||||||
|
}
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
/* ADMesh -- process triangulated solid meshes
|
/* ADMesh -- process triangulated solid meshes
|
||||||
* Copyright (C) 1995, 1996 Anthony D. Martin
|
* Copyright (C) 1995, 1996 Anthony D. Martin <amartin@engr.csulb.edu>
|
||||||
|
* Copyright (C) 2013, 2014 several contributors, see AUTHORS
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2, or (at your option)
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* any later version.
|
* (at your option) any later version.
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* Questions, comments, suggestions, etc to
|
||||||
* along with this program; if not, write to the Free Software
|
* https://github.com/admesh/admesh/issues
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* Questions, comments, suggestions, etc to <amartin@engr.csulb.edu>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -32,19 +34,18 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_open(stl_file *stl, char *file)
|
stl_open(stl_file *stl, char *file) {
|
||||||
{
|
|
||||||
stl_initialize(stl);
|
stl_initialize(stl);
|
||||||
stl_count_facets(stl, file);
|
stl_count_facets(stl, file);
|
||||||
stl_allocate(stl);
|
stl_allocate(stl);
|
||||||
stl_read(stl, 0, 1);
|
stl_read(stl, 0, 1);
|
||||||
fclose(stl->fp);
|
if (!stl->error) fclose(stl->fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_initialize(stl_file *stl)
|
stl_initialize(stl_file *stl) {
|
||||||
{
|
stl->error = 0;
|
||||||
stl->stats.degenerate_facets = 0;
|
stl->stats.degenerate_facets = 0;
|
||||||
stl->stats.edges_fixed = 0;
|
stl->stats.edges_fixed = 0;
|
||||||
stl->stats.facets_added = 0;
|
stl->stats.facets_added = 0;
|
||||||
@ -63,28 +64,30 @@ stl_initialize(stl_file *stl)
|
|||||||
stl->v_shared = NULL;
|
stl->v_shared = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
stl_count_facets(stl_file *stl, char *file)
|
stl_count_facets(stl_file *stl, char *file) {
|
||||||
{
|
|
||||||
long file_size;
|
long file_size;
|
||||||
int header_num_facets;
|
int header_num_facets;
|
||||||
int num_facets;
|
int num_facets;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
size_t s;
|
||||||
unsigned char chtest[128];
|
unsigned char chtest[128];
|
||||||
int num_lines = 1;
|
int num_lines = 1;
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
stl->fp = fopen(file, "r");
|
stl->fp = fopen(file, "r");
|
||||||
if(stl->fp == NULL)
|
if(stl->fp == NULL) {
|
||||||
{
|
|
||||||
error_msg = (char*)
|
error_msg = (char*)
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
||||||
sprintf(error_msg, "stl_initialize: Couldn't open %s for reading",
|
sprintf(error_msg, "stl_initialize: Couldn't open %s for reading",
|
||||||
file);
|
file);
|
||||||
perror(error_msg);
|
perror(error_msg);
|
||||||
free(error_msg);
|
free(error_msg);
|
||||||
exit(1);
|
stl->error = 1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
/* Find size of file */
|
/* Find size of file */
|
||||||
fseek(stl->fp, 0, SEEK_END);
|
fseek(stl->fp, 0, SEEK_END);
|
||||||
@ -92,14 +95,16 @@ stl_count_facets(stl_file *stl, char *file)
|
|||||||
|
|
||||||
/* Check for binary or ASCII file */
|
/* Check for binary or ASCII file */
|
||||||
fseek(stl->fp, HEADER_SIZE, SEEK_SET);
|
fseek(stl->fp, HEADER_SIZE, SEEK_SET);
|
||||||
fread(chtest, sizeof(chtest), 1, stl->fp);
|
if (!fread(chtest, sizeof(chtest), 1, stl->fp)) {
|
||||||
|
perror("The input is an empty file");
|
||||||
|
stl->error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
stl->stats.type = ascii;
|
stl->stats.type = ascii;
|
||||||
for(i = 0; i < sizeof(chtest); i++)
|
for(s = 0; s < sizeof(chtest); s++) {
|
||||||
{
|
if(chtest[s] > 127) {
|
||||||
if(chtest[i] > 127)
|
|
||||||
{
|
|
||||||
stl->stats.type = binary;
|
stl->stats.type = binary;
|
||||||
// close and reopen with binary flag (needed on Windows)
|
/* close and reopen with binary flag (needed on Windows) */
|
||||||
fclose(stl->fp);
|
fclose(stl->fp);
|
||||||
stl->fp = fopen(file, "rb");
|
stl->fp = fopen(file, "rb");
|
||||||
break;
|
break;
|
||||||
@ -109,41 +114,35 @@ stl_count_facets(stl_file *stl, char *file)
|
|||||||
|
|
||||||
/* Get the header and the number of facets in the .STL file */
|
/* Get the header and the number of facets in the .STL file */
|
||||||
/* If the .STL file is binary, then do the following */
|
/* If the .STL file is binary, then do the following */
|
||||||
if(stl->stats.type == binary)
|
if(stl->stats.type == binary) {
|
||||||
{
|
|
||||||
/* Test if the STL file has the right size */
|
/* Test if the STL file has the right size */
|
||||||
if(((file_size - HEADER_SIZE) % SIZEOF_STL_FACET != 0)
|
if(((file_size - HEADER_SIZE) % SIZEOF_STL_FACET != 0)
|
||||||
|| (file_size < STL_MIN_FILE_SIZE))
|
|| (file_size < STL_MIN_FILE_SIZE)) {
|
||||||
{
|
|
||||||
fprintf(stderr, "The file %s has the wrong size.\n", file);
|
fprintf(stderr, "The file %s has the wrong size.\n", file);
|
||||||
exit(1);
|
stl->error = 1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
num_facets = (file_size - HEADER_SIZE) / SIZEOF_STL_FACET;
|
num_facets = (file_size - HEADER_SIZE) / SIZEOF_STL_FACET;
|
||||||
|
|
||||||
/* Read the header */
|
/* Read the header */
|
||||||
fread(stl->stats.header, LABEL_SIZE, 1, stl->fp);
|
if (fread(stl->stats.header, LABEL_SIZE, 1, stl->fp) > 79) {
|
||||||
stl->stats.header[80] = '\0';
|
stl->stats.header[80] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
/* Read the int following the header. This should contain # of facets */
|
/* Read the int following the header. This should contain # of facets */
|
||||||
fread(&header_num_facets, sizeof(int), 1, stl->fp);
|
if((!fread(&header_num_facets, sizeof(int), 1, stl->fp)) || (num_facets != header_num_facets)) {
|
||||||
if(num_facets != header_num_facets)
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Warning: File size doesn't match number of facets in the header\n");
|
"Warning: File size doesn't match number of facets in the header\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Otherwise, if the .STL file is ASCII, then do the following */
|
/* Otherwise, if the .STL file is ASCII, then do the following */
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
/* Find the number of facets */
|
/* Find the number of facets */
|
||||||
j = 0;
|
j = 0;
|
||||||
for(i = 0; i < file_size ; i++)
|
for(i = 0; i < file_size ; i++) {
|
||||||
{
|
|
||||||
j++;
|
j++;
|
||||||
if(getc(stl->fp) == '\n')
|
if(getc(stl->fp) == '\n') {
|
||||||
{
|
if(j > 4) { /* don't count short lines */
|
||||||
if(j > 4) /* don't count short lines */
|
|
||||||
{
|
|
||||||
num_lines++;
|
num_lines++;
|
||||||
}
|
}
|
||||||
j = 0;
|
j = 0;
|
||||||
@ -164,8 +163,9 @@ stl_count_facets(stl_file *stl, char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_allocate(stl_file *stl)
|
stl_allocate(stl_file *stl) {
|
||||||
{
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Allocate memory for the entire .STL file */
|
/* Allocate memory for the entire .STL file */
|
||||||
stl->facet_start = (stl_facet*)calloc(stl->stats.number_of_facets,
|
stl->facet_start = (stl_facet*)calloc(stl->stats.number_of_facets,
|
||||||
sizeof(stl_facet));
|
sizeof(stl_facet));
|
||||||
@ -179,20 +179,54 @@ stl_allocate(stl_file *stl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_open_merge(stl_file *stl, char *file)
|
stl_open_merge(stl_file *stl, char *file_to_merge) {
|
||||||
{
|
int num_facets_so_far;
|
||||||
int first_facet;
|
stl_type origStlType;
|
||||||
|
FILE *origFp;
|
||||||
|
stl_file stl_to_merge;
|
||||||
|
|
||||||
first_facet = stl->stats.number_of_facets;
|
if (stl->error) return;
|
||||||
stl_initialize(stl);
|
|
||||||
stl_count_facets(stl, file);
|
/* Record how many facets we have so far from the first file. We will start putting
|
||||||
|
facets in the next position. Since we're 0-indexed, it'l be the same position. */
|
||||||
|
num_facets_so_far = stl->stats.number_of_facets;
|
||||||
|
|
||||||
|
/* Record the file type we started with: */
|
||||||
|
origStlType=stl->stats.type;
|
||||||
|
/* Record the file pointer too: */
|
||||||
|
origFp=stl->fp;
|
||||||
|
|
||||||
|
/* Initialize the sturucture with zero stats, header info and sizes: */
|
||||||
|
stl_initialize(&stl_to_merge);
|
||||||
|
stl_count_facets(&stl_to_merge, file_to_merge);
|
||||||
|
|
||||||
|
/* Copy what we need to into stl so that we can read the file_to_merge directly into it
|
||||||
|
using stl_read: Save the rest of the valuable info: */
|
||||||
|
stl->stats.type=stl_to_merge.stats.type;
|
||||||
|
stl->fp=stl_to_merge.fp;
|
||||||
|
|
||||||
|
/* Add the number of facets we already have in stl with what we we found in stl_to_merge but
|
||||||
|
haven't read yet. */
|
||||||
|
stl->stats.number_of_facets=num_facets_so_far+stl_to_merge.stats.number_of_facets;
|
||||||
|
|
||||||
|
/* Allocate enough room for stl->stats.number_of_facets facets and neighbors: */
|
||||||
stl_reallocate(stl);
|
stl_reallocate(stl);
|
||||||
stl_read(stl, first_facet, 0);
|
|
||||||
|
/* Read the file to merge directly into stl, adding it to what we have already.
|
||||||
|
Start at num_facets_so_far, the index to the first unused facet. Also say
|
||||||
|
that this isn't our first time so we should augment stats like min and max
|
||||||
|
instead of erasing them. */
|
||||||
|
stl_read(stl, num_facets_so_far, 0);
|
||||||
|
|
||||||
|
/* Restore the stl information we overwrote (for stl_read) so that it still accurately
|
||||||
|
reflects the subject part: */
|
||||||
|
stl->stats.type=origStlType;
|
||||||
|
stl->fp=origFp;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
stl_reallocate(stl_file *stl)
|
stl_reallocate(stl_file *stl) {
|
||||||
{
|
if (stl->error) return;
|
||||||
/* Reallocate more memory for the .STL file(s) */
|
/* Reallocate more memory for the .STL file(s) */
|
||||||
stl->facet_start = (stl_facet*)realloc(stl->facet_start, stl->stats.number_of_facets *
|
stl->facet_start = (stl_facet*)realloc(stl->facet_start, stl->stats.number_of_facets *
|
||||||
sizeof(stl_facet));
|
sizeof(stl_facet));
|
||||||
@ -206,47 +240,51 @@ stl_reallocate(stl_file *stl)
|
|||||||
if(stl->facet_start == NULL) perror("stl_initialize");
|
if(stl->facet_start == NULL) perror("stl_initialize");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
stl_read(stl_file *stl, int first_facet, int first)
|
/* Reads the contents of the file pointed to by stl->fp into the stl structure,
|
||||||
{
|
starting at facet first_facet. The second argument says if it's our first
|
||||||
|
time running this for the stl and therefore we should reset our max and min stats. */
|
||||||
|
void
|
||||||
|
stl_read(stl_file *stl, int first_facet, int first) {
|
||||||
stl_facet facet;
|
stl_facet facet;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(stl->stats.type == binary)
|
if (stl->error) return;
|
||||||
{
|
|
||||||
|
if(stl->stats.type == binary) {
|
||||||
fseek(stl->fp, HEADER_SIZE, SEEK_SET);
|
fseek(stl->fp, HEADER_SIZE, SEEK_SET);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
rewind(stl->fp);
|
rewind(stl->fp);
|
||||||
/* Skip the first line of the file */
|
/* Skip the first line of the file */
|
||||||
while(getc(stl->fp) != '\n');
|
while(getc(stl->fp) != '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = first_facet; i < stl->stats.number_of_facets; i++)
|
for(i = first_facet; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
|
||||||
if(stl->stats.type == binary)
|
if(stl->stats.type == binary)
|
||||||
/* Read a single facet from a binary .STL file */
|
/* Read a single facet from a binary .STL file */
|
||||||
{
|
{
|
||||||
// we assume little-endian architecture!
|
/* we assume little-endian architecture! */
|
||||||
fread(&facet.normal, sizeof(stl_normal), 1, stl->fp);
|
if (fread(&facet.normal, sizeof(stl_normal), 1, stl->fp) \
|
||||||
fread(&facet.vertex, sizeof(stl_vertex), 3, stl->fp);
|
+ fread(&facet.vertex, sizeof(stl_vertex), 3, stl->fp) \
|
||||||
fread(&facet.extra, sizeof(char), 2, stl->fp);
|
+ fread(&facet.extra, sizeof(char), 2, stl->fp) != 6) {
|
||||||
|
perror("Cannot read facet");
|
||||||
|
stl->error = 1;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
} else
|
||||||
/* Read a single facet from an ASCII .STL file */
|
/* Read a single facet from an ASCII .STL file */
|
||||||
{
|
{
|
||||||
fscanf(stl->fp, "%*s %*s %f %f %f\n", &facet.normal.x,
|
if((fscanf(stl->fp, "%*s %*s %f %f %f\n", &facet.normal.x, &facet.normal.y, &facet.normal.z) + \
|
||||||
&facet.normal.y, &facet.normal.z);
|
fscanf(stl->fp, "%*s %*s") + \
|
||||||
fscanf(stl->fp, "%*s %*s");
|
fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[0].x, &facet.vertex[0].y, &facet.vertex[0].z) + \
|
||||||
fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[0].x,
|
fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[1].x, &facet.vertex[1].y, &facet.vertex[1].z) + \
|
||||||
&facet.vertex[0].y, &facet.vertex[0].z);
|
fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[2].x, &facet.vertex[2].y, &facet.vertex[2].z) + \
|
||||||
fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[1].x,
|
fscanf(stl->fp, "%*s") + \
|
||||||
&facet.vertex[1].y, &facet.vertex[1].z);
|
fscanf(stl->fp, "%*s")) != 12) {
|
||||||
fscanf(stl->fp, "%*s %f %f %f\n", &facet.vertex[2].x,
|
perror("Something is syntactically very wrong with this ASCII STL!");
|
||||||
&facet.vertex[2].y, &facet.vertex[2].z);
|
stl->error = 1;
|
||||||
fscanf(stl->fp, "%*s");
|
return;
|
||||||
fscanf(stl->fp, "%*s");
|
}
|
||||||
}
|
}
|
||||||
/* Write the facet into memory. */
|
/* Write the facet into memory. */
|
||||||
stl->facet_start[i] = facet;
|
stl->facet_start[i] = facet;
|
||||||
@ -265,12 +303,14 @@ stl_read(stl_file *stl, int first_facet, int first)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_facet_stats(stl_file *stl, stl_facet facet, int first)
|
stl_facet_stats(stl_file *stl, stl_facet facet, int first) {
|
||||||
{
|
|
||||||
float diff_x;
|
float diff_x;
|
||||||
float diff_y;
|
float diff_y;
|
||||||
float diff_z;
|
float diff_z;
|
||||||
float max_diff;
|
float max_diff;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
/* while we are going through all of the facets, let's find the */
|
/* while we are going through all of the facets, let's find the */
|
||||||
/* maximum and minimum values for x, y, and z */
|
/* maximum and minimum values for x, y, and z */
|
||||||
|
|
||||||
@ -317,8 +357,9 @@ stl_facet_stats(stl_file *stl, stl_facet facet, int first)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_close(stl_file *stl)
|
stl_close(stl_file *stl) {
|
||||||
{
|
if (stl->error) return;
|
||||||
|
|
||||||
if(stl->neighbors_start != NULL)
|
if(stl->neighbors_start != NULL)
|
||||||
free(stl->neighbors_start);
|
free(stl->neighbors_start);
|
||||||
if(stl->facet_start != NULL)
|
if(stl->facet_start != NULL)
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
/* ADMesh -- process triangulated solid meshes
|
/* ADMesh -- process triangulated solid meshes
|
||||||
* Copyright (C) 1995, 1996 Anthony D. Martin
|
* Copyright (C) 1995, 1996 Anthony D. Martin <amartin@engr.csulb.edu>
|
||||||
|
* Copyright (C) 2013, 2014 several contributors, see AUTHORS
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2, or (at your option)
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* any later version.
|
* (at your option) any later version.
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* Questions, comments, suggestions, etc to
|
||||||
* along with this program; if not, write to the Free Software
|
* https://github.com/admesh/admesh/issues
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* Questions, comments, suggestions, etc to <amartin@engr.csulb.edu>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -31,8 +33,7 @@ static float get_volume(stl_file *stl);
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_verify_neighbors(stl_file *stl)
|
stl_verify_neighbors(stl_file *stl) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
stl_edge edge_a;
|
stl_edge edge_a;
|
||||||
@ -40,12 +41,12 @@ stl_verify_neighbors(stl_file *stl)
|
|||||||
int neighbor;
|
int neighbor;
|
||||||
int vnot;
|
int vnot;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
stl->stats.backwards_edges = 0;
|
stl->stats.backwards_edges = 0;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
for(j = 0; j < 3; j++) {
|
||||||
for(j = 0; j < 3; j++)
|
|
||||||
{
|
|
||||||
edge_a.p1 = stl->facet_start[i].vertex[j];
|
edge_a.p1 = stl->facet_start[i].vertex[j];
|
||||||
edge_a.p2 = stl->facet_start[i].vertex[(j + 1) % 3];
|
edge_a.p2 = stl->facet_start[i].vertex[(j + 1) % 3];
|
||||||
neighbor = stl->neighbors_start[i].neighbor[j];
|
neighbor = stl->neighbors_start[i].neighbor[j];
|
||||||
@ -53,19 +54,15 @@ stl_verify_neighbors(stl_file *stl)
|
|||||||
|
|
||||||
if(neighbor == -1)
|
if(neighbor == -1)
|
||||||
continue; /* this edge has no neighbor... Continue. */
|
continue; /* this edge has no neighbor... Continue. */
|
||||||
if(vnot < 3)
|
if(vnot < 3) {
|
||||||
{
|
|
||||||
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
|
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
|
||||||
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
|
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
stl->stats.backwards_edges += 1;
|
stl->stats.backwards_edges += 1;
|
||||||
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
|
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
|
||||||
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
|
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
|
||||||
}
|
}
|
||||||
if(memcmp(&edge_a, &edge_b, SIZEOF_EDGE_SORT) != 0)
|
if(memcmp(&edge_a, &edge_b, SIZEOF_EDGE_SORT) != 0) {
|
||||||
{
|
|
||||||
/* These edges should match but they don't. Print results. */
|
/* These edges should match but they don't. Print results. */
|
||||||
printf("edge %d of facet %d doesn't match edge %d of facet %d\n",
|
printf("edge %d of facet %d doesn't match edge %d of facet %d\n",
|
||||||
j, i, vnot + 1, neighbor);
|
j, i, vnot + 1, neighbor);
|
||||||
@ -77,15 +74,39 @@ stl_verify_neighbors(stl_file *stl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_translate_relative(stl_file *stl, float x, float y, float z)
|
stl_translate(stl_file *stl, float x, float y, float z) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
if (stl->error) return;
|
||||||
{
|
|
||||||
for(j = 0; j < 3; j++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
for(j = 0; j < 3; j++) {
|
||||||
|
stl->facet_start[i].vertex[j].x -= (stl->stats.min.x - x);
|
||||||
|
stl->facet_start[i].vertex[j].y -= (stl->stats.min.y - y);
|
||||||
|
stl->facet_start[i].vertex[j].z -= (stl->stats.min.z - z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stl->stats.max.x -= (stl->stats.min.x - x);
|
||||||
|
stl->stats.max.y -= (stl->stats.min.y - y);
|
||||||
|
stl->stats.max.z -= (stl->stats.min.z - z);
|
||||||
|
stl->stats.min.x = x;
|
||||||
|
stl->stats.min.y = y;
|
||||||
|
stl->stats.min.z = z;
|
||||||
|
|
||||||
|
stl_invalidate_shared_vertices(stl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Translates the stl by x,y,z, relatively from wherever it is currently */
|
||||||
|
void
|
||||||
|
stl_translate_relative(stl_file *stl, float x, float y, float z) {
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
|
for(j = 0; j < 3; j++) {
|
||||||
stl->facet_start[i].vertex[j].x += x;
|
stl->facet_start[i].vertex[j].x += x;
|
||||||
stl->facet_start[i].vertex[j].y += y;
|
stl->facet_start[i].vertex[j].y += y;
|
||||||
stl->facet_start[i].vertex[j].z += z;
|
stl->facet_start[i].vertex[j].z += z;
|
||||||
@ -102,12 +123,13 @@ stl_translate_relative(stl_file *stl, float x, float y, float z)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_scale_versor(stl_file *stl, float versor[3])
|
stl_scale_versor(stl_file *stl, float versor[3]) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
// scale extents
|
if (stl->error) return;
|
||||||
|
|
||||||
|
/* scale extents */
|
||||||
stl->stats.min.x *= versor[0];
|
stl->stats.min.x *= versor[0];
|
||||||
stl->stats.min.y *= versor[1];
|
stl->stats.min.y *= versor[1];
|
||||||
stl->stats.min.z *= versor[2];
|
stl->stats.min.z *= versor[2];
|
||||||
@ -115,20 +137,18 @@ stl_scale_versor(stl_file *stl, float versor[3])
|
|||||||
stl->stats.max.y *= versor[1];
|
stl->stats.max.y *= versor[1];
|
||||||
stl->stats.max.z *= versor[2];
|
stl->stats.max.z *= versor[2];
|
||||||
|
|
||||||
// scale size
|
/* scale size */
|
||||||
stl->stats.size.x *= versor[0];
|
stl->stats.size.x *= versor[0];
|
||||||
stl->stats.size.y *= versor[1];
|
stl->stats.size.y *= versor[1];
|
||||||
stl->stats.size.z *= versor[2];
|
stl->stats.size.z *= versor[2];
|
||||||
|
|
||||||
// scale volume
|
/* scale volume */
|
||||||
if (stl->stats.volume > 0.0) {
|
if (stl->stats.volume > 0.0) {
|
||||||
stl->stats.volume *= (versor[0] * versor[1] * versor[2]);
|
stl->stats.volume *= (versor[0] * versor[1] * versor[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
for(j = 0; j < 3; j++) {
|
||||||
for(j = 0; j < 3; j++)
|
|
||||||
{
|
|
||||||
stl->facet_start[i].vertex[j].x *= versor[0];
|
stl->facet_start[i].vertex[j].x *= versor[0];
|
||||||
stl->facet_start[i].vertex[j].y *= versor[1];
|
stl->facet_start[i].vertex[j].y *= versor[1];
|
||||||
stl->facet_start[i].vertex[j].z *= versor[2];
|
stl->facet_start[i].vertex[j].z *= versor[2];
|
||||||
@ -139,21 +159,24 @@ stl_scale_versor(stl_file *stl, float versor[3])
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_scale(stl_file *stl, float factor)
|
stl_scale(stl_file *stl, float factor) {
|
||||||
{
|
|
||||||
float versor[3];
|
float versor[3];
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
versor[0] = factor;
|
versor[0] = factor;
|
||||||
versor[1] = factor;
|
versor[1] = factor;
|
||||||
versor[2] = factor;
|
versor[2] = factor;
|
||||||
stl_scale_versor(stl, versor);
|
stl_scale_versor(stl, versor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calculate_normals(stl_file *stl)
|
static void calculate_normals(stl_file *stl) {
|
||||||
{
|
|
||||||
long i;
|
long i;
|
||||||
float normal[3];
|
float normal[3];
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++){
|
if (stl->error) return;
|
||||||
|
|
||||||
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
stl_calculate_normal(normal, &stl->facet_start[i]);
|
stl_calculate_normal(normal, &stl->facet_start[i]);
|
||||||
stl_normalize_vector(normal);
|
stl_normalize_vector(normal);
|
||||||
stl->facet_start[i].normal.x = normal[0];
|
stl->facet_start[i].normal.x = normal[0];
|
||||||
@ -163,15 +186,14 @@ static void calculate_normals(stl_file *stl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_rotate_x(stl_file *stl, float angle)
|
stl_rotate_x(stl_file *stl, float angle) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
if (stl->error) return;
|
||||||
{
|
|
||||||
for(j = 0; j < 3; j++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
for(j = 0; j < 3; j++) {
|
||||||
stl_rotate(&stl->facet_start[i].vertex[j].y,
|
stl_rotate(&stl->facet_start[i].vertex[j].y,
|
||||||
&stl->facet_start[i].vertex[j].z, angle);
|
&stl->facet_start[i].vertex[j].z, angle);
|
||||||
}
|
}
|
||||||
@ -181,15 +203,14 @@ stl_rotate_x(stl_file *stl, float angle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_rotate_y(stl_file *stl, float angle)
|
stl_rotate_y(stl_file *stl, float angle) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
if (stl->error) return;
|
||||||
{
|
|
||||||
for(j = 0; j < 3; j++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
for(j = 0; j < 3; j++) {
|
||||||
stl_rotate(&stl->facet_start[i].vertex[j].z,
|
stl_rotate(&stl->facet_start[i].vertex[j].z,
|
||||||
&stl->facet_start[i].vertex[j].x, angle);
|
&stl->facet_start[i].vertex[j].x, angle);
|
||||||
}
|
}
|
||||||
@ -199,15 +220,14 @@ stl_rotate_y(stl_file *stl, float angle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_rotate_z(stl_file *stl, float angle)
|
stl_rotate_z(stl_file *stl, float angle) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
if (stl->error) return;
|
||||||
{
|
|
||||||
for(j = 0; j < 3; j++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
for(j = 0; j < 3; j++) {
|
||||||
stl_rotate(&stl->facet_start[i].vertex[j].x,
|
stl_rotate(&stl->facet_start[i].vertex[j].x,
|
||||||
&stl->facet_start[i].vertex[j].y, angle);
|
&stl->facet_start[i].vertex[j].y, angle);
|
||||||
}
|
}
|
||||||
@ -219,28 +239,27 @@ stl_rotate_z(stl_file *stl, float angle)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stl_rotate(float *x, float *y, float angle)
|
stl_rotate(float *x, float *y, float angle) {
|
||||||
{
|
|
||||||
double r;
|
double r;
|
||||||
double theta;
|
double theta;
|
||||||
double radian_angle;
|
double radian_angle;
|
||||||
|
|
||||||
radian_angle = (angle / 180.0) * M_PI;
|
radian_angle = (angle / 180.0) * M_PI;
|
||||||
|
|
||||||
r = sqrt((*x * *x) + (*y * *y));
|
r = sqrt((*x **x) + (*y **y));
|
||||||
theta = atan2(*y, *x);
|
theta = atan2(*y, *x);
|
||||||
*x = r * cos(theta + radian_angle);
|
*x = r * cos(theta + radian_angle);
|
||||||
*y = r * sin(theta + radian_angle);
|
*y = r * sin(theta + radian_angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
stl_get_size(stl_file *stl)
|
stl_get_size(stl_file *stl) {
|
||||||
{
|
|
||||||
if (stl->stats.number_of_facets == 0) return;
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
if (stl->stats.number_of_facets == 0) return;
|
||||||
|
|
||||||
stl->stats.min.x = stl->facet_start[0].vertex[0].x;
|
stl->stats.min.x = stl->facet_start[0].vertex[0].x;
|
||||||
stl->stats.min.y = stl->facet_start[0].vertex[0].y;
|
stl->stats.min.y = stl->facet_start[0].vertex[0].y;
|
||||||
stl->stats.min.z = stl->facet_start[0].vertex[0].z;
|
stl->stats.min.z = stl->facet_start[0].vertex[0].z;
|
||||||
@ -248,10 +267,8 @@ stl_get_size(stl_file *stl)
|
|||||||
stl->stats.max.y = stl->facet_start[0].vertex[0].y;
|
stl->stats.max.y = stl->facet_start[0].vertex[0].y;
|
||||||
stl->stats.max.z = stl->facet_start[0].vertex[0].z;
|
stl->stats.max.z = stl->facet_start[0].vertex[0].z;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
for(j = 0; j < 3; j++) {
|
||||||
for(j = 0; j < 3; j++)
|
|
||||||
{
|
|
||||||
stl->stats.min.x = STL_MIN(stl->stats.min.x,
|
stl->stats.min.x = STL_MIN(stl->stats.min.x,
|
||||||
stl->facet_start[i].vertex[j].x);
|
stl->facet_start[i].vertex[j].x);
|
||||||
stl->stats.min.y = STL_MIN(stl->stats.min.y,
|
stl->stats.min.y = STL_MIN(stl->stats.min.y,
|
||||||
@ -277,16 +294,15 @@ stl_get_size(stl_file *stl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_mirror_xy(stl_file *stl)
|
stl_mirror_xy(stl_file *stl) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
float temp_size;
|
float temp_size;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
if (stl->error) return;
|
||||||
{
|
|
||||||
for(j = 0; j < 3; j++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
for(j = 0; j < 3; j++) {
|
||||||
stl->facet_start[i].vertex[j].z *= -1.0;
|
stl->facet_start[i].vertex[j].z *= -1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -296,21 +312,19 @@ stl_mirror_xy(stl_file *stl)
|
|||||||
stl->stats.min.z *= -1.0;
|
stl->stats.min.z *= -1.0;
|
||||||
stl->stats.max.z *= -1.0;
|
stl->stats.max.z *= -1.0;
|
||||||
stl_reverse_all_facets(stl);
|
stl_reverse_all_facets(stl);
|
||||||
stl->stats.facets_reversed -= stl->stats.number_of_facets; // for not altering stats
|
stl->stats.facets_reversed -= stl->stats.number_of_facets; /* for not altering stats */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_mirror_yz(stl_file *stl)
|
stl_mirror_yz(stl_file *stl) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
float temp_size;
|
float temp_size;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
if (stl->error) return;
|
||||||
{
|
|
||||||
for(j = 0; j < 3; j++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
for(j = 0; j < 3; j++) {
|
||||||
stl->facet_start[i].vertex[j].x *= -1.0;
|
stl->facet_start[i].vertex[j].x *= -1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,20 +334,19 @@ stl_mirror_yz(stl_file *stl)
|
|||||||
stl->stats.min.x *= -1.0;
|
stl->stats.min.x *= -1.0;
|
||||||
stl->stats.max.x *= -1.0;
|
stl->stats.max.x *= -1.0;
|
||||||
stl_reverse_all_facets(stl);
|
stl_reverse_all_facets(stl);
|
||||||
stl->stats.facets_reversed -= stl->stats.number_of_facets; // for not altering stats
|
stl->stats.facets_reversed -= stl->stats.number_of_facets; /* for not altering stats */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stl_mirror_xz(stl_file *stl)
|
stl_mirror_xz(stl_file *stl) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
float temp_size;
|
float temp_size;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++)
|
if (stl->error) return;
|
||||||
{
|
|
||||||
for(j = 0; j < 3; j++)
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
{
|
for(j = 0; j < 3; j++) {
|
||||||
stl->facet_start[i].vertex[j].y *= -1.0;
|
stl->facet_start[i].vertex[j].y *= -1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -343,11 +356,10 @@ stl_mirror_xz(stl_file *stl)
|
|||||||
stl->stats.min.y *= -1.0;
|
stl->stats.min.y *= -1.0;
|
||||||
stl->stats.max.y *= -1.0;
|
stl->stats.max.y *= -1.0;
|
||||||
stl_reverse_all_facets(stl);
|
stl_reverse_all_facets(stl);
|
||||||
stl->stats.facets_reversed -= stl->stats.number_of_facets; // for not altering stats
|
stl->stats.facets_reversed -= stl->stats.number_of_facets; /* for not altering stats */
|
||||||
}
|
}
|
||||||
|
|
||||||
static float get_volume(stl_file *stl)
|
static float get_volume(stl_file *stl) {
|
||||||
{
|
|
||||||
long i;
|
long i;
|
||||||
stl_vertex p0;
|
stl_vertex p0;
|
||||||
stl_vertex p;
|
stl_vertex p;
|
||||||
@ -356,12 +368,14 @@ static float get_volume(stl_file *stl)
|
|||||||
float area;
|
float area;
|
||||||
float volume = 0.0;
|
float volume = 0.0;
|
||||||
|
|
||||||
|
if (stl->error) return 0;
|
||||||
|
|
||||||
/* Choose a point, any point as the reference */
|
/* Choose a point, any point as the reference */
|
||||||
p0.x = stl->facet_start[0].vertex[0].x;
|
p0.x = stl->facet_start[0].vertex[0].x;
|
||||||
p0.y = stl->facet_start[0].vertex[0].y;
|
p0.y = stl->facet_start[0].vertex[0].y;
|
||||||
p0.z = stl->facet_start[0].vertex[0].z;
|
p0.z = stl->facet_start[0].vertex[0].z;
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++){
|
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
p.x = stl->facet_start[i].vertex[0].x - p0.x;
|
p.x = stl->facet_start[i].vertex[0].x - p0.x;
|
||||||
p.y = stl->facet_start[i].vertex[0].y - p0.y;
|
p.y = stl->facet_start[i].vertex[0].y - p0.y;
|
||||||
p.z = stl->facet_start[i].vertex[0].z - p0.z;
|
p.z = stl->facet_start[i].vertex[0].z - p0.z;
|
||||||
@ -374,27 +388,26 @@ static float get_volume(stl_file *stl)
|
|||||||
return volume;
|
return volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_calculate_volume(stl_file *stl)
|
void stl_calculate_volume(stl_file *stl) {
|
||||||
{
|
if (stl->error) return;
|
||||||
stl->stats.volume = get_volume(stl);
|
stl->stats.volume = get_volume(stl);
|
||||||
if(stl->stats.volume < 0.0){
|
if(stl->stats.volume < 0.0) {
|
||||||
stl_reverse_all_facets(stl);
|
stl_reverse_all_facets(stl);
|
||||||
stl->stats.volume = -stl->stats.volume;
|
stl->stats.volume = -stl->stats.volume;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static float get_area(stl_facet *facet)
|
static float get_area(stl_facet *facet) {
|
||||||
{
|
|
||||||
double cross[3][3];
|
double cross[3][3];
|
||||||
float sum[3];
|
float sum[3];
|
||||||
float n[3];
|
float n[3];
|
||||||
float area;
|
float area;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// cast to double before calculating cross product because large coordinates
|
/* cast to double before calculating cross product because large coordinates
|
||||||
// can result in overflowing product
|
can result in overflowing product
|
||||||
// (bad area is responsible for bad volume and bad facets reversal)
|
(bad area is responsible for bad volume and bad facets reversal) */
|
||||||
for(i = 0; i < 3; i++){
|
for(i = 0; i < 3; i++) {
|
||||||
cross[i][0]=(((double)facet->vertex[i].y * (double)facet->vertex[(i + 1) % 3].z) -
|
cross[i][0]=(((double)facet->vertex[i].y * (double)facet->vertex[(i + 1) % 3].z) -
|
||||||
((double)facet->vertex[i].z * (double)facet->vertex[(i + 1) % 3].y));
|
((double)facet->vertex[i].z * (double)facet->vertex[(i + 1) % 3].y));
|
||||||
cross[i][1]=(((double)facet->vertex[i].z * (double)facet->vertex[(i + 1) % 3].x) -
|
cross[i][1]=(((double)facet->vertex[i].z * (double)facet->vertex[(i + 1) % 3].x) -
|
||||||
@ -414,3 +427,126 @@ static float get_area(stl_facet *facet)
|
|||||||
area = 0.5 * (n[0] * sum[0] + n[1] * sum[1] + n[2] * sum[2]);
|
area = 0.5 * (n[0] * sum[0] + n[1] * sum[1] + n[2] * sum[2]);
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stl_repair(stl_file *stl,
|
||||||
|
int fixall_flag,
|
||||||
|
int exact_flag,
|
||||||
|
int tolerance_flag,
|
||||||
|
float tolerance,
|
||||||
|
int increment_flag,
|
||||||
|
float increment,
|
||||||
|
int nearby_flag,
|
||||||
|
int iterations,
|
||||||
|
int remove_unconnected_flag,
|
||||||
|
int fill_holes_flag,
|
||||||
|
int normal_directions_flag,
|
||||||
|
int normal_values_flag,
|
||||||
|
int reverse_all_flag,
|
||||||
|
int verbose_flag) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int last_edges_fixed = 0;
|
||||||
|
|
||||||
|
if (stl->error) return;
|
||||||
|
|
||||||
|
if(exact_flag || fixall_flag || nearby_flag || remove_unconnected_flag
|
||||||
|
|| fill_holes_flag || normal_directions_flag) {
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("Checking exact...\n");
|
||||||
|
exact_flag = 1;
|
||||||
|
stl_check_facets_exact(stl);
|
||||||
|
stl->stats.facets_w_1_bad_edge =
|
||||||
|
(stl->stats.connected_facets_2_edge -
|
||||||
|
stl->stats.connected_facets_3_edge);
|
||||||
|
stl->stats.facets_w_2_bad_edge =
|
||||||
|
(stl->stats.connected_facets_1_edge -
|
||||||
|
stl->stats.connected_facets_2_edge);
|
||||||
|
stl->stats.facets_w_3_bad_edge =
|
||||||
|
(stl->stats.number_of_facets -
|
||||||
|
stl->stats.connected_facets_1_edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nearby_flag || fixall_flag) {
|
||||||
|
if(!tolerance_flag) {
|
||||||
|
tolerance = stl->stats.shortest_edge;
|
||||||
|
}
|
||||||
|
if(!increment_flag) {
|
||||||
|
increment = stl->stats.bounding_diameter / 10000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||||
|
for(i = 0; i < iterations; i++) {
|
||||||
|
if(stl->stats.connected_facets_3_edge <
|
||||||
|
stl->stats.number_of_facets) {
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("\
|
||||||
|
Checking nearby. Tolerance= %f Iteration=%d of %d...",
|
||||||
|
tolerance, i + 1, iterations);
|
||||||
|
stl_check_facets_nearby(stl, tolerance);
|
||||||
|
if (verbose_flag)
|
||||||
|
printf(" Fixed %d edges.\n",
|
||||||
|
stl->stats.edges_fixed - last_edges_fixed);
|
||||||
|
last_edges_fixed = stl->stats.edges_fixed;
|
||||||
|
tolerance += increment;
|
||||||
|
} else {
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("\
|
||||||
|
All facets connected. No further nearby check necessary.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("All facets connected. No nearby check necessary.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(remove_unconnected_flag || fixall_flag || fill_holes_flag) {
|
||||||
|
if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("Removing unconnected facets...\n");
|
||||||
|
stl_remove_unconnected_facets(stl);
|
||||||
|
} else
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("No unconnected need to be removed.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fill_holes_flag || fixall_flag) {
|
||||||
|
if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("Filling holes...\n");
|
||||||
|
stl_fill_holes(stl);
|
||||||
|
} else
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("No holes need to be filled.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(reverse_all_flag) {
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("Reversing all facets...\n");
|
||||||
|
stl_reverse_all_facets(stl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(normal_directions_flag || fixall_flag) {
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("Checking normal directions...\n");
|
||||||
|
stl_fix_normal_directions(stl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(normal_values_flag || fixall_flag) {
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("Checking normal values...\n");
|
||||||
|
stl_fix_normal_values(stl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Always calculate the volume. It shouldn't take too long */
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("Calculating volume...\n");
|
||||||
|
stl_calculate_volume(stl);
|
||||||
|
|
||||||
|
if(exact_flag) {
|
||||||
|
if (verbose_flag)
|
||||||
|
printf("Verifying neighbors...\n");
|
||||||
|
stl_verify_neighbors(stl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -29,6 +29,7 @@ TriangleMesh::TriangleMesh(const TriangleMesh &other)
|
|||||||
{
|
{
|
||||||
this->stl.heads = NULL;
|
this->stl.heads = NULL;
|
||||||
this->stl.tail = NULL;
|
this->stl.tail = NULL;
|
||||||
|
this->stl.error = other.stl.error;
|
||||||
if (other.stl.facet_start != NULL) {
|
if (other.stl.facet_start != NULL) {
|
||||||
this->stl.facet_start = (stl_facet*)calloc(other.stl.stats.number_of_facets, sizeof(stl_facet));
|
this->stl.facet_start = (stl_facet*)calloc(other.stl.stats.number_of_facets, sizeof(stl_facet));
|
||||||
std::copy(other.stl.facet_start, other.stl.facet_start + other.stl.stats.number_of_facets, this->stl.facet_start);
|
std::copy(other.stl.facet_start, other.stl.facet_start + other.stl.stats.number_of_facets, this->stl.facet_start);
|
||||||
@ -125,6 +126,7 @@ TriangleMesh::repair() {
|
|||||||
// fill_holes
|
// fill_holes
|
||||||
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
|
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
|
||||||
stl_fill_holes(&stl);
|
stl_fill_holes(&stl);
|
||||||
|
stl_clear_error(&stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// normal_directions
|
// normal_directions
|
||||||
@ -280,6 +282,7 @@ TriangleMesh::split() const
|
|||||||
mesh->stl.stats.type = inmemory;
|
mesh->stl.stats.type = inmemory;
|
||||||
mesh->stl.stats.number_of_facets = facets.size();
|
mesh->stl.stats.number_of_facets = facets.size();
|
||||||
mesh->stl.stats.original_num_facets = mesh->stl.stats.number_of_facets;
|
mesh->stl.stats.original_num_facets = mesh->stl.stats.number_of_facets;
|
||||||
|
stl_clear_error(&mesh->stl);
|
||||||
stl_allocate(&mesh->stl);
|
stl_allocate(&mesh->stl);
|
||||||
|
|
||||||
int first = 1;
|
int first = 1;
|
||||||
@ -389,6 +392,7 @@ TriangleMesh::to_SV() {
|
|||||||
|
|
||||||
void TriangleMesh::ReadFromPerl(SV* vertices, SV* facets)
|
void TriangleMesh::ReadFromPerl(SV* vertices, SV* facets)
|
||||||
{
|
{
|
||||||
|
stl.error = 0;
|
||||||
stl.stats.type = inmemory;
|
stl.stats.type = inmemory;
|
||||||
|
|
||||||
// count facets and allocate memory
|
// count facets and allocate memory
|
||||||
|
Loading…
Reference in New Issue
Block a user