material.cpp
Go to the documentation of this file.
1 
29 #include <stdexcept>
30 #include <unordered_map>
31 
32 #include <boost/algorithm/string.hpp>
33 #include <console_bridge/console.h>
34 #include <Eigen/Geometry>
35 #include <tesseract_common/utils.h>
36 #include <tinyxml2.h>
38 
41 
42 namespace tesseract_urdf
43 {
45 parseMaterial(const tinyxml2::XMLElement* xml_element,
46  std::unordered_map<std::string, tesseract_scene_graph::Material::Ptr>& available_materials,
47  bool allow_anonymous)
48 {
49  std::string material_name;
50  if (tesseract_common::QueryStringAttribute(xml_element, "name", material_name) != tinyxml2::XML_SUCCESS)
51  std::throw_with_nested(std::runtime_error("Material: Missing or failed parsing attribute 'name'!"));
52 
53  auto m = std::make_shared<tesseract_scene_graph::Material>(material_name);
54 
55  m->texture_filename = "";
56  const tinyxml2::XMLElement* texture = xml_element->FirstChildElement("texture");
57  if (texture != nullptr)
58  {
59  if (tesseract_common::QueryStringAttribute(texture, "filename", m->texture_filename) != tinyxml2::XML_SUCCESS)
60  std::throw_with_nested(std::runtime_error("Material: Missing or failed parsing texture attribute 'filename'!"));
61  }
62 
63  const tinyxml2::XMLElement* color = xml_element->FirstChildElement("color");
64  if (color != nullptr)
65  {
66  std::string color_string;
67  if (tesseract_common::QueryStringAttribute(color, "rgba", color_string) != tinyxml2::XML_SUCCESS)
68  std::throw_with_nested(std::runtime_error("Material: Missing or failed parsing color attribute 'rgba'!"));
69 
70  if (!color_string.empty())
71  {
72  std::vector<std::string> tokens;
73  boost::split(tokens, color_string, boost::is_any_of(" "), boost::token_compress_on);
74  if (tokens.size() != 4 || !tesseract_common::isNumeric(tokens))
75  std::throw_with_nested(std::runtime_error("Material: Failed to parse color attribute 'rgba' from string!"));
76 
77  double r{ 0 }, g{ 0 }, b{ 0 }, a{ 0 };
78  // No need to check return values because the tokens are verified above
83 
84  m->color = Eigen::Vector4d(r, g, b, a);
85  }
86  else
87  {
88  std::throw_with_nested(std::runtime_error("Material: Missing or failed parsing color attribute 'rgba'!"));
89  }
90  }
91 
92  if (color == nullptr && texture == nullptr)
93  {
94  if (available_materials.empty())
95  std::throw_with_nested(
96  std::runtime_error("Material: Material name '" + material_name + "' only is not allowed!"));
97 
98  auto it = available_materials.find(material_name);
99  if (it == available_materials.end())
100  std::throw_with_nested(std::runtime_error("Material with name only '" + material_name +
101  "' was not located in available materials!"));
102 
103  m = it->second;
104  }
105  else
106  {
107  if (!material_name.empty())
108  {
109  auto it = available_materials.find(material_name);
110  if (it != available_materials.end())
111  CONSOLE_BRIDGE_logDebug("Multiple materials with the same name '%s' exist!", material_name.c_str());
112 
113  available_materials[material_name] = m;
114  }
115  else if (!allow_anonymous)
116  {
117  std::throw_with_nested(std::runtime_error("Anonymous material names (empty string) not allowed!"));
118  }
119  }
120 
121  return m;
122 }
123 
124 tinyxml2::XMLElement* writeMaterial(const std::shared_ptr<const tesseract_scene_graph::Material>& material,
125  tinyxml2::XMLDocument& doc)
126 {
127  if (material == nullptr)
128  std::throw_with_nested(std::runtime_error("Material is nullptr and cannot be converted to XML"));
129  tinyxml2::XMLElement* xml_element = doc.NewElement(MATERIAL_ELEMENT_NAME.data());
130  Eigen::IOFormat eigen_format(Eigen::StreamPrecision, Eigen::DontAlignCols, " ", " ");
131 
132  xml_element->SetAttribute("name", material->getName().c_str());
133 
134  if (!material->texture_filename.empty())
135  {
136  tinyxml2::XMLElement* xml_texture = doc.NewElement("texture");
137  xml_texture->SetAttribute("filename", material->texture_filename.c_str());
138  xml_element->InsertEndChild(xml_texture);
139  }
140 
141  tinyxml2::XMLElement* xml_color = doc.NewElement("color");
142  std::stringstream color_string;
143  color_string << material->color.format(eigen_format);
144  xml_color->SetAttribute("rgba", color_string.str().c_str());
145  xml_element->InsertEndChild(xml_color);
146 
147  return xml_element;
148 }
149 
150 } // namespace tesseract_urdf
utils.h
tesseract_urdf::MATERIAL_ELEMENT_NAME
static constexpr std::string_view MATERIAL_ELEMENT_NAME
Definition: material.h:46
TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
#define TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
material.h
Parse material from xml string.
tesseract_common::QueryStringAttribute
int QueryStringAttribute(const tinyxml2::XMLElement *xml_element, const char *name, std::string &value)
r
S r
TESSERACT_COMMON_IGNORE_WARNINGS_POP
tesseract_urdf::writeMaterial
tinyxml2::XMLElement * writeMaterial(const std::shared_ptr< const tesseract_scene_graph::Material > &material, tinyxml2::XMLDocument &doc)
Definition: material.cpp:124
tesseract_common::isNumeric
bool isNumeric(const std::string &s)
tesseract_common::toNumeric< double >
template bool toNumeric< double >(const std::string &, double &)
tesseract_scene_graph::Material::Ptr
std::shared_ptr< Material > Ptr
macros.h
tesseract_urdf
Definition: box.h:43
tesseract_urdf::parseMaterial
std::shared_ptr< tesseract_scene_graph::Material > parseMaterial(const tinyxml2::XMLElement *xml_element, std::unordered_map< std::string, std::shared_ptr< tesseract_scene_graph::Material >> &available_materials, bool allow_anonymous)
Parse xml element material.


tesseract_urdf
Author(s): Levi Armstrong
autogenerated on Thu Apr 24 2025 03:10:44