From 48b39d574e8956416085cbe476c31c5f145b2e81 Mon Sep 17 00:00:00 2001 From: Alexey Smolenchuk Date: Mon, 10 Feb 2025 23:45:31 +0000 Subject: [PATCH 1/2] rename classic readers --- src/lib/io/{BGEO.cpp => BHCLASSIC.cpp} | 4 ++-- src/lib/io/{GEO.cpp => HCLASSIC.cpp} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/lib/io/{BGEO.cpp => BHCLASSIC.cpp} (98%) rename src/lib/io/{GEO.cpp => HCLASSIC.cpp} (98%) diff --git a/src/lib/io/BGEO.cpp b/src/lib/io/BHCLASSIC.cpp similarity index 98% rename from src/lib/io/BGEO.cpp rename to src/lib/io/BHCLASSIC.cpp index e3406d3..2fe9662 100644 --- a/src/lib/io/BGEO.cpp +++ b/src/lib/io/BHCLASSIC.cpp @@ -184,7 +184,7 @@ bool skipPrimitives(int nPoints, int nPrims, int nPrimAttrib, istream* input,std return true; } -ParticlesDataMutable* readBGEO(const char* filename,const bool headersOnly,std::ostream* errorStream) +ParticlesDataMutable* readBHCLASSIC(const char* filename,const bool headersOnly,std::ostream* errorStream) { unique_ptr input(io::unzip(filename)); if(!*input){ @@ -299,7 +299,7 @@ ParticlesDataMutable* readBGEO(const char* filename,const bool headersOnly,std:: return simple; } -bool writeBGEO(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream) +bool writeBHCLASSIC(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream) { unique_ptr output(io::write(filename, compressed)); if(!*output){ diff --git a/src/lib/io/GEO.cpp b/src/lib/io/HCLASSIC.cpp similarity index 98% rename from src/lib/io/GEO.cpp rename to src/lib/io/HCLASSIC.cpp index f08a8b6..df8ed7a 100644 --- a/src/lib/io/GEO.cpp +++ b/src/lib/io/HCLASSIC.cpp @@ -99,7 +99,7 @@ string scanString(istream& input) return string(buf); } -ParticlesDataMutable* readGEO(const char* filename,const bool headersOnly,std::ostream* errorStream) +ParticlesDataMutable* readHCLASSIC(const char* filename,const bool headersOnly,std::ostream* errorStream) { unique_ptr input(io::unzip(filename)); if(!*input){ @@ -227,7 +227,7 @@ void writeType(ostream& output,const ParticlesData&,const ParticleAttribute& att } } -bool writeGEO(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream) +bool writeHCLASSIC(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream) { unique_ptr output(io::write(filename, compressed)); *output<<"PGEOMETRY V5"< Date: Tue, 11 Feb 2025 00:23:12 +0000 Subject: [PATCH 2/2] add simple modern-bgeo reader --- CMakeLists.txt | 7 ++ src/lib/CMakeLists.txt | 35 +++++++++- src/lib/core/KdTree.h | 8 +++ src/lib/io/BGEO.cpp | 24 +++++++ src/lib/io/BJSON.cpp | 136 ++++++++++++++++++++++++++++++++++++++ src/lib/io/GEO.cpp | 24 +++++++ src/lib/io/ParticleIO.cpp | 18 ++--- src/lib/io/readers.h | 55 ++++++++------- src/tests/testcluster.cpp | 2 +- 9 files changed, 274 insertions(+), 35 deletions(-) create mode 100644 src/lib/io/BGEO.cpp create mode 100644 src/lib/io/BJSON.cpp create mode 100644 src/lib/io/GEO.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 691d561..ef81902 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,6 +129,13 @@ else() set(ZLIB_LIBRARY "") endif() +find_package(bgeo) +if (bgeo_FOUND) + message("Building with modern Bgeo support") +else() + message("Building with NO modern Bgeo support") +endif() + # Make modules able to see partio library set(PARTIO_LIBRARIES partio ${ZLIB_LIBRARY}) diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 451abdc..5349425 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -31,8 +31,34 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -file(GLOB io_cpp "io/*.cpp") -file(GLOB core_cpp "core/*.cpp") +set(core_cpp + core/Particle.cpp + core/ParticleCaching.cpp + core/ParticleHeaders.cpp + core/ParticleSimple.cpp + core/ParticleSimpleInterleave.cpp) + +set(io_cpp + io/BGEO.cpp + io/BHCLASSIC.cpp + io/BIN.cpp + io/GEO.cpp + io/HCLASSIC.cpp + io/MC.cpp + io/ParticleIO.cpp + io/PDA.cpp + io/PDB.cpp + io/PDC.cpp + io/PRT.cpp + io/PTC.cpp + io/PTS.cpp + io/RIB.cpp + io/ZIP.cpp +) + +if (bgeo_FOUND) + list(APPEND io_cpp io/BJSON.cpp ) +endif() if(PARTIO_BUILD_SHARED_LIBS) set(PARTIO_LIBRARY_TYPE SHARED) @@ -55,6 +81,11 @@ if (ZLIB_FOUND) target_link_libraries(partio PUBLIC ZLIB::ZLIB) endif() +if (bgeo_FOUND) + target_link_libraries(partio PUBLIC bgeo::bgeo) + target_compile_definitions(partio PRIVATE MODERN_BGEO) +endif() + install(TARGETS partio DESTINATION ${CMAKE_INSTALL_LIBDIR}) file(GLOB public_includes "*.h") diff --git a/src/lib/core/KdTree.h b/src/lib/core/KdTree.h index 7b73b86..9736533 100644 --- a/src/lib/core/KdTree.h +++ b/src/lib/core/KdTree.h @@ -325,8 +325,16 @@ void KdTree::sortSubtree(int n, int size, int j) // partition range [n, n+size) along axis j into two subranges: // [n, n+leftSize+1) and [n+leftSize+1, n+size) +#ifdef NDEBUG std::nth_element(&_ids[n], &_ids[n+left], &_ids[n+size], ComparePointsById(&_points[0].p[j])); +#else + // In Debug mode element compiler asserting on _ids[n+size] with + // Expression: vector subscript out of range + // whereas it's not accessed by algorithm + std::nth_element(&_ids[n], &_ids[n+left], &_ids[std::min(n+size, this->size()-1)], + ComparePointsById(&_points[0].p[j])); +#endif // move median value (nth element) to front as root node of subtree std::swap(_ids[n], _ids[n+left]); diff --git a/src/lib/io/BGEO.cpp b/src/lib/io/BGEO.cpp new file mode 100644 index 0000000..3fe02b4 --- /dev/null +++ b/src/lib/io/BGEO.cpp @@ -0,0 +1,24 @@ + +#include "../core/ParticleHeaders.h" +#include "readers.h" + +namespace Partio +{ + ParticlesDataMutable* readBGEO(const char* filename, const bool headersOnly, std::ostream* errorStream) + { + +#ifdef MODERN_BGEO + ParticlesDataMutable *result = readBJSON(filename, headersOnly, errorStream); + if (result != nullptr) + return result; +#endif + + // Fallback to bhclassic + return readBHCLASSIC(filename, headersOnly, errorStream); + } + + bool writeBGEO(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream) + { + return writeBHCLASSIC(filename, p, compressed, errorStream); + } +} diff --git a/src/lib/io/BJSON.cpp b/src/lib/io/BJSON.cpp new file mode 100644 index 0000000..920c1a0 --- /dev/null +++ b/src/lib/io/BJSON.cpp @@ -0,0 +1,136 @@ +// Utilize this library +// https://github.com/LaikaStudios/bgeo_reader + + +#include "../core/ParticleHeaders.h" + +#ifdef MODERN_BGEO + #include + #include + #include +#endif + +#include + +using namespace ika::bgeo; + +namespace Partio +{ + std::string getMapping(const char* name) + { + const std::unordered_map mapping = + { + {"P", "position"}, + }; + auto it = mapping.find(name); + if (it != mapping.end()) + return it->second; + else + return name; + } + + ParticlesDataMutable* readBJSON(const char* filename, const bool headersOnly, std::ostream* errorStream) + { + try + { + BgeoHeader bgeoHeader(filename); + } + catch(const ika::bgeo::parser::ReadError& e) + { + return nullptr; + } + + Bgeo bgeo(filename, false); + + // Allocate a simple particle with the appropriate number of points + ParticlesDataMutable* particles = headersOnly ? new ParticleHeaders : create(); + particles->addParticles(bgeo.getPointCount()); + + int attribCount = bgeo.getPointAttributeCount(); + for (int k = 0; k < attribCount; k++) + { + Bgeo::AttributePtr currentAttrib = bgeo.getPointAttribute(k); + + if (strcmp(currentAttrib->getType(), "string") == 0) + { + std::vector values; + std::vector strings; + currentAttrib->getData(values); + currentAttrib->getStrings(strings); + + ParticleAttribute attrib = particles->addAttribute( getMapping(currentAttrib->getName()).c_str(), INDEXEDSTR, 1); + for(size_t i = 0; i < strings.size(); i++) + { + particles->registerIndexedStr(attrib, strings[i].c_str()); + } + + for (size_t i = 0; i < bgeo.getPointCount(); i++) + { + int* data = particles->dataWrite(attrib, i); + *data = values[i]; + } + continue; + } + + int tupleSize = currentAttrib->getTupleSize(); + parser::storage::Storage fundamentalType = currentAttrib->getFundamentalType();// 1: Int32, 2: Fpreal32 + ParticleAttributeType myType = NONE; + + if (fundamentalType == parser::storage::Int32) + myType = INT; + else if(fundamentalType == parser::storage::Fpreal32) + { + myType = FLOAT; + const char *subType = currentAttrib->getSubType(); + + if ((tupleSize == 3) && + ((strcmp(subType, "point") == 0) || + (strcmp(subType, "vector") == 0) || + (strcmp(subType, "normal") == 0))) + myType = VECTOR; + } + else + continue; + + ParticleAttribute attrib = particles->addAttribute( getMapping(currentAttrib->getName()).c_str(), myType, tupleSize); + + if (fundamentalType == parser::storage::Int32) + { + std::vector values; + currentAttrib->getData(values); + size_t idx = 0; + + for (size_t i = 0; i < bgeo.getPointCount(); i++) + { + int* data = particles->dataWrite(attrib, i); + + for (int c = 0; c < tupleSize; c++) + { + data[c] = values[idx+c]; + } + idx += tupleSize; + } + } + else if(fundamentalType == parser::storage::Fpreal32) + { + std::vector values; + currentAttrib->getData(values); + size_t idx = 0; + + for (size_t i = 0; i < bgeo.getPointCount(); i++) + { + float* data = particles->dataWrite(attrib, i); + for (int c = 0; c < tupleSize; c++) + { + data[c] = values[idx+c]; + } + idx += tupleSize; + } + } + else + continue; + } + + return particles; + } +} diff --git a/src/lib/io/GEO.cpp b/src/lib/io/GEO.cpp new file mode 100644 index 0000000..1943587 --- /dev/null +++ b/src/lib/io/GEO.cpp @@ -0,0 +1,24 @@ + +#include "../core/ParticleHeaders.h" +#include "readers.h" + +namespace Partio +{ + ParticlesDataMutable* readGEO(const char* filename, const bool headersOnly, std::ostream* errorStream) + { + +#ifdef MODERN_BGEO + ParticlesDataMutable *result = readBJSON(filename, headersOnly, errorStream); + if (result != nullptr) + return result; +#endif + + // Fallback to hclassic + return readHCLASSIC(filename, headersOnly, errorStream); + } + + bool writeGEO(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream) + { + return writeHCLASSIC(filename, p, compressed, errorStream); + } +} diff --git a/src/lib/io/ParticleIO.cpp b/src/lib/io/ParticleIO.cpp index ba4698f..2048906 100644 --- a/src/lib/io/ParticleIO.cpp +++ b/src/lib/io/ParticleIO.cpp @@ -55,9 +55,9 @@ readers() if(!initialized){ initializationMutex.lock(); data["bgeo"]=readBGEO; - data["bhclassic"]=readBGEO; + data["bhclassic"]=readBHCLASSIC; data["geo"]=readGEO; - data["hclassic"]=readGEO; + data["hclassic"]=readHCLASSIC; data["pdb"]=readPDB; data["pdb32"]=readPDB32; data["pdb64"]=readPDB64; @@ -69,8 +69,8 @@ readers() data["bin"]=readBIN; data["pts"]=readPTS; data["ptf"]=readPTC; - data["itbl"]=readBGEO; - data["atbl"]=readBGEO; + data["itbl"]=readBHCLASSIC; + data["atbl"]=readBHCLASSIC; initialized=true; initializationMutex.unlock(); } @@ -85,9 +85,9 @@ writers() if(!initialized){ initializationMutex.lock(); data["bgeo"]=writeBGEO; - data["bhclassic"]=writeBGEO; + data["bhclassic"]=writeBHCLASSIC; data["geo"]=writeGEO; - data["hclassic"]=writeGEO; + data["hclassic"]=writeHCLASSIC; data["pdb"]=writePDB; data["pdb32"]=writePDB32; data["pdb64"]=writePDB64; @@ -98,8 +98,8 @@ writers() data["prt"]=writePRT; data["bin"]=writeBIN; data["ptf"]=writePTC; - data["itbl"]=writeBGEO; - data["atbl"]=writeBGEO; + data["itbl"]=writeBHCLASSIC; + data["atbl"]=writeBHCLASSIC; initialized=true; initializationMutex.unlock(); } @@ -117,7 +117,7 @@ bool extensionIgnoringGz(const string& filename,string& ret,bool &endsWithGz,std return false; } string extension=filename.substr(period+1); - if(extension=="gz"){ + if(extension=="gz" || extension=="sc"){ endsWithGz=true; size_t period2=filename.rfind('.',period-1); if(period2==string::npos){ diff --git a/src/lib/io/readers.h b/src/lib/io/readers.h index 0e8d60d..5379873 100644 --- a/src/lib/io/readers.h +++ b/src/lib/io/readers.h @@ -36,30 +36,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. #define _READERS_h_ namespace Partio{ -ParticlesDataMutable* readBGEO( const char* filename,const bool headersOnly,std::ostream* errorStream); -ParticlesDataMutable* readGEO( const char* filename,const bool headersOnly,std::ostream* errorStream); -ParticlesDataMutable* readPDB( const char* filename,const bool headersOnly,std::ostream* errorStream); -ParticlesDataMutable* readPDB32(const char* filename,const bool headersOnly,std::ostream* errorStream); -ParticlesDataMutable* readPDB64(const char* filename,const bool headersOnly,std::ostream* errorStream); -ParticlesDataMutable* readPDA( const char* filename,const bool headersOnly,std::ostream* errorStream); -ParticlesDataMutable* readMC( const char* filename,const bool headersOnly,std::ostream* errorStream); -ParticlesDataMutable* readPTC( const char* filename,const bool headersOnly,std::ostream* errorStream); -ParticlesDataMutable* readPDC( const char* filename,const bool headersOnly,std::ostream* errorStream); -ParticlesDataMutable* readPRT( const char* filename,const bool headersOnly,std::ostream* errorStream); -ParticlesDataMutable* readBIN( const char* filename,const bool headersOnly,std::ostream* errorStream); -ParticlesDataMutable* readPTS( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readBGEO( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readGEO( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readBHCLASSIC(const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readHCLASSIC( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readPDB( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readPDB32( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readPDB64( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readPDA( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readMC( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readPTC( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readPDC( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readPRT( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readBIN( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readPTS( const char* filename,const bool headersOnly,std::ostream* errorStream); -bool writeBGEO(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); -bool writeGEO(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); -bool writePDB(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); -bool writePDB32(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); -bool writePDB64(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); -bool writePDA(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); -bool writePTC(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); -bool writeRIB(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); -bool writePDC(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); -bool writePRT(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); -bool writeBIN(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +#ifdef MODERN_BGEO +ParticlesDataMutable* readBJSON( const char* filename,const bool headersOnly,std::ostream* errorStream); +ParticlesDataMutable* readJSON( const char* filename,const bool headersOnly,std::ostream* errorStream); +#endif + +bool writeBGEO( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writeGEO( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writeBHCLASSIC(const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writeHCLASSIC( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writePDB( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writePDB32( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writePDB64( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writePDA( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writePTC( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writeRIB( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writePDC( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writePRT( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); +bool writeBIN( const char* filename,const ParticlesData& p,const bool compressed,std::ostream* errorStream); } #endif diff --git a/src/tests/testcluster.cpp b/src/tests/testcluster.cpp index f4fa498..d2c125d 100644 --- a/src/tests/testcluster.cpp +++ b/src/tests/testcluster.cpp @@ -45,6 +45,6 @@ int main(int argc,char *argv[]) { Partio::ParticlesDataMutable* p=Partio::read(PARTIO_DATA_DIR "/scatter.bgeo"); Partio::ParticlesDataMutable* c=Partio::computeClustering(p,5,1.5,100,2,5); - Partio::write("/tmp/partio-cluster.bgeo",*c); + Partio::write("partio-cluster.bgeo",*c); return 0; }