Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:33

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Visualization/ObjVisualization3D.hpp"
0010 
0011 #include <algorithm>
0012 #include <fstream>
0013 #include <stdexcept>
0014 
0015 namespace Acts {
0016 
0017 void ObjVisualization3D::vertex(const Vector3& vtx, Color color) {
0018   auto& o = object();
0019   o.vertexColors[o.vertices.size()] = color;
0020   o.vertices.push_back(vtx.template cast<ValueType>());
0021 }
0022 
0023 void ObjVisualization3D::line(const Vector3& a, const Vector3& b, Color color) {
0024   auto& o = object();
0025   if (color != Color{0, 0, 0}) {
0026     o.lineColors[o.lines.size()] = color;
0027   }
0028   // not implemented
0029   vertex(a, color);
0030   vertex(b, color);
0031   o.lines.push_back({o.vertices.size() - 2, o.vertices.size() - 1});
0032 }
0033 
0034 void ObjVisualization3D::face(const std::vector<Vector3>& vtxs, Color color) {
0035   auto& o = object();
0036   if (color != Color{0, 0, 0}) {
0037     o.faceColors[o.faces.size()] = color;
0038   }
0039   FaceType idxs;
0040   idxs.reserve(vtxs.size());
0041   for (const auto& vtx : vtxs) {
0042     vertex(vtx, color);
0043     idxs.push_back(o.vertices.size() - 1);
0044   }
0045   o.faces.push_back(std::move(idxs));
0046 }
0047 
0048 void ObjVisualization3D::faces(const std::vector<Vector3>& vtxs,
0049                                const std::vector<FaceType>& faces,
0050                                Color color) {
0051   auto& o = object();
0052   // No faces given - call the face() method
0053   if (faces.empty()) {
0054     face(vtxs, color);
0055   } else {
0056     if (color != Color{0, 0, 0}) {
0057       o.faceColors[o.faces.size()] = color;
0058     }
0059     auto vtxoffs = o.vertices.size();
0060     if (color != Color{0, 0, 0}) {
0061       o.vertexColors[o.vertices.size()] = color;
0062     }
0063     o.vertices.insert(o.vertices.end(), vtxs.begin(), vtxs.end());
0064     for (const auto& face : faces) {
0065       if (face.size() == 2) {
0066         o.lines.push_back({face[0] + vtxoffs, face[1] + vtxoffs});
0067       } else {
0068         FaceType rawFace;
0069         std::ranges::transform(
0070             face, std::back_inserter(rawFace),
0071             [&](unsigned long iv) { return (iv + vtxoffs); });
0072         o.faces.push_back(rawFace);
0073       }
0074     }
0075   }
0076 }
0077 
0078 void ObjVisualization3D::write(const std::filesystem::path& path) const {
0079   std::ofstream os;
0080   std::filesystem::path objectpath = path;
0081   if (!objectpath.has_extension()) {
0082     objectpath.replace_extension(std::filesystem::path("obj"));
0083   }
0084   os.open(std::filesystem::absolute(objectpath).string());
0085   std::filesystem::path mtlpath = objectpath;
0086   mtlpath.replace_extension(std::filesystem::path("mtl"));
0087 
0088   const std::string mtlpathString = std::filesystem::absolute(mtlpath).string();
0089   os << "mtllib " << mtlpathString << "\n";
0090   std::ofstream mtlos;
0091   mtlos.open(mtlpathString);
0092 
0093   write(os, mtlos);
0094   os.close();
0095   mtlos.close();
0096 }
0097 
0098 void ObjVisualization3D::write(std::ostream& os) const {
0099   std::stringstream sterile;
0100   write(os, sterile);
0101 }
0102 
0103 void ObjVisualization3D::write(std::ostream& os, std::ostream& mos) const {
0104   std::map<std::string, bool, std::less<>> materials;
0105 
0106   auto mixColor = [&](const Color& color) {
0107     std::string materialName;
0108     materialName = "material_";
0109     materialName += std::to_string(color[0]) + std::string("_");
0110     materialName += std::to_string(color[1]) + std::string("_");
0111     materialName += std::to_string(color[2]);
0112 
0113     if (!materials.contains(materialName)) {
0114       mos << "newmtl " << materialName << "\n";
0115       std::vector<std::string> shadings = {"Ka", "Kd", "Ks"};
0116       for (const auto& shd : shadings) {
0117         mos << shd << " " << std::to_string(color[0] / 256.) << " ";
0118         mos << std::to_string(color[1] / 256.) << " ";
0119         mos << std::to_string(color[2] / 256.) << " " << "\n";
0120       }
0121       mos << "\n";
0122     }
0123     return std::string("usemtl ") + materialName;
0124   };
0125 
0126   std::size_t vertexOffset = 0;
0127   for (const auto& o : m_objects) {
0128     if (!o.name.empty()) {
0129       os << "o " << o.name << "\n";
0130     }
0131 
0132     std::size_t iv = 0;
0133     Color lastVertexColor = {0, 0, 0};
0134     for (const VertexType& vtx : o.vertices) {
0135       if (o.vertexColors.contains(iv)) {
0136         auto color = o.vertexColors.find(iv)->second;
0137         if (color != lastVertexColor) {
0138           os << mixColor(color) << "\n";
0139           lastVertexColor = color;
0140         }
0141       }
0142 
0143       os << "v " << std::setprecision(m_outputPrecision)
0144          << m_outputScalor * vtx.x() << " " << m_outputScalor * vtx.y() << " "
0145          << m_outputScalor * vtx.z() << "\n";
0146       ++iv;
0147     }
0148     std::size_t il = 0;
0149     Color lastLineColor = {0, 0, 0};
0150     for (const auto& [start, end] : o.lines) {
0151       if (o.lineColors.contains(il)) {
0152         auto color = o.lineColors.find(il)->second;
0153         if (color != lastLineColor) {
0154           os << mixColor(color) << "\n";
0155           lastLineColor = color;
0156         }
0157       }
0158       os << "l " << vertexOffset + start + 1 << " " << vertexOffset + end + 1
0159          << "\n";
0160       ++il;
0161     }
0162     std::size_t is = 0;
0163     Color lastFaceColor = {0, 0, 0};
0164     for (const FaceType& fc : o.faces) {
0165       if (o.faceColors.contains(is)) {
0166         auto color = o.faceColors.find(is)->second;
0167         if (color != lastFaceColor) {
0168           os << mixColor(color) << "\n";
0169           lastFaceColor = color;
0170         }
0171       }
0172       os << "f";
0173       for (std::size_t fi : fc) {
0174         os << " " << vertexOffset + fi + 1;
0175       }
0176       os << "\n";
0177       ++is;
0178     }
0179 
0180     vertexOffset += iv;
0181   }
0182 }
0183 
0184 void ObjVisualization3D::clear() {
0185   m_objects.clear();
0186 }
0187 
0188 void ObjVisualization3D::object(const std::string& name) {
0189   if (name.empty()) {
0190     throw std::invalid_argument{"Object name can not be empty"};
0191   }
0192   m_objects.push_back(Object{.name = name});
0193 }
0194 
0195 ObjVisualization3D::Object& ObjVisualization3D::object() {
0196   if (m_objects.empty()) {
0197     m_objects.push_back(Object{.name = ""});
0198   }
0199 
0200   return m_objects.back();
0201 }
0202 
0203 const ObjVisualization3D::Object& ObjVisualization3D::object() const {
0204   if (m_objects.empty()) {
0205     throw std::runtime_error{"No objects present"};
0206   }
0207 
0208   return m_objects.back();
0209 }
0210 
0211 }  // namespace Acts