29#include "DGtal/base/Common.h"
30#include "DGtal/helpers/StdDefs.h"
31#include "DGtal/io/readers/GenericReader.h"
32#include "DGtal/io/readers/PointListReader.h"
34#include "DGtal/images/ImageSelector.h"
78using Vertices = std::vector<std::array<double, 3>>;
79using Faces = std::vector<std::array<size_t, 3>>;
82void pushCube(
const T& center, Vertices& vertices, Faces& faces) {
83 constexpr static double size = 0.5;
84 constexpr static std::array<std::array<double, 3>, 8> coords {{
85 {-size, -size, -size},
86 { size, -size, -size},
94 constexpr static std::array<std::array<size_t, 3>, 12> indices {{
103 const double x = center[0];
104 const double y = center[1];
105 const double z = center[2];
107 const size_t startIndex = vertices.size() + 1;
108 for (
size_t i = 0; i < coords.size(); ++i) {
109 vertices.push_back({x + coords[i][0],
113 for (
size_t i = 0; i < indices.size(); ++i) {
114 faces.push_back({startIndex + indices[i][0],
115 startIndex + indices[i][1],
116 startIndex + indices[i][2]});
120int main(
int argc,
char** argv )
125 std::string inputFileName;
126 std::string outputFileName {
"result.obj"};
127 int thresholdMin {128};
128 int thresholdMax {255};
129 DGtal::int64_t rescaleInputMin {0};
130 DGtal::int64_t rescaleInputMax {255};
133 app.description(
" Converts any volumetric file (or .sdp file) to an OBJ one. Each grid point with value between [thresholdMin, thresholdMax] is exported as a unit cube.");
134 app.add_option(
"-i,--input,1", inputFileName,
"vol file (.vol, .longvol .p3d, .pgm3d or .sdp and if DGTAL_WITH_ITK is selected: dicom, dcm, mha, mhd). For longvol, dicom, dcm, mha or mhd formats, the input values are linearly scaled between 0 and 255." )
136 ->check(CLI::ExistingFile);
137 app.add_option(
"--output,-o,2",outputFileName ,
"output file (.obj or .off).");
138 app.add_option(
"--thresholdMin,-m", thresholdMin,
"threshold min (excluded) to define binary shape.");
139 app.add_option(
"--thresholdMax,-M", thresholdMax,
"threshold max (included) to define binary shape.");
140 app.add_option(
"--rescaleInputMin", rescaleInputMin,
"min value used to rescale the input intensity (to avoid basic cast into 8 bits image).");
141 app.add_option(
"--rescaleInputMax", rescaleInputMax,
"max value used to rescale the input intensity (to avoid basic cast into 8 bits image).");
144 app.get_formatter()->column_width(40);
145 CLI11_PARSE(app, argc, argv);
151 typedef ImageSelector<Domain, unsigned char>::Type Image;
152 string extension = inputFileName.substr(inputFileName.find_last_of(
".") + 1);
156 typedef DGtal::functors::Rescaling<DGtal::int64_t ,unsigned char > RescalFCT;
157 Image image = GenericReader< Image >::importWithValueFunctor( inputFileName,RescalFCT(rescaleInputMin,
160 trace.info() <<
"Image loaded: "<<image<< std::endl;
161 Domain domain = image.domain();
162 for(Domain::ConstIterator it = domain.begin(), itend=domain.end(); it!=itend; ++it){
163 unsigned char val= image( (*it) );
164 if(val<=thresholdMax && val >=thresholdMin){
165 pushCube(*it, vertices, faces);
172 vector<Z3i::Point> vectVoxels = PointListReader<Z3i::Point>::getPointsFromFile(inputFileName);
173 for(
unsigned int i=0;i< vectVoxels.size(); i++){
174 pushCube(vectVoxels.at(i), vertices, faces);
179 std::ofstream outFile(outputFileName);
181 trace.error() <<
"Can not open file: '" << outputFileName <<
"'\n";
185 outFile <<
"#This file was created by DGtalTools vol2obj object\n";
186 for (
size_t i = 0; i < vertices.size(); ++i) {
187 outFile <<
"v " << vertices[i][0] <<
' ' << vertices[i][1] <<
' ' << vertices[i][2] <<
'\n';
189 for (
size_t i = 0; i < faces.size(); ++i) {
190 outFile <<
"f " << faces[i][0] <<
' ' << faces[i][1] <<
' ' << faces[i][2] <<
'\n';