diff --git a/src/Mod/Mesh/App/Core/MeshIO.cpp b/src/Mod/Mesh/App/Core/MeshIO.cpp index a109fa82e..afb93a713 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.cpp +++ b/src/Mod/Mesh/App/Core/MeshIO.cpp @@ -42,8 +42,10 @@ #include #include #include +#include #include #include +#include using namespace MeshCore; @@ -493,6 +495,18 @@ bool MeshInput::LoadOFF (std::istream &rstrIn) return true; } +namespace MeshCore { + struct MeshPly_Property : public std::binary_function, + std::string, bool> + { + bool operator()(const std::pair& x, + const std::string& y) const + { + return x.first == y; + } + }; +} + bool MeshInput::LoadPLY (std::istream &inp) { // http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/ @@ -503,6 +517,11 @@ bool MeshInput::LoadPLY (std::istream &inp) enum { ascii, binary_little_endian, binary_big_endian } format; + + enum Number { + int8, uint8, int16, uint16, int32, uint32, float32, float64 + }; + if (!inp || inp.bad() == true) return false; @@ -519,10 +538,10 @@ bool MeshInput::LoadPLY (std::istream &inp) if ((ply[0] != 'p') || (ply[1] != 'l') || (ply[2] != 'y')) return false; // wrong header - std::vector face_props; + std::vector > vertex_props; + std::vector face_props; std::string line, element; - bool xyz_float=false,xyz_double=false; - int xyz_coords=0; + MeshIO::Binding rgb_value = MeshIO::OVERALL; while (std::getline(inp, line)) { std::istringstream str(line); @@ -593,37 +612,86 @@ bool MeshInput::LoadPLY (std::istream &inp) if (element == "vertex") { str >> space >> std::ws >> type >> space >> std::ws >> name >> std::ws; - if (name == "x") { - xyz_coords++; - if (type == "float" || type == "float32") - xyz_float = true; - else if (type == "double" || type == "float64") - xyz_double = true; + + Number number; + if (type == "char" || type == "int8") { + number = int8; } - else if (name == "y") { - xyz_coords++; + else if (type == "uchar" || type == "uint8") { + number = uint8; } - else if (name == "z") { - xyz_coords++; + else if (type == "short" || type == "int16") { + number = int16; } - else if (name == "red") { - rgb_value = MeshIO::PER_VERTEX; - if (_material) { - _material->binding = MeshIO::PER_VERTEX; - _material->diffuseColor.reserve(v_count); - } + else if (type == "ushort" || type == "uint16") { + number = uint16; } + else if (type == "int" || type == "int32") { + number = int32; + } + else if (type == "uint" || type == "uint32") { + number = uint32; + } + else if (type == "float" || type == "float32") { + number = float32; + } + else if (type == "double" || type == "float64") { + number = float64; + } + else { + // no valid number type + return false; + } + + // store the property name and type + vertex_props.push_back(std::make_pair(name, number)); } else if (element == "face") { std::string list, uchr; str >> space >> std::ws - >> list >> std::ws >> uchr >> std::ws - >> type >> std::ws >> name >> std::ws; - if (name != "vertex_indices") { - if (type == "float" || type == "float32") - face_props.push_back(4); - else if (type == "double" || type == "float64") - face_props.push_back(8); + >> list >> std::ws; + if (list == "list") { + str >> uchr >> std::ws + >> type >> std::ws >> name >> std::ws; + } + else { + // not a 'list' + type = list; + str >> name; + } + if (name != "vertex_indices" && name != "vertex_index") { + Number number; + if (type == "char" || type == "int8") { + number = int8; + } + else if (type == "uchar" || type == "uint8") { + number = uint8; + } + else if (type == "short" || type == "int16") { + number = int16; + } + else if (type == "ushort" || type == "uint16") { + number = uint16; + } + else if (type == "int" || type == "int32") { + number = int32; + } + else if (type == "uint" || type == "uint32") { + number = uint32; + } + else if (type == "float" || type == "float32") { + number = float32; + } + else if (type == "double" || type == "float64") { + number = float64; + } + else { + // no valid number type + return false; + } + + // store the property name and type + face_props.push_back(number); } } } @@ -632,64 +700,121 @@ bool MeshInput::LoadPLY (std::istream &inp) } } - // not 3d points - if (xyz_coords != 3) + // check if valid 3d points + MeshPly_Property property; + std::size_t num_x = std::count_if(vertex_props.begin(), vertex_props.end(), + std::bind2nd(property, "x")); + if (num_x != 1) return false; - if (format == ascii) { - boost::regex rx_p("^([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" - "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" - "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)\\s*$"); - boost::regex rx_c("^([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" - "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" - "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" - "\\s+([0-9]{1,3})\\s+([0-9]{1,3})\\s+([0-9]{1,3})\\s*$"); - boost::regex rx_f("^\\s*3\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*"); - boost::cmatch what; - Base::Vector3f pt; + std::size_t num_y = std::count_if(vertex_props.begin(), vertex_props.end(), + std::bind2nd(property, "y")); + if (num_y != 1) + return false; - if (rgb_value == MeshIO::PER_VERTEX) { - int r,g,b; - for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) { - if (boost::regex_match(line.c_str(), what, rx_c)) { - pt.x = (float)std::atof(what[1].first); - pt.y = (float)std::atof(what[4].first); - pt.z = (float)std::atof(what[7].first); - meshPoints.push_back(pt); - if (_material) { - r = std::min(std::atoi(what[10].first),255); - g = std::min(std::atoi(what[11].first),255); - b = std::min(std::atoi(what[12].first),255); - float fr = (float)r/255.0f; - float fg = (float)g/255.0f; - float fb = (float)b/255.0f; - _material->diffuseColor.push_back(App::Color(fr, fg, fb)); - } - } - else { + std::size_t num_z = std::count_if(vertex_props.begin(), vertex_props.end(), + std::bind2nd(property, "z")); + if (num_z != 1) + return false; + + // check if valid colors are set + std::size_t num_r = std::count_if(vertex_props.begin(), vertex_props.end(), + std::bind2nd(property, "red")); + std::size_t num_g = std::count_if(vertex_props.begin(), vertex_props.end(), + std::bind2nd(property, "green")); + std::size_t num_b = std::count_if(vertex_props.begin(), vertex_props.end(), + std::bind2nd(property, "blue")); + std::size_t rgb_colors = num_r + num_g + num_b; + if (rgb_colors != 0 && rgb_colors != 3) + return false; + + // only if set per vertex + if (rgb_colors == 3) { + rgb_value = MeshIO::PER_VERTEX; + if (_material) { + _material->binding = MeshIO::PER_VERTEX; + _material->diffuseColor.reserve(v_count); + } + } + + if (format == ascii) { + boost::regex rx_d("(([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?))\\s*"); + boost::regex rx_s("\\b([-+]?[0-9]+)\\s*"); + boost::regex rx_u("\\b([0-9]+)\\s*"); + boost::regex rx_f("^\\s*3\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*"); + boost::smatch what; + + for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) { + // go through the vertex properties + std::map prop_values; + for (std::vector >::iterator it = vertex_props.begin(); it != vertex_props.end(); ++it) { + switch (it->second) { + case int8: + case int16: + case int32: + { + if (boost::regex_search(line, what, rx_s)) { + int v; + v = boost::lexical_cast(what[1]); + prop_values[it->first] = static_cast(v); + line = line.substr(what[0].length()); + } + else { + return false; + } + } break; + case uint8: + case uint16: + case uint32: + { + if (boost::regex_search(line, what, rx_u)) { + int v; + v = boost::lexical_cast(what[1]); + prop_values[it->first] = static_cast(v); + line = line.substr(what[0].length()); + } + else { + return false; + } + } break; + case float32: + case float64: + { + if (boost::regex_search(line, what, rx_d)) { + double v; + v = boost::lexical_cast(what[1]); + prop_values[it->first] = static_cast(v); + line = line.substr(what[0].length()); + } + else { + return false; + } + } break; + default: return false; } } - } - else { - for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) { - if (boost::regex_match(line.c_str(), what, rx_p)) { - pt.x = (float)std::atof(what[1].first); - pt.y = (float)std::atof(what[4].first); - pt.z = (float)std::atof(what[7].first); - meshPoints.push_back(pt); - } - else { - return false; - } + + Base::Vector3f pt; + pt.x = (prop_values["x"]); + pt.y = (prop_values["y"]); + pt.z = (prop_values["z"]); + meshPoints.push_back(pt); + + if (_material && (rgb_value == MeshIO::PER_VERTEX)) { + float r = (prop_values["red"]) / 255.0f; + float g = (prop_values["green"]) / 255.0f; + float b = (prop_values["blue"]) / 255.0f; + _material->diffuseColor.push_back(App::Color(r, g, b)); } } + int f1, f2, f3; for (std::size_t i = 0; i < f_count && std::getline(inp, line); i++) { - if (boost::regex_search(line.c_str(), what, rx_f)) { - f1 = std::atoi(what[1].first); - f2 = std::atoi(what[2].first); - f3 = std::atoi(what[3].first); + if (boost::regex_search(line, what, rx_f)) { + f1 = boost::lexical_cast(what[1]); + f2 = boost::lexical_cast(what[2]); + f3 = boost::lexical_cast(what[3]); meshFacets.push_back(MeshFacet(f1,f2,f3)); } } @@ -701,39 +826,71 @@ bool MeshInput::LoadPLY (std::istream &inp) is.setByteOrder(Base::Stream::LittleEndian); else is.setByteOrder(Base::Stream::BigEndian); - int r,g,b; - if (xyz_float) { + + for (std::size_t i = 0; i < v_count; i++) { + // go through the vertex properties + std::map prop_values; + for (std::vector >::iterator it = vertex_props.begin(); it != vertex_props.end(); ++it) { + switch (it->second) { + case int8: + { + int8_t v; is >> v; + prop_values[it->first] = static_cast(v); + } break; + case uint8: + { + uint8_t v; is >> v; + prop_values[it->first] = static_cast(v); + } break; + case int16: + { + int16_t v; is >> v; + prop_values[it->first] = static_cast(v); + } break; + case uint16: + { + uint16_t v; is >> v; + prop_values[it->first] = static_cast(v); + } break; + case int32: + { + int32_t v; is >> v; + prop_values[it->first] = static_cast(v); + } break; + case uint32: + { + uint32_t v; is >> v; + prop_values[it->first] = static_cast(v); + } break; + case float32: + { + float v; is >> v; + prop_values[it->first] = v; + } break; + case float64: + { + double v; is >> v; + prop_values[it->first] = static_cast(v); + } break; + default: + return false; + } + } + Base::Vector3f pt; - for (std::size_t i = 0; i < v_count; i++) { - is >> pt.x >> pt.y >> pt.z; - meshPoints.push_back(pt); - if (rgb_value == MeshIO::PER_VERTEX) { - is >> r >> g >> b; - if (_material) { - float fr = (float)r/255.0f; - float fg = (float)g/255.0f; - float fb = (float)b/255.0f; - _material->diffuseColor.push_back(App::Color(fr, fg, fb)); - } - } - } - } - else if (xyz_double) { - Base::Vector3d pt; - for (std::size_t i = 0; i < v_count; i++) { - is >> pt.x >> pt.y >> pt.z; - meshPoints.push_back(Base::Vector3f((float)pt.x,(float)pt.y,(float)pt.z)); - if (rgb_value == MeshIO::PER_VERTEX) { - is >> r >> g >> b; - if (_material) { - float fr = (float)r/255.0f; - float fg = (float)g/255.0f; - float fb = (float)b/255.0f; - _material->diffuseColor.push_back(App::Color(fr, fg, fb)); - } - } + pt.x = (prop_values["x"]); + pt.y = (prop_values["y"]); + pt.z = (prop_values["z"]); + meshPoints.push_back(pt); + + if (_material && (rgb_value == MeshIO::PER_VERTEX)) { + float r = (prop_values["red"]) / 255.0f; + float g = (prop_values["green"]) / 255.0f; + float b = (prop_values["blue"]) / 255.0f; + _material->diffuseColor.push_back(App::Color(r, g, b)); } } + unsigned char n; uint32_t f1, f2, f3; for (std::size_t i = 0; i < f_count; i++) { @@ -742,18 +899,48 @@ bool MeshInput::LoadPLY (std::istream &inp) is >> f1 >> f2 >> f3; if (f1 < v_count && f2 < v_count && f3 < v_count) meshFacets.push_back(MeshFacet(f1,f2,f3)); - for (std::vector::iterator it = face_props.begin(); it != face_props.end(); ++it) { - if (*it == 4) { - is >> n; - float f; - for (unsigned char j=0; j> f; - } - else if (*it == 8) { - is >> n; - double d; - for (unsigned char j=0; j> d; + for (std::vector::iterator it = face_props.begin(); it != face_props.end(); ++it) { + switch (*it) { + case int8: + { + int8_t v; is >> v; + } break; + case uint8: + { + uint8_t v; is >> v; + } break; + case int16: + { + int16_t v; is >> v; + } break; + case uint16: + { + uint16_t v; is >> v; + } break; + case int32: + { + int32_t v; is >> v; + } break; + case uint32: + { + uint32_t v; is >> v; + } break; + case float32: + { + is >> n; + float v; + for (unsigned char j=0; j> v; + } break; + case float64: + { + is >> n; + double v; + for (unsigned char j=0; j> v; + } break; + default: + return false; } } }