215 cXMLElementList children = xml->getChildren();
216 for (cXMLElementList::const_iterator it = children.begin(); it != children.end(); ++it) {
218 cXMLElement *element = *it;
219 const char *tag = element->getTagName();
220 if (strcmp(tag,
"object"))
223 const char *idAttribute = element->getAttribute(
"id");
226 id = atoi(idAttribute);
228 const char *name = element->getAttribute(
"name");
231 Quaternion orientation;
232 const char *orientationAttribute = element->getAttribute(
"orientation");
233 if (orientationAttribute) {
234 cStringTokenizer tokenizer(orientationAttribute);
235 if ((tok = tokenizer.nextToken()) ==
nullptr)
236 throw cRuntimeError(
"Missing orientation alpha at %s", element->getSourceLocation());
238 if ((tok = tokenizer.nextToken()) ==
nullptr)
239 throw cRuntimeError(
"Missing orientation beta at %s", element->getSourceLocation());
240 auto beta =
deg(atof(tok));
241 if ((tok = tokenizer.nextToken()) ==
nullptr)
242 throw cRuntimeError(
"Missing orientation gamma at %s", element->getSourceLocation());
243 auto gamma =
deg(atof(tok));
244 orientation = Quaternion(EulerAngles(
alpha, beta, gamma));
248 const ShapeBase *shape =
nullptr;
249 const char *shapeAttribute = element->getAttribute(
"shape");
251 throw cRuntimeError(
"Missing shape attribute of object");
252 cStringTokenizer shapeTokenizer(shapeAttribute);
253 const char *shapeType = shapeTokenizer.nextToken();
254 if (!strcmp(shapeType,
"cuboid")) {
255 if ((tok = shapeTokenizer.nextToken()) ==
nullptr)
256 throw cRuntimeError(
"Missing cuboid x at %s", element->getSourceLocation());
258 if ((tok = shapeTokenizer.nextToken()) ==
nullptr)
259 throw cRuntimeError(
"Missing cuboid y at %s", element->getSourceLocation());
261 if ((tok = shapeTokenizer.nextToken()) ==
nullptr)
262 throw cRuntimeError(
"Missing cuboid z at %s", element->getSourceLocation());
264 shape =
new Cuboid(size);
267 else if (!strcmp(shapeType,
"sphere")) {
268 if ((tok = shapeTokenizer.nextToken()) ==
nullptr)
269 throw cRuntimeError(
"Missing sphere radius at %s", element->getSourceLocation());
270 double radius = atof(tok);
271 shape =
new Sphere(radius);
272 size = Coord(radius, radius, radius) * 2;
275 else if (!strcmp(shapeType,
"prism")) {
277 if ((tok = shapeTokenizer.nextToken()) ==
nullptr)
278 throw cRuntimeError(
"Missing prism height at %s", element->getSourceLocation());
280 std::vector<Coord> points;
281 while (shapeTokenizer.hasMoreTokens()) {
283 point.x = atof(shapeTokenizer.nextToken());
284 if ((tok = shapeTokenizer.nextToken()) ==
nullptr)
285 throw cRuntimeError(
"Missing prism y at %s", element->getSourceLocation());
287 point.z = -height / 2;
288 points.push_back(point);
290 if (points.size() < 3)
291 throw cRuntimeError(
"prism needs at least three points at %s", element->getSourceLocation());
294 shape =
new Prism(height, Polygon(points));
297 else if (!strcmp(shapeType,
"polyhedron")) {
298 std::vector<Coord> points;
299 while (shapeTokenizer.hasMoreTokens()) {
301 point.x = atof(shapeTokenizer.nextToken());
302 if ((tok = shapeTokenizer.nextToken()) ==
nullptr)
303 throw cRuntimeError(
"Missing polyhedron y at %s", element->getSourceLocation());
305 if ((tok = shapeTokenizer.nextToken()) ==
nullptr)
306 throw cRuntimeError(
"Missing polyhedron z at %s", element->getSourceLocation());
308 points.push_back(point);
310 if (points.size() < 4)
311 throw cRuntimeError(
"polyhedron needs at least four points at %s", element->getSourceLocation());
314 shape =
new Polyhedron(points);
318 int id = atoi(shapeAttribute);
322 throw cRuntimeError(
"Unknown shape '%s'", shapeAttribute);
325 const char *positionAttribute = element->getAttribute(
"position");
326 if (positionAttribute) {
327 cStringTokenizer tokenizer(positionAttribute);
328 const char *
kind = tokenizer.nextToken();
330 throw cRuntimeError(
"Missing position kind");
331 if ((tok = tokenizer.nextToken()) ==
nullptr)
332 throw cRuntimeError(
"Missing position x at %s", element->getSourceLocation());
333 position.x = atof(tok);
334 if ((tok = tokenizer.nextToken()) ==
nullptr)
335 throw cRuntimeError(
"Missing position y at %s", element->getSourceLocation());
336 position.y = atof(tok);
337 if ((tok = tokenizer.nextToken()) ==
nullptr)
338 throw cRuntimeError(
"Missing position z at %s", element->getSourceLocation());
339 position.z = atof(tok);
340 if (!strcmp(
kind,
"min"))
341 position += size / 2;
342 else if (!strcmp(
kind,
"max"))
343 position -= size / 2;
344 else if (!strcmp(
kind,
"center"))
347 throw cRuntimeError(
"Unknown position kind");
350 position.
x = convertedPosition.x;
351 position.y = convertedPosition.y;
355 const Material *material;
356 const char *materialAttribute = element->getAttribute(
"material");
357 if (!materialAttribute)
358 throw cRuntimeError(
"Missing material attribute of object");
366 throw cRuntimeError(
"Unknown material '%s'", materialAttribute);
368 double lineWidth = 1;
369 const char *lineWidthAttribute = element->getAttribute(
"line-width");
370 if (lineWidthAttribute)
371 lineWidth = atof(lineWidthAttribute);
374 const char *lineColorAttribute = element->getAttribute(
"line-color");
375 if (lineColorAttribute) {
376 if (strchr(lineColorAttribute,
' ')) {
377 cStringTokenizer tokenizer(lineColorAttribute);
378 if ((tok = tokenizer.nextToken()) ==
nullptr)
379 throw cRuntimeError(
"Missing line-color red at %s", element->getSourceLocation());
380 lineColor.red = atoi(tok);
381 if ((tok = tokenizer.nextToken()) ==
nullptr)
382 throw cRuntimeError(
"Missing line-color green at %s", element->getSourceLocation());
383 lineColor.green = atoi(tok);
384 if ((tok = tokenizer.nextToken()) ==
nullptr)
385 throw cRuntimeError(
"Missing line-color blue at %s", element->getSourceLocation());
386 lineColor.blue = atoi(tok);
393 const char *fillColorAttribute = element->getAttribute(
"fill-color");
394 if (fillColorAttribute) {
395 if (strchr(fillColorAttribute,
' ')) {
396 cStringTokenizer tokenizer(fillColorAttribute);
397 if ((tok = tokenizer.nextToken()) ==
nullptr)
398 throw cRuntimeError(
"Missing fill-color red at %s", element->getSourceLocation());
399 fillColor.red = atoi(tok);
400 if ((tok = tokenizer.nextToken()) ==
nullptr)
401 throw cRuntimeError(
"Missing fill-color green at %s", element->getSourceLocation());
402 fillColor.green = atoi(tok);
403 if ((tok = tokenizer.nextToken()) ==
nullptr)
404 throw cRuntimeError(
"Missing fill-color blue at %s", element->getSourceLocation());
405 fillColor.blue = atoi(tok);
412 const char *opacityAttribute = element->getAttribute(
"opacity");
413 if (opacityAttribute)
414 opacity = atof(opacityAttribute);
416 const char *texture = element->getAttribute(
"texture");
418 const char *
tags = element->getAttribute(
"tags");
420 PhysicalObject *
object =
new PhysicalObject(name,
id, position, orientation, shape, material, lineWidth, lineColor, fillColor, opacity, texture,
tags);
423 idToObjectMap.insert(std::pair<int, const PhysicalObject *>(
id,
object));
424 const Coord
min = position - size / 2;
425 const Coord
max = position + size / 2;
429 throw cRuntimeError(
"Object is outside of space limits");
430 if (std::isnan(computedSpaceMin.x) ||
min.x < computedSpaceMin.x) computedSpaceMin.x =
min.x;
431 if (std::isnan(computedSpaceMin.y) ||
min.y < computedSpaceMin.y) computedSpaceMin.y =
min.y;
432 if (std::isnan(computedSpaceMin.z) ||
min.z < computedSpaceMin.z) computedSpaceMin.z =
min.z;
433 if (std::isnan(computedSpaceMax.x) ||
max.x > computedSpaceMax.x) computedSpaceMax.x =
max.x;
434 if (std::isnan(computedSpaceMax.y) ||
max.y > computedSpaceMax.y) computedSpaceMax.y =
max.y;
435 if (std::isnan(computedSpaceMax.z) ||
max.z > computedSpaceMax.z) computedSpaceMax.z =
max.z;