use convhull_3d for quicker hull calculation
This commit is contained in:
parent
1191f54ef4
commit
736f89026f
|
|
@ -1,16 +1,16 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2017-2018 Leo McCormack
|
Copyright (c) 2017-2018 Leo McCormack
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONVHULL_3D_USE_FLOAT_PRECISION
|
#ifdef CONVHULL_3D_USE_FLOAT_PRECISION
|
||||||
typedef float CH_FLOAT;
|
typedef float CH_FLOAT;
|
||||||
#else
|
#else
|
||||||
|
|
@ -72,7 +72,7 @@ typedef struct _ch_vertex {
|
||||||
};
|
};
|
||||||
} ch_vertex;
|
} ch_vertex;
|
||||||
typedef ch_vertex ch_vec3;
|
typedef ch_vertex ch_vec3;
|
||||||
|
|
||||||
/* builds the convexhull, returning the face indices corresponding to "in_vertices" */
|
/* builds the convexhull, returning the face indices corresponding to "in_vertices" */
|
||||||
void convhull_3d_build(/* input arguments */
|
void convhull_3d_build(/* input arguments */
|
||||||
ch_vertex* const in_vertices, /* vector of input vertices; nVert x 1 */
|
ch_vertex* const in_vertices, /* vector of input vertices; nVert x 1 */
|
||||||
|
|
@ -80,30 +80,6 @@ void convhull_3d_build(/* input arguments */
|
||||||
/* output arguments */
|
/* output arguments */
|
||||||
int** out_faces, /* & of empty int*, output face indices; flat: nOut_faces x 3 */
|
int** out_faces, /* & of empty int*, output face indices; flat: nOut_faces x 3 */
|
||||||
int* nOut_faces); /* & of int, number of output face indices */
|
int* nOut_faces); /* & of int, number of output face indices */
|
||||||
|
|
||||||
/* exports the vertices, face indices, and face normals, as an 'obj' file, ready for GPU */
|
|
||||||
void convhull_3d_export_obj(/* input arguments */
|
|
||||||
ch_vertex* const vertices, /* vector of input vertices; nVert x 1 */
|
|
||||||
const int nVert, /* number of vertices */
|
|
||||||
int* const faces, /* face indices; flat: nFaces x 3 */
|
|
||||||
const int nFaces, /* number of faces in hull */
|
|
||||||
const int keepOnlyUsedVerticesFLAG, /* 0: exports in_vertices, 1: exports only used vertices */
|
|
||||||
char* const obj_filename); /* obj filename, WITHOUT extension */
|
|
||||||
|
|
||||||
/* exports the vertices, face indices, and face normals, as an 'm' file, for MatLab verification */
|
|
||||||
void convhull_3d_export_m(/* input arguments */
|
|
||||||
ch_vertex* const vertices, /* vector of input vertices; nVert x 1 */
|
|
||||||
const int nVert, /* number of vertices */
|
|
||||||
int* const faces, /* face indices; flat: nFaces x 3 */
|
|
||||||
const int nFaces, /* number of faces in hull */
|
|
||||||
char* const m_filename); /* m filename, WITHOUT extension */
|
|
||||||
|
|
||||||
/* reads an 'obj' file and extracts only the vertices */
|
|
||||||
void extractVerticesFromObjFile(/* input arguments */
|
|
||||||
char* const obj_filename, /* obj filename, WITHOUT extension */
|
|
||||||
/* output arguments */
|
|
||||||
ch_vertex** out_vertices, /* & of empty ch_vertex*, output vertices; out_nVert x 1 */
|
|
||||||
int* out_nVert); /* & of int, number of vertices */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /*extern "C"*/
|
} /*extern "C"*/
|
||||||
|
|
@ -116,22 +92,11 @@ void extractVerticesFromObjFile(/* input arguments */
|
||||||
* INTERNAL:
|
* INTERNAL:
|
||||||
***********/
|
***********/
|
||||||
|
|
||||||
#ifdef CONVHULL_3D_ENABLE
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
|
||||||
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
|
||||||
#define CV_STRNCPY(a,b,c) strncpy_s(a,c+1,b,c);
|
|
||||||
#define CV_STRCAT(a,b) strcat_s(a,sizeof(b),b);
|
|
||||||
#else
|
|
||||||
#define CV_STRNCPY(a,b,c) strncpy(a,b,c);
|
|
||||||
#define CV_STRCAT(a,b) strcat(a,b);
|
|
||||||
#endif
|
|
||||||
#ifdef CONVHULL_3D_USE_FLOAT_PRECISION
|
#ifdef CONVHULL_3D_USE_FLOAT_PRECISION
|
||||||
#define CH_FLT_MIN FLT_MIN
|
#define CH_FLT_MIN FLT_MIN
|
||||||
#define CH_FLT_MAX FLT_MAX
|
#define CH_FLT_MAX FLT_MAX
|
||||||
|
|
@ -167,39 +132,38 @@ static int cmp_asc_int(const void*, const void*);
|
||||||
static int cmp_desc_int(const void*, const void*);
|
static int cmp_desc_int(const void*, const void*);
|
||||||
static void sort_float(CH_FLOAT*, CH_FLOAT*, int*, int, int);
|
static void sort_float(CH_FLOAT*, CH_FLOAT*, int*, int, int);
|
||||||
static void sort_int(int*, int*, int*, int, int);
|
static void sort_int(int*, int*, int*, int, int);
|
||||||
static ch_vec3 cross(ch_vec3*, ch_vec3*);
|
|
||||||
static CH_FLOAT det_4x4(CH_FLOAT*);
|
static CH_FLOAT det_4x4(CH_FLOAT*);
|
||||||
static void plane_3d(CH_FLOAT*, CH_FLOAT*, CH_FLOAT*);
|
static void plane_3d(CH_FLOAT*, CH_FLOAT*, CH_FLOAT*);
|
||||||
static void ismember(int*, int*, int*, int, int);
|
static void ismember(int*, int*, int*, int, int);
|
||||||
|
|
||||||
/* internal functions definitions: */
|
/* internal functions definitions: */
|
||||||
static int cmp_asc_float(const void *a,const void *b) {
|
static int cmp_asc_float(const void *a,const void *b) {
|
||||||
struct float_w_idx *a1 = (struct float_w_idx*)a;
|
const struct float_w_idx *a1 = (const struct float_w_idx*)a;
|
||||||
struct float_w_idx *a2 = (struct float_w_idx*)b;
|
const struct float_w_idx *a2 = (const struct float_w_idx*)b;
|
||||||
if((*a1).val<(*a2).val)return -1;
|
if((*a1).val<(*a2).val)return -1;
|
||||||
else if((*a1).val>(*a2).val)return 1;
|
else if((*a1).val>(*a2).val)return 1;
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmp_desc_float(const void *a,const void *b) {
|
static int cmp_desc_float(const void *a,const void *b) {
|
||||||
struct float_w_idx *a1 = (struct float_w_idx*)a;
|
const struct float_w_idx *a1 = (const struct float_w_idx*)a;
|
||||||
struct float_w_idx *a2 = (struct float_w_idx*)b;
|
const struct float_w_idx *a2 = (const struct float_w_idx*)b;
|
||||||
if((*a1).val>(*a2).val)return -1;
|
if((*a1).val>(*a2).val)return -1;
|
||||||
else if((*a1).val<(*a2).val)return 1;
|
else if((*a1).val<(*a2).val)return 1;
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmp_asc_int(const void *a,const void *b) {
|
static int cmp_asc_int(const void *a,const void *b) {
|
||||||
struct int_w_idx *a1 = (struct int_w_idx*)a;
|
const struct int_w_idx *a1 = (const struct int_w_idx*)a;
|
||||||
struct int_w_idx *a2 = (struct int_w_idx*)b;
|
const struct int_w_idx *a2 = (const struct int_w_idx*)b;
|
||||||
if((*a1).val<(*a2).val)return -1;
|
if((*a1).val<(*a2).val)return -1;
|
||||||
else if((*a1).val>(*a2).val)return 1;
|
else if((*a1).val>(*a2).val)return 1;
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmp_desc_int(const void *a,const void *b) {
|
static int cmp_desc_int(const void *a,const void *b) {
|
||||||
struct int_w_idx *a1 = (struct int_w_idx*)a;
|
const struct int_w_idx *a1 = (const struct int_w_idx*)a;
|
||||||
struct int_w_idx *a2 = (struct int_w_idx*)b;
|
const struct int_w_idx *a2 = (const struct int_w_idx*)b;
|
||||||
if((*a1).val>(*a2).val)return -1;
|
if((*a1).val>(*a2).val)return -1;
|
||||||
else if((*a1).val<(*a2).val)return 1;
|
else if((*a1).val<(*a2).val)return 1;
|
||||||
else return 0;
|
else return 0;
|
||||||
|
|
@ -216,7 +180,7 @@ static void sort_float
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct float_w_idx *data;
|
struct float_w_idx *data;
|
||||||
|
|
||||||
data = (float_w_idx*)malloc(len*sizeof(float_w_idx));
|
data = (float_w_idx*)malloc(len*sizeof(float_w_idx));
|
||||||
for(i=0;i<len;i++) {
|
for(i=0;i<len;i++) {
|
||||||
data[i].val=in_vec[i];
|
data[i].val=in_vec[i];
|
||||||
|
|
@ -248,7 +212,7 @@ static void sort_int
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct int_w_idx *data;
|
struct int_w_idx *data;
|
||||||
|
|
||||||
data = (int_w_idx*)malloc(len*sizeof(int_w_idx));
|
data = (int_w_idx*)malloc(len*sizeof(int_w_idx));
|
||||||
for(i=0;i<len;i++) {
|
for(i=0;i<len;i++) {
|
||||||
data[i].val=in_vec[i];
|
data[i].val=in_vec[i];
|
||||||
|
|
@ -269,15 +233,6 @@ static void sort_int
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ch_vec3 cross(ch_vec3* v1, ch_vec3* v2)
|
|
||||||
{
|
|
||||||
ch_vec3 cross;
|
|
||||||
cross.x = v1->y * v2->z - v1->z * v2->y;
|
|
||||||
cross.y = v1->z * v2->x - v1->x * v2->z;
|
|
||||||
cross.z = v1->x * v2->y - v1->y * v2->x;
|
|
||||||
return cross;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calculates the determinent of a 4x4 matrix */
|
/* calculates the determinent of a 4x4 matrix */
|
||||||
static CH_FLOAT det_4x4(CH_FLOAT* m) {
|
static CH_FLOAT det_4x4(CH_FLOAT* m) {
|
||||||
return
|
return
|
||||||
|
|
@ -310,7 +265,7 @@ static void plane_3d
|
||||||
int r[3];
|
int r[3];
|
||||||
CH_FLOAT sign, det, norm_c;
|
CH_FLOAT sign, det, norm_c;
|
||||||
CH_FLOAT pdiff[2][3], pdiff_s[2][2];
|
CH_FLOAT pdiff[2][3], pdiff_s[2][2];
|
||||||
|
|
||||||
for(i=0; i<2; i++)
|
for(i=0; i<2; i++)
|
||||||
for(j=0; j<3; j++)
|
for(j=0; j<3; j++)
|
||||||
pdiff[i][j] = p[(i+1)*3+j] - p[i*3+j];
|
pdiff[i][j] = p[(i+1)*3+j] - p[i*3+j];
|
||||||
|
|
@ -380,13 +335,13 @@ void convhull_3d_build
|
||||||
int* aVec, *faces;
|
int* aVec, *faces;
|
||||||
CH_FLOAT dfi, v, max_p, min_p;
|
CH_FLOAT dfi, v, max_p, min_p;
|
||||||
CH_FLOAT* points, *cf, *cfi, *df, *p_s, *span;
|
CH_FLOAT* points, *cf, *cfi, *df, *p_s, *span;
|
||||||
|
|
||||||
if(nVert<3 || in_vertices==NULL){
|
if(nVert<3 || in_vertices==NULL){
|
||||||
(*out_faces) = NULL;
|
(*out_faces) = NULL;
|
||||||
(*nOut_faces) = 0;
|
(*nOut_faces) = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3 dimensions. The code should theoretically work for >=2 dimensions, but "plane_3d" and "det_4x4" are hardcoded for 3,
|
/* 3 dimensions. The code should theoretically work for >=2 dimensions, but "plane_3d" and "det_4x4" are hardcoded for 3,
|
||||||
* so would need to be rewritten */
|
* so would need to be rewritten */
|
||||||
d = 3;
|
d = 3;
|
||||||
|
|
@ -405,14 +360,14 @@ void convhull_3d_build
|
||||||
points[i*(d+1)+j] = in_vertices[i].v[j] + CH_NOISE_VAL*rand()/(float)RAND_MAX; /* noise mitigates duplicates */
|
points[i*(d+1)+j] = in_vertices[i].v[j] + CH_NOISE_VAL*rand()/(float)RAND_MAX; /* noise mitigates duplicates */
|
||||||
points[i*(d+1)+d] = 1.0f; /* add a last column of ones. Used only for determinant calculation */
|
points[i*(d+1)+d] = 1.0f; /* add a last column of ones. Used only for determinant calculation */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The initial convex hull is a simplex with (d+1) facets, where d is the number of dimensions */
|
/* The initial convex hull is a simplex with (d+1) facets, where d is the number of dimensions */
|
||||||
nFaces = (d+1);
|
nFaces = (d+1);
|
||||||
faces = (int*)calloc(nFaces*d, sizeof(int));
|
faces = (int*)calloc(nFaces*d, sizeof(int));
|
||||||
aVec = (int*)malloc(nFaces*sizeof(int));
|
aVec = (int*)malloc(nFaces*sizeof(int));
|
||||||
for(i=0; i<nFaces; i++)
|
for(i=0; i<nFaces; i++)
|
||||||
aVec[i] = i;
|
aVec[i] = i;
|
||||||
|
|
||||||
/* Each column of cf contains the coefficients of a plane */
|
/* Each column of cf contains the coefficients of a plane */
|
||||||
cf = (CH_FLOAT*)malloc(nFaces*d*sizeof(CH_FLOAT));
|
cf = (CH_FLOAT*)malloc(nFaces*d*sizeof(CH_FLOAT));
|
||||||
cfi = (CH_FLOAT*)malloc(d*sizeof(CH_FLOAT));
|
cfi = (CH_FLOAT*)malloc(d*sizeof(CH_FLOAT));
|
||||||
|
|
@ -426,12 +381,12 @@ void convhull_3d_build
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate and store the plane coefficients of the face */
|
/* Calculate and store the plane coefficients of the face */
|
||||||
for(j=0; j<d; j++)
|
for(j=0; j<d; j++)
|
||||||
for(k=0; k<d; k++)
|
for(k=0; k<d; k++)
|
||||||
p_s[j*d+k] = points[(faces[i*d+j])*(d+1) + k];
|
p_s[j*d+k] = points[(faces[i*d+j])*(d+1) + k];
|
||||||
|
|
||||||
/* Calculate and store the plane coefficients of the face */
|
/* Calculate and store the plane coefficients of the face */
|
||||||
plane_3d(p_s, cfi, &dfi);
|
plane_3d(p_s, cfi, &dfi);
|
||||||
for(j=0; j<d; j++)
|
for(j=0; j<d; j++)
|
||||||
|
|
@ -440,12 +395,12 @@ void convhull_3d_build
|
||||||
}
|
}
|
||||||
CH_FLOAT *A;
|
CH_FLOAT *A;
|
||||||
int *bVec, *fVec, *asfVec, *face_tmp;
|
int *bVec, *fVec, *asfVec, *face_tmp;
|
||||||
|
|
||||||
/* Check to make sure that faces are correctly oriented */
|
/* Check to make sure that faces are correctly oriented */
|
||||||
bVec = (int*)malloc(4*sizeof(int));
|
bVec = (int*)malloc(4*sizeof(int));
|
||||||
for(i=0; i<d+1; i++)
|
for(i=0; i<d+1; i++)
|
||||||
bVec[i] = i;
|
bVec[i] = i;
|
||||||
|
|
||||||
/* A contains the coordinates of the points forming a simplex */
|
/* A contains the coordinates of the points forming a simplex */
|
||||||
A = (CH_FLOAT*)calloc((d+1)*(d+1), sizeof(CH_FLOAT));
|
A = (CH_FLOAT*)calloc((d+1)*(d+1), sizeof(CH_FLOAT));
|
||||||
face_tmp = (int*)malloc((d+1)*sizeof(int));
|
face_tmp = (int*)malloc((d+1)*sizeof(int));
|
||||||
|
|
@ -463,10 +418,10 @@ void convhull_3d_build
|
||||||
for(; i<(d+1); i++)
|
for(; i<(d+1); i++)
|
||||||
for(j=0; j<(d+1); j++)
|
for(j=0; j<(d+1); j++)
|
||||||
A[i*(d+1)+j] = points[p*(d+1)+j];
|
A[i*(d+1)+j] = points[p*(d+1)+j];
|
||||||
|
|
||||||
/* det(A) determines the orientation of the face */
|
/* det(A) determines the orientation of the face */
|
||||||
v = det_4x4(A);
|
v = det_4x4(A);
|
||||||
|
|
||||||
/* Orient so that each point on the original simplex can't see the opposite face */
|
/* Orient so that each point on the original simplex can't see the opposite face */
|
||||||
if(v<0){
|
if(v<0){
|
||||||
/* Reverse the order of the last two vertices to change the volume */
|
/* Reverse the order of the last two vertices to change the volume */
|
||||||
|
|
@ -474,7 +429,7 @@ void convhull_3d_build
|
||||||
face_tmp[j] = faces[k*d+j];
|
face_tmp[j] = faces[k*d+j];
|
||||||
for(j=0, l=d-2; j<d-1; j++, l++)
|
for(j=0, l=d-2; j<d-1; j++, l++)
|
||||||
faces[k*d+l] = face_tmp[d-j-1];
|
faces[k*d+l] = face_tmp[d-j-1];
|
||||||
|
|
||||||
/* Modify the plane coefficients of the properly oriented faces */
|
/* Modify the plane coefficients of the properly oriented faces */
|
||||||
for(j=0; j<d; j++)
|
for(j=0; j<d; j++)
|
||||||
cf[k*d+j] = -cf[k*d+j];
|
cf[k*d+j] = -cf[k*d+j];
|
||||||
|
|
@ -487,7 +442,7 @@ void convhull_3d_build
|
||||||
A[i*(d+1)+j] = points[p*(d+1)+j];
|
A[i*(d+1)+j] = points[p*(d+1)+j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Coordinates of the center of the point set */
|
/* Coordinates of the center of the point set */
|
||||||
CH_FLOAT* meanp, *absdist, *reldist, *desReldist;
|
CH_FLOAT* meanp, *absdist, *reldist, *desReldist;
|
||||||
meanp = (CH_FLOAT*)calloc(d, sizeof(CH_FLOAT));
|
meanp = (CH_FLOAT*)calloc(d, sizeof(CH_FLOAT));
|
||||||
|
|
@ -496,41 +451,41 @@ void convhull_3d_build
|
||||||
meanp[j] += points[i*(d+1)+j];
|
meanp[j] += points[i*(d+1)+j];
|
||||||
for(j=0; j<d; j++)
|
for(j=0; j<d; j++)
|
||||||
meanp[j] = meanp[j]/(CH_FLOAT)(nVert-d-1);
|
meanp[j] = meanp[j]/(CH_FLOAT)(nVert-d-1);
|
||||||
|
|
||||||
/* Absolute distance of points from the center */
|
/* Absolute distance of points from the center */
|
||||||
absdist = (CH_FLOAT*)malloc((nVert-d-1)*d * sizeof(CH_FLOAT));
|
absdist = (CH_FLOAT*)malloc((nVert-d-1)*d * sizeof(CH_FLOAT));
|
||||||
for(i=d+1, k=0; i<nVert; i++, k++)
|
for(i=d+1, k=0; i<nVert; i++, k++)
|
||||||
for(j=0; j<d; j++)
|
for(j=0; j<d; j++)
|
||||||
absdist[k*d+j] = (points[i*(d+1)+j] - meanp[j])/span[j];
|
absdist[k*d+j] = (points[i*(d+1)+j] - meanp[j])/span[j];
|
||||||
|
|
||||||
/* Relative distance of points from the center */
|
/* Relative distance of points from the center */
|
||||||
reldist = (CH_FLOAT*)calloc((nVert-d-1), sizeof(CH_FLOAT));
|
reldist = (CH_FLOAT*)calloc((nVert-d-1), sizeof(CH_FLOAT));
|
||||||
desReldist = (CH_FLOAT*)malloc((nVert-d-1) * sizeof(CH_FLOAT));
|
desReldist = (CH_FLOAT*)malloc((nVert-d-1) * sizeof(CH_FLOAT));
|
||||||
for(i=0; i<(nVert-d-1); i++)
|
for(i=0; i<(nVert-d-1); i++)
|
||||||
for(j=0; j<d; j++)
|
for(j=0; j<d; j++)
|
||||||
reldist[i] += pow(absdist[i*d+j], 2.0);
|
reldist[i] += pow(absdist[i*d+j], 2.0);
|
||||||
|
|
||||||
/* Sort from maximum to minimum relative distance */
|
/* Sort from maximum to minimum relative distance */
|
||||||
int num_pleft, cnt;
|
int num_pleft, cnt;
|
||||||
int* ind, *pleft;
|
int* ind, *pleft;
|
||||||
ind = (int*)malloc((nVert-d-1) * sizeof(int));
|
ind = (int*)malloc((nVert-d-1) * sizeof(int));
|
||||||
pleft = (int*)malloc((nVert-d-1) * sizeof(int));
|
pleft = (int*)malloc((nVert-d-1) * sizeof(int));
|
||||||
sort_float(reldist, desReldist, ind, (nVert-d-1), 1);
|
sort_float(reldist, desReldist, ind, (nVert-d-1), 1);
|
||||||
|
|
||||||
/* Initialize the vector of points left. The points with the larger relative
|
/* Initialize the vector of points left. The points with the larger relative
|
||||||
distance from the center are scanned first. */
|
distance from the center are scanned first. */
|
||||||
num_pleft = (nVert-d-1);
|
num_pleft = (nVert-d-1);
|
||||||
for(i=0; i<num_pleft; i++)
|
for(i=0; i<num_pleft; i++)
|
||||||
pleft[i] = ind[i]+d+1;
|
pleft[i] = ind[i]+d+1;
|
||||||
|
|
||||||
/* Loop over all remaining points that are not deleted. Deletion of points
|
/* Loop over all remaining points that are not deleted. Deletion of points
|
||||||
occurs every #iter2del# iterations of this while loop */
|
occurs every #iter2del# iterations of this while loop */
|
||||||
memset(A, 0, (d+1)*(d+1) * sizeof(CH_FLOAT));
|
memset(A, 0, (d+1)*(d+1) * sizeof(CH_FLOAT));
|
||||||
|
|
||||||
/* cnt is equal to the points having been selected without deletion of
|
/* cnt is equal to the points having been selected without deletion of
|
||||||
nonvisible points (i.e. points inside the current convex hull) */
|
nonvisible points (i.e. points inside the current convex hull) */
|
||||||
cnt=0;
|
cnt=0;
|
||||||
|
|
||||||
/* The main loop for the quickhull algorithm */
|
/* The main loop for the quickhull algorithm */
|
||||||
CH_FLOAT detA;
|
CH_FLOAT detA;
|
||||||
CH_FLOAT* points_cf, *points_s;
|
CH_FLOAT* points_cf, *points_s;
|
||||||
|
|
@ -549,7 +504,7 @@ void convhull_3d_build
|
||||||
while( (num_pleft>0) ){
|
while( (num_pleft>0) ){
|
||||||
/* i is the first point of the points left */
|
/* i is the first point of the points left */
|
||||||
i = pleft[0];
|
i = pleft[0];
|
||||||
|
|
||||||
/* Delete the point selected */
|
/* Delete the point selected */
|
||||||
for(j=0; j<num_pleft-1; j++)
|
for(j=0; j<num_pleft-1; j++)
|
||||||
pleft[j] = pleft[j+1];
|
pleft[j] = pleft[j+1];
|
||||||
|
|
@ -558,10 +513,10 @@ void convhull_3d_build
|
||||||
free(pleft);
|
free(pleft);
|
||||||
else
|
else
|
||||||
pleft = (int*)realloc(pleft, num_pleft*sizeof(int));
|
pleft = (int*)realloc(pleft, num_pleft*sizeof(int));
|
||||||
|
|
||||||
/* Update point selection counter */
|
/* Update point selection counter */
|
||||||
cnt++;
|
cnt++;
|
||||||
|
|
||||||
/* find visible faces */
|
/* find visible faces */
|
||||||
for(j=0; j<d; j++)
|
for(j=0; j<d; j++)
|
||||||
points_s[j] = points[i*(d+1)+j];
|
points_s[j] = points[i*(d+1)+j];
|
||||||
|
|
@ -596,7 +551,7 @@ void convhull_3d_build
|
||||||
visible_ind[j] = 0;
|
visible_ind[j] = 0;
|
||||||
}
|
}
|
||||||
num_nonvisible_faces = nFaces - num_visible_ind;
|
num_nonvisible_faces = nFaces - num_visible_ind;
|
||||||
|
|
||||||
/* proceed if there are any visible faces */
|
/* proceed if there are any visible faces */
|
||||||
if(num_visible_ind!=0){
|
if(num_visible_ind!=0){
|
||||||
/* Find visible face indices */
|
/* Find visible face indices */
|
||||||
|
|
@ -607,7 +562,7 @@ void convhull_3d_build
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find nonvisible faces */
|
/* Find nonvisible faces */
|
||||||
nonvisible_faces = (int*)malloc(num_nonvisible_faces*d*sizeof(int));
|
nonvisible_faces = (int*)malloc(num_nonvisible_faces*d*sizeof(int));
|
||||||
f0 = (int*)malloc(num_nonvisible_faces*d*sizeof(int));
|
f0 = (int*)malloc(num_nonvisible_faces*d*sizeof(int));
|
||||||
|
|
@ -618,7 +573,7 @@ void convhull_3d_build
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create horizon (count is the number of the edges of the horizon) */
|
/* Create horizon (count is the number of the edges of the horizon) */
|
||||||
count=0;
|
count=0;
|
||||||
for(j=0; j<num_visible_ind; j++){
|
for(j=0; j<num_visible_ind; j++){
|
||||||
|
|
@ -629,7 +584,7 @@ void convhull_3d_build
|
||||||
sort_int(face_s, NULL, NULL, d, 0);
|
sort_int(face_s, NULL, NULL, d, 0);
|
||||||
ismember(nonvisible_faces, face_s, f0, num_nonvisible_faces*d, d);
|
ismember(nonvisible_faces, face_s, f0, num_nonvisible_faces*d, d);
|
||||||
u_len = 0;
|
u_len = 0;
|
||||||
|
|
||||||
/* u are the nonvisible faces connected to the face v, if any */
|
/* u are the nonvisible faces connected to the face v, if any */
|
||||||
for(k=0; k<num_nonvisible_faces; k++){
|
for(k=0; k<num_nonvisible_faces; k++){
|
||||||
f0_sum = 0;
|
f0_sum = 0;
|
||||||
|
|
@ -669,7 +624,7 @@ void convhull_3d_build
|
||||||
/* Delete visible faces */
|
/* Delete visible faces */
|
||||||
for(k=0; k<d; k++)
|
for(k=0; k<d; k++)
|
||||||
faces[l*d+k] = faces[j*d+k];
|
faces[l*d+k] = faces[j*d+k];
|
||||||
|
|
||||||
/* Delete the corresponding plane coefficients of the faces */
|
/* Delete the corresponding plane coefficients of the faces */
|
||||||
for(k=0; k<d; k++)
|
for(k=0; k<d; k++)
|
||||||
cf[l*d+k] = cf[j*d+k];
|
cf[l*d+k] = cf[j*d+k];
|
||||||
|
|
@ -677,16 +632,16 @@ void convhull_3d_build
|
||||||
l++;
|
l++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the number of faces */
|
/* Update the number of faces */
|
||||||
nFaces = nFaces-num_visible_ind;
|
nFaces = nFaces-num_visible_ind;
|
||||||
faces = (int*)realloc(faces, nFaces*d*sizeof(int));
|
faces = (int*)realloc(faces, nFaces*d*sizeof(int));
|
||||||
cf = (CH_FLOAT*)realloc(cf, nFaces*d*sizeof(CH_FLOAT));
|
cf = (CH_FLOAT*)realloc(cf, nFaces*d*sizeof(CH_FLOAT));
|
||||||
df = (CH_FLOAT*)realloc(df, nFaces*sizeof(CH_FLOAT));
|
df = (CH_FLOAT*)realloc(df, nFaces*sizeof(CH_FLOAT));
|
||||||
|
|
||||||
/* start is the first row of the new faces */
|
/* start is the first row of the new faces */
|
||||||
start=nFaces;
|
start=nFaces;
|
||||||
|
|
||||||
/* Add faces connecting horizon to the new point */
|
/* Add faces connecting horizon to the new point */
|
||||||
n_newfaces = horizon_size1;
|
n_newfaces = horizon_size1;
|
||||||
for(j=0; j<n_newfaces; j++){
|
for(j=0; j<n_newfaces; j++){
|
||||||
|
|
@ -697,7 +652,7 @@ void convhull_3d_build
|
||||||
for(k=0; k<d-1; k++)
|
for(k=0; k<d-1; k++)
|
||||||
faces[(nFaces-1)*d+k] = horizon[j*(d-1)+k];
|
faces[(nFaces-1)*d+k] = horizon[j*(d-1)+k];
|
||||||
faces[(nFaces-1)*d+(d-1)] = i;
|
faces[(nFaces-1)*d+(d-1)] = i;
|
||||||
|
|
||||||
/* Calculate and store appropriately the plane coefficients of the faces */
|
/* Calculate and store appropriately the plane coefficients of the faces */
|
||||||
for(k=0; k<d; k++)
|
for(k=0; k<d; k++)
|
||||||
for(l=0; l<d; l++)
|
for(l=0; l<d; l++)
|
||||||
|
|
@ -712,7 +667,7 @@ void convhull_3d_build
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Orient each new face properly */
|
/* Orient each new face properly */
|
||||||
hVec = (int*)malloc( nFaces*sizeof(int));
|
hVec = (int*)malloc( nFaces*sizeof(int));
|
||||||
hVec_mem_face = (int*)malloc( nFaces*sizeof(int));
|
hVec_mem_face = (int*)malloc( nFaces*sizeof(int));
|
||||||
|
|
@ -736,7 +691,7 @@ void convhull_3d_build
|
||||||
}
|
}
|
||||||
index = 0;
|
index = 0;
|
||||||
detA = 0.0;
|
detA = 0.0;
|
||||||
|
|
||||||
/* While new point is coplanar, choose another point */
|
/* While new point is coplanar, choose another point */
|
||||||
while(detA==0.0){
|
while(detA==0.0){
|
||||||
for(j=0;j<d; j++)
|
for(j=0;j<d; j++)
|
||||||
|
|
@ -748,7 +703,7 @@ void convhull_3d_build
|
||||||
index++;
|
index++;
|
||||||
detA = det_4x4(A);
|
detA = det_4x4(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Orient faces so that each point on the original simplex can't see the opposite face */
|
/* Orient faces so that each point on the original simplex can't see the opposite face */
|
||||||
if (detA<0.0){
|
if (detA<0.0){
|
||||||
/* If orientation is improper, reverse the order to change the volume sign */
|
/* If orientation is improper, reverse the order to change the volume sign */
|
||||||
|
|
@ -756,7 +711,7 @@ void convhull_3d_build
|
||||||
face_tmp[j] = faces[k*d+j];
|
face_tmp[j] = faces[k*d+j];
|
||||||
for(j=0, l=d-2; j<d-1; j++, l++)
|
for(j=0, l=d-2; j<d-1; j++, l++)
|
||||||
faces[k*d+l] = face_tmp[d-j-1];
|
faces[k*d+l] = face_tmp[d-j-1];
|
||||||
|
|
||||||
/* Modify the plane coefficients of the properly oriented faces */
|
/* Modify the plane coefficients of the properly oriented faces */
|
||||||
for(j=0; j<d; j++)
|
for(j=0; j<d; j++)
|
||||||
cf[k*d+j] = -cf[k*d+j];
|
cf[k*d+j] = -cf[k*d+j];
|
||||||
|
|
@ -781,7 +736,7 @@ void convhull_3d_build
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* output */
|
/* output */
|
||||||
if(FUCKED){
|
if(FUCKED){
|
||||||
(*out_faces) = NULL;
|
(*out_faces) = NULL;
|
||||||
|
|
@ -792,7 +747,7 @@ void convhull_3d_build
|
||||||
memcpy((*out_faces),faces, nFaces*d*sizeof(int));
|
memcpy((*out_faces),faces, nFaces*d*sizeof(int));
|
||||||
(*nOut_faces) = nFaces;
|
(*nOut_faces) = nFaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean-up */
|
/* clean-up */
|
||||||
free(visible_ind);
|
free(visible_ind);
|
||||||
free(points_cf);
|
free(points_cf);
|
||||||
|
|
@ -819,178 +774,5 @@ void convhull_3d_build
|
||||||
free(A);
|
free(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
void convhull_3d_export_obj
|
|
||||||
(
|
|
||||||
ch_vertex* const vertices,
|
|
||||||
const int nVert,
|
|
||||||
int* const faces,
|
|
||||||
const int nFaces,
|
|
||||||
const int keepOnlyUsedVerticesFLAG,
|
|
||||||
char* const obj_filename
|
|
||||||
)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
char path[256] = "\0";
|
|
||||||
CV_STRNCPY(path, obj_filename, strlen(obj_filename));
|
|
||||||
FILE* obj_file;
|
|
||||||
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
|
||||||
CV_STRCAT(path, ".obj");
|
|
||||||
fopen_s(&obj_file, path, "wt");
|
|
||||||
#else
|
|
||||||
obj_file = fopen(strcat(path, ".obj"), "wt");
|
|
||||||
#endif
|
|
||||||
fprintf(obj_file, "o\n");
|
|
||||||
CH_FLOAT scale;
|
|
||||||
ch_vec3 v1, v2, normal;
|
|
||||||
|
|
||||||
/* export vertices */
|
|
||||||
if(keepOnlyUsedVerticesFLAG){
|
|
||||||
for (i = 0; i < nFaces; i++)
|
|
||||||
for(j=0; j<3; j++)
|
|
||||||
fprintf(obj_file, "v %f %f %f\n", vertices[faces[i*3+j]].x,
|
|
||||||
vertices[faces[i*3+j]].y, vertices[faces[i*3+j]].z);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (i = 0; i < nVert; i++)
|
|
||||||
fprintf(obj_file, "v %f %f %f\n", vertices[i].x,
|
|
||||||
vertices[i].y, vertices[i].z);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* export the face normals */
|
|
||||||
for (i = 0; i < nFaces; i++){
|
|
||||||
/* calculate cross product between v1-v0 and v2-v0 */
|
|
||||||
v1 = vertices[faces[i*3+1]];
|
|
||||||
v2 = vertices[faces[i*3+2]];
|
|
||||||
v1.x -= vertices[faces[i*3]].x;
|
|
||||||
v1.y -= vertices[faces[i*3]].y;
|
|
||||||
v1.z -= vertices[faces[i*3]].z;
|
|
||||||
v2.x -= vertices[faces[i*3]].x;
|
|
||||||
v2.y -= vertices[faces[i*3]].y;
|
|
||||||
v2.z -= vertices[faces[i*3]].z;
|
|
||||||
normal = cross(&v1, &v2);
|
|
||||||
|
|
||||||
/* normalise to unit length */
|
|
||||||
scale = 1.0/(sqrt(pow(normal.x, 2.0)+pow(normal.y, 2.0)+pow(normal.z, 2.0))+2.23e-9);
|
|
||||||
normal.x *= scale;
|
|
||||||
normal.y *= scale;
|
|
||||||
normal.z *= scale;
|
|
||||||
fprintf(obj_file, "vn %f %f %f\n", normal.x, normal.y, normal.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* export the face indices */
|
|
||||||
if(keepOnlyUsedVerticesFLAG){
|
|
||||||
for (i = 0; i < nFaces; i++){
|
|
||||||
/* vertices are in same order as the faces, and normals are in order */
|
|
||||||
fprintf(obj_file, "f %u//%u %u//%u %u//%u\n",
|
|
||||||
i*3 + 1, i + 1,
|
|
||||||
i*3+1 + 1, i + 1,
|
|
||||||
i*3+2 + 1, i + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* just normals are in order */
|
|
||||||
for (i = 0; i < nFaces; i++){
|
|
||||||
fprintf(obj_file, "f %u//%u %u//%u %u//%u\n",
|
|
||||||
faces[i*3] + 1, i + 1,
|
|
||||||
faces[i*3+1] + 1, i + 1,
|
|
||||||
faces[i*3+2] + 1, i + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(obj_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
void convhull_3d_export_m
|
|
||||||
(
|
|
||||||
ch_vertex* const vertices,
|
|
||||||
const int nVert,
|
|
||||||
int* const faces,
|
|
||||||
const int nFaces,
|
|
||||||
char* const m_filename
|
|
||||||
)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char path[256] = { "\0" };
|
|
||||||
memcpy(path, m_filename, strlen(m_filename));
|
|
||||||
FILE* m_file;
|
|
||||||
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
|
||||||
CV_STRCAT(path, ".m");
|
|
||||||
fopen_s(&m_file, path, "wt");
|
|
||||||
#else
|
|
||||||
m_file = fopen(strcat(path, ".m"), "wt");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* save face indices and vertices for verification in matlab: */
|
|
||||||
fprintf(m_file, "vertices = [\n");
|
|
||||||
for (i = 0; i < nVert; i++)
|
|
||||||
fprintf(m_file, "%f, %f, %f;\n", vertices[i].x, vertices[i].y, vertices[i].z);
|
|
||||||
fprintf(m_file, "];\n\n\n");
|
|
||||||
fprintf(m_file, "faces = [\n");
|
|
||||||
for (int i = 0; i < nFaces; i++) {
|
|
||||||
fprintf(m_file, " %u, %u, %u;\n",
|
|
||||||
faces[3*i+0]+1,
|
|
||||||
faces[3*i+1]+1,
|
|
||||||
faces[3*i+2]+1);
|
|
||||||
}
|
|
||||||
fprintf(m_file, "];\n\n\n");
|
|
||||||
fclose(m_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
void extractVerticesFromObjFile(char* const obj_filename, ch_vertex** out_vertices, int* out_nVert)
|
|
||||||
{
|
|
||||||
FILE* obj_file;
|
|
||||||
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
|
||||||
CV_STRCAT(obj_filename, ".obj");
|
|
||||||
fopen_s(&obj_file, obj_filename, "r");
|
|
||||||
#else
|
|
||||||
obj_file = fopen(strcat(obj_filename, ".obj"), "r");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* determine number of vertices */
|
|
||||||
unsigned int nVert = 0;
|
|
||||||
char line[256];
|
|
||||||
while (fgets(line, sizeof(line), obj_file)) {
|
|
||||||
char* vexists = strstr(line, "v ");
|
|
||||||
if(vexists!=NULL)
|
|
||||||
nVert++;
|
|
||||||
}
|
|
||||||
(*out_nVert) = nVert;
|
|
||||||
(*out_vertices) = (ch_vertex*)malloc(nVert*sizeof(ch_vertex));
|
|
||||||
|
|
||||||
/* extract the vertices */
|
|
||||||
rewind(obj_file);
|
|
||||||
int i=0;
|
|
||||||
int vertID, prev_char_isDigit, current_char_isDigit;
|
|
||||||
char vert_char[256] = { 0 };
|
|
||||||
while (fgets(line, sizeof(line), obj_file)) {
|
|
||||||
char* vexists = strstr(line, "v ");
|
|
||||||
if(vexists!=NULL){
|
|
||||||
prev_char_isDigit = 0;
|
|
||||||
vertID = -1;
|
|
||||||
for(int j=0; j<strlen(line)-1; j++){
|
|
||||||
if(isdigit(line[j])||line[j]=='.'||line[j]=='-'||line[j]=='+'||line[j]=='E'||line[j]=='e'){
|
|
||||||
vert_char[strlen(vert_char)] = line[j];
|
|
||||||
current_char_isDigit = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
current_char_isDigit = 0;
|
|
||||||
if((prev_char_isDigit && !current_char_isDigit) || j ==strlen(line)-2 ){
|
|
||||||
vertID++;
|
|
||||||
if(vertID>4){
|
|
||||||
/* not a valid file */
|
|
||||||
free((*out_vertices));
|
|
||||||
(*out_vertices) = NULL;
|
|
||||||
(*out_nVert) = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
(*out_vertices)[i].v[vertID] = atof(vert_char);
|
|
||||||
memset(vert_char, 0, 256 * sizeof(char));
|
|
||||||
}
|
|
||||||
prev_char_isDigit = current_char_isDigit;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* CONVHULL_3D_ENABLE */
|
|
||||||
|
|
|
||||||
|
|
@ -1012,6 +1012,9 @@ public:
|
||||||
std::size_t size() const {
|
std::size_t size() const {
|
||||||
return m_vertices.size();
|
return m_vertices.size();
|
||||||
}
|
}
|
||||||
|
const Vector3& operator[]( std::size_t i ) const {
|
||||||
|
return m_vertices[i];
|
||||||
|
}
|
||||||
brushsplit_t classify_plane( const Plane3& plane ) const {
|
brushsplit_t classify_plane( const Plane3& plane ) const {
|
||||||
brushsplit_t split;
|
brushsplit_t split;
|
||||||
for( const_iterator i = begin(); i != end(); ++i ){
|
for( const_iterator i = begin(); i != end(); ++i ){
|
||||||
|
|
@ -1084,6 +1087,53 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include "convhull_3d.h"
|
||||||
|
void CSG_build_hull( const MergeVertices& mergeVertices, MergePlanes& mergePlanes ){
|
||||||
|
#if 0
|
||||||
|
/* bruteforce new planes */
|
||||||
|
for( MergeVertices::const_iterator i = mergeVertices.begin() + 0; i != mergeVertices.end() - 2; ++i )
|
||||||
|
for( MergeVertices::const_iterator j = i + 1; j != mergeVertices.end() - 1; ++j )
|
||||||
|
for( MergeVertices::const_iterator k = j + 1; k != mergeVertices.end() - 0; ++k ){
|
||||||
|
const Plane3 plane = plane3_for_points( *i, *j, *k );
|
||||||
|
if( plane3_valid( plane ) ){
|
||||||
|
const brushsplit_t split = mergeVertices.classify_plane( plane );
|
||||||
|
if( ( split.counts[ePlaneFront] == 0 ) != ( split.counts[ePlaneBack] == 0 ) ){
|
||||||
|
if( split.counts[ePlaneFront] != 0 )
|
||||||
|
mergePlanes.insert( MergePlane( plane3_flipped( plane ), *i, *j, *k ) );
|
||||||
|
else
|
||||||
|
mergePlanes.insert( MergePlane( plane, *i, *k, *j ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
const int nVertices = mergeVertices.size();
|
||||||
|
ch_vertex* vertices = ( ch_vertex* )malloc( mergeVertices.size() * sizeof( ch_vertex ) );
|
||||||
|
for( std::size_t i = 0; i < mergeVertices.size(); ++i ){
|
||||||
|
vertices[i].x = static_cast<double>( mergeVertices[i].x() );
|
||||||
|
vertices[i].y = static_cast<double>( mergeVertices[i].y() );
|
||||||
|
vertices[i].z = static_cast<double>( mergeVertices[i].z() );
|
||||||
|
}
|
||||||
|
int* faceIndices = NULL;
|
||||||
|
int nFaces;
|
||||||
|
convhull_3d_build( vertices, nVertices, &faceIndices, &nFaces );
|
||||||
|
/* Where 'faceIndices' is a flat 2D matrix [nFaces x 3] */
|
||||||
|
for( int i = 0; i < nFaces; ++i ){
|
||||||
|
Vector3 p[3];
|
||||||
|
for( int j = 0; j < 3; ++j ){
|
||||||
|
// p[j] = Vector3( vertices[faceIndices[i * 3 + j]].x, vertices[faceIndices[i * 3 + j]].y, vertices[faceIndices[i * 3 + j]].z );
|
||||||
|
p[j] = mergeVertices[faceIndices[i * 3 + j]];
|
||||||
|
}
|
||||||
|
const Plane3 plane = plane3_for_points( p[0], p[1], p[2] );
|
||||||
|
if( plane3_valid( plane ) ){
|
||||||
|
mergePlanes.insert( MergePlane( plane, p[0], p[2], p[1] ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free( vertices );
|
||||||
|
free( faceIndices );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void CSG_WrapMerge( const ClipperPoints& clipperPoints ){
|
void CSG_WrapMerge( const ClipperPoints& clipperPoints ){
|
||||||
const bool primit = ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive );
|
const bool primit = ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive );
|
||||||
brush_vector_t selected_brushes;
|
brush_vector_t selected_brushes;
|
||||||
|
|
@ -1127,21 +1177,8 @@ void CSG_WrapMerge( const ClipperPoints& clipperPoints ){
|
||||||
mergePlanes.insert( MergePlane( face.getPlane().plane3(), &face ) );
|
mergePlanes.insert( MergePlane( face.getPlane().plane3(), &face ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* bruteforce new planes */
|
|
||||||
for( MergeVertices::const_iterator i = mergeVertices.begin() + 0; i != mergeVertices.end() - 2; ++i )
|
CSG_build_hull( mergeVertices, mergePlanes );
|
||||||
for( MergeVertices::const_iterator j = i + 1; j != mergeVertices.end() - 1; ++j )
|
|
||||||
for( MergeVertices::const_iterator k = j + 1; k != mergeVertices.end() - 0; ++k ){
|
|
||||||
const Plane3 plane = plane3_for_points( *i, *j, *k );
|
|
||||||
if( plane3_valid( plane ) ){
|
|
||||||
const brushsplit_t split = mergeVertices.classify_plane( plane );
|
|
||||||
if( ( split.counts[ePlaneFront] == 0 ) != ( split.counts[ePlaneBack] == 0 ) ){
|
|
||||||
if( split.counts[ePlaneFront] != 0 )
|
|
||||||
mergePlanes.insert( MergePlane( plane3_flipped( plane ), *i, *j, *k ) );
|
|
||||||
else
|
|
||||||
mergePlanes.insert( MergePlane( plane, *i, *k, *j ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//globalOutputStream() << mergePlanes.size() << " mergePlanes.size()\n";
|
//globalOutputStream() << mergePlanes.size() << " mergePlanes.size()\n";
|
||||||
if( mergePlanes.size() < 4 ){
|
if( mergePlanes.size() < 4 ){
|
||||||
|
|
@ -1242,21 +1279,8 @@ void CSG_DeleteComponents(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bruteforce new planes */
|
CSG_build_hull( mergeVertices, mergePlanes );
|
||||||
for( MergeVertices::const_iterator i = mergeVertices.begin() + 0; i != mergeVertices.end() - 2; ++i )
|
|
||||||
for( MergeVertices::const_iterator j = i + 1; j != mergeVertices.end() - 1; ++j )
|
|
||||||
for( MergeVertices::const_iterator k = j + 1; k != mergeVertices.end() - 0; ++k ){
|
|
||||||
const Plane3 plane = plane3_for_points( *i, *j, *k );
|
|
||||||
if( plane3_valid( plane ) ){
|
|
||||||
const brushsplit_t split = mergeVertices.classify_plane( plane );
|
|
||||||
if( ( split.counts[ePlaneFront] == 0 ) != ( split.counts[ePlaneBack] == 0 ) ){
|
|
||||||
if( split.counts[ePlaneFront] != 0 )
|
|
||||||
mergePlanes.insert( MergePlane( plane3_flipped( plane ), *i, *j, *k ) );
|
|
||||||
else
|
|
||||||
mergePlanes.insert( MergePlane( plane, *i, *k, *j ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( mergePlanes.size() < 4 ){
|
if( mergePlanes.size() < 4 ){
|
||||||
globalWarningStream() << "CSG_DeleteComponents: Too few planes left: " << mergePlanes.size() << ".\n";
|
globalWarningStream() << "CSG_DeleteComponents: Too few planes left: " << mergePlanes.size() << ".\n";
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user