00001 #ifndef OPENTISSUE_DYNAMICS_EDM_IO_EDM_SYSTEM_XML_READ_H
00002 #define OPENTISSUE_DYNAMICS_EDM_IO_EDM_SYSTEM_XML_READ_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/edm/edm.h>
00013
00014 #include <TinyXML/tinyxml.h>
00015
00016 #include <string>
00017 #include <fstream>
00018 #include <sstream>
00019
00020
00021 namespace OpenTissue
00022 {
00023
00024 namespace edm
00025 {
00026
00027 namespace xml
00028 {
00029
00030
00031
00032 template<typename T>
00033 inline Vector3<T> & operator<<(Vector3<T> & to, std::string const & from)
00034 {
00035 std::istringstream ist(from);
00036 char dummy;
00037 ist >> dummy >> to(0) >> dummy >> to(1) >> dummy >> to(2) >> dummy;
00038 return to;
00039 }
00040
00041 template<typename T>
00042 inline Vector3<T> & operator<<(Vector3<T> & to,Vector3<T> const &from)
00043 {
00044 to = from;
00045 return to;
00046 }
00047
00048
00049 template<typename T>
00050 inline Vector3<T> const & operator>>(Vector3<T> const & from, std::string & to)
00051 {
00052 std::ostringstream ost;
00053 ost << "[" << from(0) << "," << from(1) << "," << from(2) << "]" << std::endl;
00054 to = ost.str();
00055 return from;
00056 }
00057
00058
00059 template<typename T>
00060 inline Vector3<T> const & operator>>(Vector3<T> const & from,Vector3<T> & to)
00061 {
00062 to = from;
00063 return from;
00064 }
00065
00066 inline bool error(std::string const &err)
00067 {
00068 std::cerr << "EDM ERROR: " << err << std::endl;
00069 return false;
00070 }
00071
00072 template<typename real_type>
00073 inline bool get_value_real(real_type& val, TiXmlElement const & elem, std::string const & att)
00074 {
00075 char const * attr = elem.Attribute(att);
00076 if (!attr) return false;
00077 std::istringstream ist(attr);
00078 ist >> val;
00079 return true;
00080 }
00081
00082 template<typename tensor2_type>
00083 inline bool get_value_tensor2(tensor2_type& val, TiXmlElement const & elem, std::string const & att)
00084 {
00085 char const * attr = elem.Attribute(att);
00086 if (!attr)
00087 return false;
00088 std::istringstream ist(attr);
00089 typename tensor2_type::value_type tmp;
00090 char dummy;
00091 ist >> dummy >> dummy >> tmp;
00092 val.t0[0] = tmp;
00093 ist >> dummy >> tmp;
00094 val.t0[1] = tmp;
00095 ist >> dummy >> dummy >> dummy >> tmp;
00096 val.t1[0] = tmp;
00097 ist >> dummy >> tmp;
00098 val.t1[1] = tmp;
00099 return true;
00100 }
00101
00102 template<typename tensor3_type>
00103 inline bool get_value_tensor3(tensor3_type& val, TiXmlElement const & elem, std::string const & att)
00104 {
00105 const char* attr = elem.Attribute(att);
00106 if (!attr) return false;
00107 std::istringstream ist(attr);
00108 typename tensor3_type::value_type tmp;
00109 char dummy;
00110 ist >> dummy >> dummy >> tmp;
00111 val.t0[0] = tmp;
00112 ist >> dummy >> tmp;
00113 val.t0[1] = tmp;
00114 ist >> dummy >> tmp;
00115 val.t0[2] = tmp;
00116 ist >> dummy >> dummy >> dummy >> tmp;
00117 val.t1[0] = tmp;
00118 ist >> dummy >> tmp;
00119 val.t1[1] = tmp;
00120 ist >> dummy >> tmp;
00121 val.t1[2] = tmp;
00122 ist >> dummy >> dummy >> dummy >> tmp;
00123 val.t2[0] = tmp;
00124 ist >> dummy >> tmp;
00125 val.t2[1] = tmp;
00126 ist >> dummy >> tmp;
00127 val.t2[2] = tmp;
00128 return true;
00129 }
00130
00131 inline bool get_value_compare(bool& val, TiXmlElement const & elem, std::string const & att, std::string const & cmp)
00132 {
00133 char const * attr = elem.Attribute(att);
00134 if (!attr) return false;
00135 val = cmp == attr;
00136 return true;
00137 }
00138
00139
00140
00141 template<typename ulong_type>
00142 inline void get_correct_index(ulong_type& idx, std::istringstream& ist)
00143 {
00144 char tst = static_cast<char>(ist.peek());
00145 if ('[' == tst)
00146 ist >> tst;
00147 ist >> idx;
00148 }
00149
00150 template<typename edm_system_type>
00151 inline bool create_surface(edm_system_type& system, TiXmlNode const & surface_node, std::string const & type, std::string const & id)
00152 {
00153 typedef typename edm_system_type::EDM_TYPES edm_types;
00154 typedef Surface<edm_types> surface_type;
00155 typedef GenericBezierPatch<edm_types> generic_bezier_patch_type;
00156 typedef QuadraticBezierPatch<edm_types> quadratic_bezier_patch_type;
00157 typedef EllipsoidPatch<edm_types> ellipsoid_patch_type;
00158 typedef typename Surface::SurfaceParticle SurfaceParticle;
00159
00160 const TiXmlElement* properties = surface_node.FirstChildElement("Properties");
00161
00162 if (!properties)
00163 return error("'Body' force requieres a 'Properties' child node!");
00164
00165 const char* timestep = properties->Attribute("timestep");
00166 if (!timestep)
00167 return error("A 'Body' object's 'Properties' node must have the delta t 'timestep' attribute!");
00168 typename Surface::real_type dt;
00169 std::istringstream ist1(timestep);
00170 ist1 >> dt;
00171
00172 bool wrap_m = false;
00173 const char* mcont = properties->Attribute("mcont");
00174 if (mcont)
00175 wrap_m = std::string("Yes") == mcont;
00176
00177 bool wrap_n = false;
00178 const char* ncont = properties->Attribute("ncont");
00179 if (ncont)
00180 wrap_n = std::string("Yes") == ncont;
00181
00182 const TiXmlNode* rest = surface_node.FirstChild("NaturalShape");
00183 if (!(rest && rest == surface_node.LastChild("NaturalShape")))
00184 return error("One and exactly one 'NaturalShape' node must exist within a 'Body' node!");
00185
00186 const TiXmlNode* InitialShapes = surface_node.FirstChild("InitialShape");
00187 if (InitialShapes && InitialShapes != surface_node.LastChild("InitialShape"))
00188 return error("Only one 'InitialShape' node can exist within a 'Body' node!");
00189
00190 const TiXmlNode* particles = surface_node.FirstChild("Particles");
00191 if (!(particles && particles == surface_node.LastChild("Particles")))
00192 return error("One and exactly one 'Particles' node must exist within a 'Body' node!");
00193
00194
00195 if ("GenericBezierPatch" == type)
00196 {
00197 const char* Order = properties->Attribute("order");
00198 if (!Order)
00199 return error("The 'Properties' node of a concrete 'GenericBezierPatch' model must have the 'order' attribute!");
00200 size_t order;
00201 std::istringstream ist(Order);
00202 ist >> order;
00203 system.template create_model< generic_bezier_patch_type >(id)->set(order);
00204 }
00205
00206
00207 else if ("QuadraticBezierPatch" == type)
00208 system.template create_model< quadratic_bezier_patch_type >(id);
00209
00210 else if ("Ellipsoid" == type)
00211 system.template create_model< ellipsoid_patch_type >(id);
00212
00213
00214 else error("Deformable Surface type '"+type+"' not supported!");
00215
00216 surface_type * surface = static_cast<surface_type*>(system.models().find(id)->second);
00217
00218
00219 {
00220 const TiXmlNode* Nodes = rest->FirstChild("Node");
00221 size_t n = 0;
00222 for (; Nodes; Nodes = Nodes->NextSibling("Node"), ++n)
00223 {
00224 const TiXmlElement& Node = *Nodes->ToElement();
00225 const char* index = Node.Attribute("index");
00226 if (!index)
00227 return error("All 'NaturalShape' child nodes must have the 'index' attribute!");
00228 std::istringstream ist(index);
00229 size_t idx;
00230 get_correct_index(idx, ist);
00231 if (idx >= surface->nodes())
00232 {
00233 std::ostringstream ost;
00234 ost << "Index " << idx << " outta bounds for 'Node' no. " << n+1 << ".\n" <<
00235 "Index range for this Surface is [0.." << surface->nodes()-1 <<"]";
00236 return error(ost.str());
00237 }
00238
00239 const char* pos = Node.Attribute("pos");
00240 if (pos)
00241 {
00242 typename surface_type::vector3_type r;
00243 r << pos;
00244 surface->set_natural_position(idx,r);
00245 if (!InitialShapes)
00246 surface->set_initial_position(idx,r);
00247 }
00248 }
00249 }
00250
00251
00252 if (InitialShapes)
00253 {
00254 const TiXmlElement& init = *InitialShapes->ToElement();
00255 size_t n = 0;
00256 const TiXmlNode* Nodes = init.FirstChild("Node");
00257 for (; Nodes; Nodes = Nodes->NextSibling("Node"), ++n)
00258 {
00259 const TiXmlElement& Node = *Nodes->ToElement();
00260 const char* index = Node.Attribute("index");
00261 if (!index)
00262 return error("All 'InitialShape' child nodes must have the 'index' attribute!");
00263 std::istringstream ist(index);
00264 size_t idx;
00265 get_correct_index(idx, ist);
00266 if (idx >= surface->nodes()) {
00267 std::ostringstream ost;
00268 ost << "Index " << idx << " outta bounds for 'Node' no. " << n+1 << ".\n" <<
00269 "Index range for this Surface is [0.." << surface->nodes()-1 <<"]";
00270 return error(ost.str());
00271 }
00272
00273 const char* pos = Node.Attribute("pos");
00274 if (pos) {
00275 typename surface_type::vector3_type r;
00276 r << pos;
00277 surface->set_initial_position(idx,r);
00278 }
00279 }
00280 }
00281
00282
00283 char const * grid = particles->ToElement()->Attribute("grid");
00284 if (!grid)
00285 return error("A 'Body' object's 'Particles' node must have the 'grid' attribute!");
00286 std::istringstream ist(grid);
00287 size_t M,N;
00288 char dummy;
00289 ist >> dummy >> M >> dummy >> N >> dummy;
00290
00291 surface->wrapping(wrap_m,wrap_n);
00292 if (!surface->initialize(M,N))
00293 return error("Deformable Surface "+type+" failed the initialization!");
00294
00295
00296 const TiXmlElement* all = particles->FirstChildElement("All");
00297 if (all)
00298 {
00299 SurfaceParticle const M_default;
00300
00301 typename surface_type::real_type tmp1;
00302 bool tmp2;
00303 typename surface_type::tensor2_type tmp3;
00304
00305 typename surface_type::real_type const mass = get_value_real(tmp1, *all, "mass") ? tmp1 : M_default.m;
00306 typename surface_type::real_type const damping = get_value_real(tmp1, *all, "damping") ? tmp1 : M_default.g;
00307 typename surface_type::tensor2_type const tension = get_value_tensor2(tmp3, *all, "tension") ? tmp3 : M_default.e;
00308 typename surface_type::tensor2_type const rigidity = get_value_tensor2(tmp3, *all, "rigidity") ? tmp3 : M_default.x;
00309 bool const fixed = get_value_compare(tmp2, *all, "fixed", "Yes") ? tmp2 : M_default.f;
00310
00311 for (size_t n = 0; n < N; ++n)
00312 for (size_t m = 0; m < M; ++m)
00313 surface->set_mass(m,n,mass).set_damping(m,n,damping).set_tension(m,n,tension).set_rigidity(m,n,rigidity).set_fixed(m,n,fixed);
00314 }
00315
00316 const TiXmlNode* Singles = particles->FirstChild("Single");
00317 for (; Singles; Singles = Singles->NextSibling("Single"))
00318 {
00319 const TiXmlElement& Single = *Singles->ToElement();
00320 const char* par = Single.Attribute("particle");
00321 if (!par)
00322 return error("A 'Single' child node must have the 'particle' attribute!");
00323 std::istringstream ist2(par);
00324 size_t m, n;
00325 char dummy2;
00326 ist2 >> dummy2 >> m >> dummy2 >> n >> dummy2;
00327
00328 if (m>=M||n>=N)
00329 {
00330 std::ostringstream ost;
00331 ost << "Particle [" << m << "," << n << "] is outta bounds in 'Single' node";
00332 return error(ost.str());
00333 }
00334
00335 typename surface_type::real_type tmp1;
00336 bool tmp2;
00337 typename surface_type::tensor2_type tmp3;
00338
00339 if (get_value_real(tmp1, Single, "mass"))
00340 surface->set_mass(m,n,tmp1);
00341 if (get_value_real(tmp1, Single, "damping"))
00342 surface->set_damping(m,n,tmp1);
00343 if (get_value_tensor2(tmp3, Single, "tension"))
00344 surface->set_tension(m,n,tmp3);
00345 if (get_value_tensor2(tmp3, Single, "rigidity"))
00346 surface->set_rigidity(m,n,tmp3);
00347 if (get_value_compare(tmp2, Single, "fixed", "Yes"))
00348 surface->set_fixed(m,n,tmp2);
00349 }
00350
00351 surface->timestep() = dt;
00352
00353 return true;
00354 }
00355
00356 template <typename edm_system_type>
00357 inline bool create_solid(edm_system_type& system, TiXmlNode const & solid_node, std::string const & type, std::string const & id)
00358 {
00359 typedef typename edm_system_type::EDM_TYPES edm_types;
00360 typedef Solid<edm_types> solid_type;
00361 typedef GenericBezierSolid<edm_types> generic_bezier_solid_type;
00362 typedef LinearBezierSolid<edm_types> linear_bezier_solid_type;
00363 typedef EllipsoidSolid<edm_types> ellipsoid_solid_type;
00364 typedef typename Solid::SolidParticle SolidParticle;
00365
00366 const TiXmlElement* properties = solid_node.FirstChildElement("Properties");
00367
00368 if (!properties)
00369 return error("'Body' force requieres a 'Properties' child node!");
00370
00371 const char* timestep = properties->Attribute("timestep");
00372 if (!timestep)
00373 return error("A 'Body' object's 'Properties' node must have the delta t 'timestep' attribute!");
00374 typename Solid::real_type dt;
00375 std::istringstream ist1(timestep);
00376 ist1 >> dt;
00377
00378 bool wrap_l = false;
00379 const char* lcont = properties->Attribute("lcont");
00380 if (lcont)
00381 wrap_l = std::string("Yes") == lcont;
00382
00383 bool wrap_m = false;
00384 const char* mcont = properties->Attribute("mcont");
00385 if (mcont)
00386 wrap_m = std::string("Yes") == mcont;
00387
00388 bool wrap_n = false;
00389 const char* ncont = properties->Attribute("ncont");
00390 if (ncont)
00391 wrap_n = std::string("Yes") == ncont;
00392
00393 const TiXmlNode* rest = solid_node.FirstChild("NaturalShape");
00394 if (!(rest && rest == solid_node.LastChild("NaturalShape")))
00395 return error("One and exactly one 'NaturalShape' node must exist within a 'Body' node!");
00396
00397 const TiXmlNode* InitialShapes = solid_node.FirstChild("InitialShape");
00398 if (InitialShapes && InitialShapes != solid_node.LastChild("InitialShape"))
00399 return error("Only one 'InitialShape' node can exist within a 'Body' node!");
00400
00401 const TiXmlNode* particles = solid_node.FirstChild("Particles");
00402 if (!(particles && particles == solid_node.LastChild("Particles")))
00403 return error("One and exactly one 'Particles' node must exist within a 'Body' node!");
00404
00405
00406 if ("GenericBezierSolid" == type) {
00407 const char* Order = properties->Attribute("order");
00408 if (!Order)
00409 return error("The 'Properties' node of a concrete 'GenericBezierSolid' model must have the 'order' attribute!");
00410 size_t order;
00411 std::istringstream ist(Order);
00412 ist >> order;
00413 system.template create_model<generic_bezier_solid_type>(id)->set(order);
00414 }
00415
00416 else if ("LinearBezierSolid" == type)
00417 system.template create_model<linear_bezier_solid_type>(id);
00418
00419 else if ("Ellipsoid" == type)
00420 system.template create_model<ellipsoid_solid_type>(id);
00421
00422
00423 else return error("Deformable Solid type '"+type+" not supported!");
00424
00425 solid_type* solid = static_cast<solid_type*>(system.models().find(id)->second);
00426
00427
00428 {
00429 const TiXmlNode* Nodes = rest->FirstChild("Node");
00430 size_t n = 0;
00431 for (; Nodes; Nodes = Nodes->NextSibling("Node"), ++n)
00432 {
00433 const TiXmlElement& Node = *Nodes->ToElement();
00434 const char* index = Node.Attribute("index");
00435 if (!index)
00436 return error("All 'NaturalShape' child nodes must have the 'index' attribute!");
00437 std::istringstream ist(index);
00438 size_t idx;
00439 get_correct_index(idx, ist);
00440 if (idx >= solid->nodes())
00441 {
00442 std::ostringstream ost;
00443 ost << "Index " << idx << " outta bounds for 'Node' no. " << n+1 << ". " <<
00444 "Index range for this Solid is [0.." << solid->nodes()-1 <<"]!";
00445 return error(ost.str());
00446 }
00447
00448 char const * pos = Node.Attribute("pos");
00449 if (pos)
00450 {
00451 typename Solid::vector3_type r;
00452 r << pos;
00453 solid->set_natural_position(idx,r);
00454 if (!InitialShapes)
00455 solid->set_initial_position(idx,r);
00456 }
00457 }
00458 }
00459
00460
00461 if (InitialShapes)
00462 {
00463 TiXmlElement const & init = *InitialShapes->ToElement();
00464 size_t n = 0;
00465 const TiXmlNode* Nodes = init.FirstChild("Node");
00466 for (; Nodes; Nodes = Nodes->NextSibling("Node"), ++n)
00467 {
00468 TiXmlElement const & Node = *Nodes->ToElement();
00469 char const * index = Node.Attribute("index");
00470 if (!index)
00471 return error("All 'InitialShape' child nodes must have the 'index' attribute!");
00472 std::istringstream ist(index);
00473 size_t idx;
00474 get_correct_index(idx, ist);
00475 if (idx >= solid->nodes())
00476 {
00477 std::ostringstream ost;
00478 ost << "Index " << idx << " outta bounds for 'Node' no. " << n+1 << ". " <<
00479 "Index range for this Solid is [0.." << solid->nodes()-1 <<"]!";
00480 return error(ost.str());
00481 }
00482
00483 char const * pos = Node.Attribute("pos");
00484 if (pos)
00485 {
00486 typename solid_type::vector3_type r;
00487 r << pos;
00488 solid->set_initial_position(idx,r);
00489 }
00490 }
00491 }
00492
00493
00494 char const * grid = particles->ToElement()->Attribute("grid");
00495 if (!grid)
00496 return error("A 'Body' object's 'Particles' node must have the 'grid' attribute!");
00497 std::istringstream ist(grid);
00498 size_t L,M,N;
00499 char dummy;
00500 ist >> dummy >> L >> dummy >> M >> dummy >> N >> dummy;
00501
00502 solid->wrapping(wrap_l,wrap_m,wrap_n);
00503 if (!solid->initialize(L,M,N))
00504 return error("Deformable Solid "+type+" failed the initialization!");
00505
00506
00507 TiXmlElement const * all = particles->FirstChildElement("All");
00508 if (all)
00509 {
00510 SolidParticle const M_default;
00511
00512 typename solid_type::real_type tmp1;
00513 bool tmp2;
00514 typename solid_type::tensor3_type tmp3; typename solid_type::tensor2_type tmp4;
00515
00516 typename solid_type::real_type const mass = get_value_real(tmp1, *all, "mass") ? tmp1 : M_default.m;
00517 typename solid_type::real_type const damping = get_value_real(tmp1, *all, "damping") ? tmp1 : M_default.g;
00518 typename solid_type::tensor2_type const spatial = get_value_tensor2(tmp4, *all, "spatial") ? tmp4 : M_default.u;
00519 typename solid_type::tensor3_type const tension = get_value_tensor3(tmp3, *all, "tension") ? tmp3 : M_default.e;
00520 bool const fixed = get_value_compare(tmp2, *all, "fixed", "Yes") ? tmp2 : M_default.f;
00521
00522 for (size_t n = 0; n < N; ++n)
00523 for (size_t m = 0; m < M; ++m)
00524 for (size_t l = 0; l < L; ++l)
00525 solid->set_mass(l,m,n,mass).set_damping(l,m,n,damping).set_tension(l,m,n,tension).set_spatial(l,m,n,spatial).set_fixed(l,m,n,fixed);
00526 }
00527
00528 TiXmlNode const * Singles = particles->FirstChild("Single");
00529 for (; Singles; Singles = Singles->NextSibling("Single"))
00530 {
00531 TiXmlElement const & Single = *Singles->ToElement();
00532 char const * par = Single.Attribute("particle");
00533 if (!par)
00534 return error("A 'Single' child node must have the 'particle' attribute!");
00535 std::istringstream ist2(par);
00536 size_t l, m, n;
00537 char dummy2;
00538 ist2 >> dummy2 >> l >> dummy2 >> m >> dummy2 >> n >> dummy2;
00539
00540 if (l>=L||m>=M||n>=N)
00541 {
00542 std::ostringstream ost;
00543 ost << "Particle [" << l << "," << m << "," << n << "] is outta bounds in 'Single' node";
00544 return error(ost.str());
00545 }
00546
00547 typename solid_type::real_type tmp1;
00548 bool tmp2;
00549 typename solid_type::tensor3_type tmp3;
00550 typename solid_type::tensor2_type tmp4;
00551
00552 if (get_value_real(tmp1, Single, "mass"))
00553 solid->set_mass(l,m,n,tmp1);
00554 if (get_value_real(tmp1, Single, "damping"))
00555 solid->set_damping(l,m,n,tmp1);
00556 if (get_value_tensor3(tmp3, Single, "tension"))
00557 solid->set_tension(l,m,n,tmp3);
00558 if (get_value_tensor2(tmp4, Single, "spatial"))
00559 solid->set_spatial(l,m,n,tmp4);
00560 if (get_value_compare(tmp2, Single, "fixed", "Yes"))
00561 solid->set_fixed(l,m,n,tmp2);
00562 }
00563
00564 solid->timestep() = dt;
00565
00566 return true;
00567 }
00568
00569 template <typename edm_system_type>
00570 inline bool create_models(edm_system_type& system, TiXmlNode const & models_node)
00571 {
00572 typedef typename edm_system_type::EDM_TYPES edm_types;
00573 typedef typename edm_types::model_type model_type;
00574 typedef Surface<edm_types> surface_type;
00575 typedef Solid<edm_types> solid_type;
00576
00577 typedef typename edm_system_type::EDMIOMaterials EDMIOMaterials;
00578 typedef typename edm_system_type::EDMIOForces EDMIOForces;
00579 typedef typename edm_system_type::EDMIOObjects EDMIOObjects;
00580
00581 EDMIOMaterials const & materials = system.materials();
00582 EDMIOForces const & forces = system.forces();
00583 EDMIOObjects const & objects = system.objects();
00584
00585 TiXmlNode const * Bodies = models_node.FirstChild("Body");
00586 for (; Bodies; Bodies = Bodies->NextSibling("Body"))
00587 {
00588 TiXmlElement const & body = *Bodies->ToElement();
00589 std::string val;
00590
00591 char const * id = body.Attribute("id");
00592 if (!id)
00593 return error("'Body' node must have an 'id' attribute!");
00594 val = id;
00595 if (system.models().find(val) != system.models().end())
00596 return error("Deformable Body with id = '"+val+"' already exist!");
00597
00598 char const * type = body.Attribute("type");
00599 if (!type)
00600 return error("'Body' node must have a 'type' attribute!");
00601
00602 char const * model = body.Attribute("model");
00603 if (!model)
00604 return error("'Body' node must have a 'model' attribute!");
00605 val = model;
00606
00607
00608 if ("Curve" == val)
00609 return error("A deformable body model of type '"+val+"' is not (yet) supported!");
00610
00611
00612 else if ("Surface" == val) {
00613 if (!create_surface(system, body, type, id))
00614 return false;
00615 }
00616
00617
00618 else if ("Solid" == val) {
00619 if (!create_solid(system, body, type, id))
00620 return false;
00621 }
00622
00623
00624 else return error("'model' attribute value '"+val+" not recognized in node 'Body'");
00625
00626
00627 model_type * deform = system.models().find(id)->second;
00628
00629
00630 TiXmlNode* const bindings = body.FirstChild("Bind");
00631 for (; bindings; bindings = bindings->NextSibling("Bind"))
00632 {
00633 TiXmlElement const & bind = *bindings->ToElement();
00634 std::string val2;
00635
00636 char const * type2 = bind.Attribute("type");
00637 if (!type2)
00638 return error("Mandatory attribute 'type' not found!");
00639 val2 = type2;
00640 if ("Collision" != val2 && "Force" != val2 && "Material" != val2)
00641 return error("'type' attribute value '"+val2+"' not recognized in node 'Bind'");
00642
00643 char const * ref = bind.Attribute("ref");
00644 if (!ref)
00645 return error("Mandatory attribute 'ref' not found!");
00646 val2 = ref;
00647 typename EDMIOObjects::const_iterator obj_itor = objects.find(val2);
00648 typename EDMIOForces::const_iterator force_itor = forces.find(val2);
00649 typename EDMIOMaterials::const_iterator mat_itor = materials.find(val2);
00650 char const * par = bind.Attribute("particle");
00651
00652
00653 if (std::string("Material") == type2)
00654 if (mat_itor == materials.end())
00655 return error("Material with id = '"+val2+"' does not exist!");
00656 else
00657 deform->add(*mat_itor->second);
00658 else if (std::string("Collision") == type2)
00659 if (obj_itor == objects.end())
00660 return error("Rigid Object with id = '"+val2+"' does not exist!");
00661 else
00662 deform->add(*obj_itor->second);
00663 else
00664 if (force_itor == forces.end())
00665 return error("External Force with id = '"+val2+"' does not exist!");
00666 else if (!par)
00667 deform->add(*force_itor->second);
00668 else {
00669 std::istringstream ist(par);
00670 size_t a1, a2, a3;
00671 char dummy;
00672 ist >> dummy >> a1 >> dummy >> a2 >> dummy >> a3 >> dummy;
00673 switch (deform->type())
00674 {
00675 case edm_types::EDM_Surface:
00676 deform->add(static_cast<surface_type*>(deform)->particle(a1,a2), *force_itor->second);
00677 break;
00678 case edm_types::EDM_Solid:
00679 deform->add(static_cast<solid_type*>(deform)->particle(a1,a2,a3), *force_itor->second);
00680 break;
00681 }
00682 }
00683 }
00684 }
00685
00686 return true;
00687 }
00688
00689 template <typename edm_system>
00690 inline bool create_objects(edm_system & system, TiXmlNode const & objects_node)
00691 {
00692 typedef typename edm_system::edm_types::object_type object_type;
00693 typedef EDMPlane<typename edm_system::edm_types> EDMPlane;
00694 typedef EDMSphere<typename edm_system::edm_types> EDMSphere;
00695 typedef EDMTorus<typename edm_system::edm_types> EDMTorus;
00696 typedef EDMCylinder<typename edm_system::edm_types> EDMCylinder;
00697
00698 TiXmlNode const * Objects = objects_node.FirstChild("Object");
00699 for (; Objects; Objects = Objects->NextSibling("Object"))
00700 {
00701 TiXmlElement const & object = *Objects->ToElement();
00702 std::string val;
00703
00704 char const * id = object.Attribute("id");
00705 if (!id)
00706 return error("'Object' node must have an 'id' attribute!");
00707 val = id;
00708 if (system.objects().find(val) != system.objects().end())
00709 return error("Rigid Object with id = '"+val+"' already exist!");
00710
00711 char const * type = object.Attribute("type");
00712 if (!type)
00713 return error("'Object' node must have an 'type' attribute!");
00714 val = type;
00715
00716 TiXmlElement const * properties = object.FirstChildElement("Properties");
00717
00718
00719 if ("Plane" == val)
00720 {
00721 if (!properties)
00722 return error("'Plane' object requieres a 'Properties' child node!");
00723 char const * X0 = properties->Attribute("x0");
00724 if (!X0)
00725 return error("A 'Plane' object's 'Properties' node must have the fixed point 'x0' attribute!");
00726 val = X0;
00727 typename EDMPlane::vector3_type x0;
00728 x0 << val;
00729
00730 char const * N = properties->Attribute("n");
00731 if (!N)
00732 return error("A 'Plane' object's 'Properties' node must have the plane normal 'n' attribute!");
00733 val = N;
00734 typename EDMPlane::vector3_type n;
00735 n << val;
00736
00737 system.template create_object<EDMPlane>(id)->set(x0,n);
00738 }
00739
00740
00741 else if ("Sphere" == val)
00742 {
00743 if (!properties)
00744 return error("'Sphere' object requieres a 'Properties' child node!");
00745 char const * R = properties->Attribute("r");
00746 if (!R)
00747 return error("A 'Sphere' object's 'Properties' node must have the radius 'r' attribute!");
00748 typename EDMSphere::real_type r;
00749 std::istringstream ist(R);
00750 ist >> r;
00751
00752 char const * C = properties->Attribute("c");
00753 if (!C)
00754 return error("A 'Sphere' object's 'Properties' node must have the fixed center 'c' attribute!");
00755 val = C;
00756 typename EDMSphere::vector3_type c;
00757 c << val;
00758
00759 system.template create_object<EDMSphere>(id)->set(r,c);
00760 }
00761
00762
00763 else if ("Torus" == val)
00764 {
00765 if (!properties)
00766 return error("'Torus' object requieres a 'Properties' child node!");
00767
00768 char const * A = properties->Attribute("a");
00769 if (!A)
00770 return error("A 'Torus' object's 'Properties' node must have the torus tupe radius 'a' attribute!");
00771 typename EDMTorus::real_type a;
00772 std::istringstream ist1(A);
00773 ist1 >> a;
00774
00775 char const * R = properties->Attribute("r");
00776 if (!R)
00777 return error("A 'Torus' object's 'Properties' node must have the hole radius 'r' attribute!");
00778 typename EDMTorus::real_type r;
00779 std::istringstream ist2(R);
00780 ist2 >> r;
00781
00782 char const * C = properties->Attribute("c");
00783 if (!C)
00784 return error("A 'Torus' object's 'Properties' node must have the torus center 'c' attribute!");
00785 val = C;
00786 typename EDMTorus::vector3_type c;
00787 c << val;
00788
00789 system.template create_object<EDMTorus>(id)->set(a,r,c);
00790 }
00791
00792
00793 else if ("Cylinder" == val)
00794 {
00795 if (!properties)
00796 return error("'Cylinder' object requieres a 'Properties' child node!");
00797
00798 char const * R = properties->Attribute("r");
00799 if (!R)
00800 return error("A 'Cylinder' object's 'Properties' node must have the cylinder radius 'r' attribute!");
00801 typename EDMCylinder::real_type r;
00802 std::istringstream ist1(R);
00803 ist1 >> r;
00804
00805 char const * H = properties->Attribute("h");
00806 if (!H)
00807 return error("A 'Cylinder' object's 'Properties' node must have the height (length) 'h' attribute!");
00808 typename EDMCylinder::real_type h;
00809 std::istringstream ist2(H);
00810 ist2 >> h;
00811
00812 char const * C = properties->Attribute("c");
00813 if (!C)
00814 return error("A 'Cylinder' object's 'Properties' node must have the center 'c' attribute!");
00815 val = C;
00816 typename EDMCylinder::vector3_type c;
00817 c << val;
00818
00819 system.template create_object<EDMCylinder>(id)->set(c,r,r,h);
00820 }
00821
00822
00823 else return error("'type' attribute value '"+val+"' not recognized in node 'Object'");
00824
00825
00826 object_type * obj = system.objects().find(id)->second;
00827
00828 char const * visible = object.Attribute("visible");
00829 if (visible)
00830 obj->set_visibility(std::string("Yes") == visible);
00831
00832 char const * E = object.Attribute("epsilon");
00833 if (E)
00834 {
00835 std::istringstream ist(E);
00836 typename Object::real_type e;
00837 ist >> e;
00838 obj->set_epsilon(e);
00839 }
00840
00841 char const * Scale = object.Attribute("scale");
00842 if (Scale)
00843 {
00844 std::istringstream ist(Scale);
00845 typename Object::real_type scale;
00846 ist >> scale;
00847 obj->set_scale(scale);
00848 }
00849
00850
00851 TiXmlNode const * bindings = object.FirstChild("Bind");
00852 if (bindings)
00853 {
00854 TiXmlElement const & bind = *bindings->ToElement();
00855 std::string val2;
00856
00857 char const * type2 = bind.Attribute("type");
00858 if (!type2)
00859 return error("Mandatory attribute 'type' not found for 'Bind' node!");
00860 if (std::string("Material") != type2)
00861 return error("Only 'Material' bindings are supported for objects");
00862
00863
00864 char const * ref = bind.Attribute("ref");
00865 if (!ref)
00866 return error("Mandatory attribute 'ref' not found!");
00867 val2 = ref;
00868 typename edm_system_type::EDMIOMaterials::const_iterator mat_itor = system.materials().find(val2);
00869 if (mat_itor == system.materials().end())
00870 return error("Material with id = '"+val2+"' does not exist!");
00871 else
00872 obj->set_material(*mat_itor->second);
00873 }
00874 }
00875
00876 return true;
00877 }
00878
00879 template<typename edm_system>
00880 inline bool create_forces(edm_system & system, TiXmlNode const & forces_node)
00881 {
00882 typedef Gravity<typename edm_system::edm_types> gravity_type;
00883 typedef Viscous<typename edm_system::edm_types> viscous_type;
00884 typedef Spring<typename edm_system::edm_types> spring_type;
00885
00886 TiXmlNode const * Forces = forces_node.FirstChild("Force");
00887 for (; Forces; Forces = Forces->NextSibling("Force"))
00888 {
00889 TiXmlElement const & force = *Forces->ToElement();
00890 std::string val;
00891
00892 char const * id = force.Attribute("id");
00893 if (!id)
00894 return error("'Force' node must have an 'id' attribute!");
00895 val = id;
00896 if (system.forces().find(val) != system.forces().end())
00897 return error("External Force with id = '"+val+"' already exist!");
00898
00899 char const * type = force.Attribute("type");
00900 if (!type)
00901 return error("'Force' node must have a 'type' attribute!");
00902 val = type;
00903
00904 TiXmlElemen const t* properties = force.FirstChildElement("Properties");
00905
00906
00907 if ("Gravity" == val)
00908 {
00909 if (!properties)
00910 return error("'Gravity' force requieres a 'Properties' child node!");
00911 char const * G = properties->Attribute("g");
00912 if (!G)
00913 return error("A 'Gravity' force's 'Properties' node must have the gravitationsl field 'g' attribute!");
00914 val = G;
00915 typename gravity_type::vector3_type g;
00916 g << val;
00917 system.template create_force<gravity_type>(id)->set(g);
00918 }
00919
00920
00921 else if ("Viscous" == val)
00922 {
00923 if (!properties)
00924 return error("'Viscous' force requieres a 'Properties' child node!");
00925 char const * C = properties->Attribute("c");
00926 if (!C)
00927 return error("A 'Viscous' force's 'Properties' node must have the fluid strength 'c' attribute!");
00928 typename viscous_type::real_type c;
00929 std::istringstream ist(C);
00930 ist >> c;
00931 char const * U = properties->Attribute("u");
00932 if (!U)
00933 return error("A 'Viscous' force's 'Properties' node must have the constant stream velocity 'u' attribute!");
00934 val = U;
00935 typename viscous_type::vector3_type u;
00936 u << val;
00937 system.template create_force<viscous_type>(id)->set(c,u);
00938 }
00939
00940
00941 else if ("Spring" == val)
00942 {
00943 if (!properties)
00944 return error("'Spring' force requieres a 'Properties' child node!");
00945 char const * K = properties->Attribute("k");
00946 if (!K)
00947 return error("A 'Spring' force's 'Properties' node must have the spring constant 'k' attribute!");
00948 typename Spring::real_type k;
00949 std::istringstream ist(K);
00950 ist >> k;
00951 char const * R0 = properties->Attribute("r0");
00952 if (!R0)
00953 return error("A 'Spring' force's 'Properties' node must have the fixed world point 'r0' attribute!");
00954 val = R0;
00955 typename Spring::vector3_type r0;
00956 r0 << val;
00957 system.template create_force<spring_type>(id)->set(k,r0);
00958 }
00959
00960
00961 else return error("'type' attribute value '"+val+"' not recognized in node 'Force'");
00962 }
00963
00964 return true;
00965 }
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031 template<typename edm_system>
01032 inline bool create_system(edm_system & system, TiXmlNode const & root_node)
01033 {
01034 TiXmlNode const * EDMConfig = root_node.FirstChild("EDMConfig");
01035 if (!(EDMConfig && EDMConfig == root_node.LastChild("EDMConfig")))
01036 return error("One and exactly one 'EDMConfig' node must exist!");
01037
01039
01040
01041
01042
01043
01044
01045
01046 TiXmlNode const * ForceContainer = EDMConfig->FirstChild("ExternalForces");
01047 if (!(ForceContainer && ForceContainer == EDMConfig->LastChild("ExternalForces")))
01048 return error("One and exactly one 'ExternalForces' node must exist!");
01049 if (!create_forces(system, *ForceContainer))
01050 return false;
01051
01052
01053 TiXmlNode const * ObjectContainer = EDMConfig->FirstChild("RigidObjects");
01054 if (!(ObjectContainer && ObjectContainer == EDMConfig->LastChild("RigidObjects")))
01055 return error("One and exactly one 'RigidObjects' node must exist!");
01056 if (!create_objects(system, *ObjectContainer))
01057 return false;
01058
01059
01060 TiXmlNode const * ModelContainer = EDMConfig->FirstChild("DeformableBodies");
01061 if (!(ModelContainer && ModelContainer == EDMConfig->LastChild("DeformableBodies")))
01062 return error("One and exactly one 'DeformableBodies' node must exist!");
01063 if (!create_models(system, *ModelContainer))
01064 return false;
01065
01066 return true;
01067 }
01068
01069 }
01070
01071
01072 template<typename edm_system>
01073 inline bool edm_system_xml_read(edm_system & system, std::string const & filename)
01074 {
01075 std::ifstream in(filename.c_str(), std::ios::binary);
01076 if (!in)
01077 return xml::error("file \"" + filename + "\" not found!");
01078 unsigned long len = in.seekg(0, std::ios::end).tellg();
01079 if (!len)
01080 return xml::error("file has no data!");
01081 char *data = new char[len+1];
01082 data[len]=0;
01083 in.seekg(0).read(data, len);
01084 in.close();
01085 std::string xml = data;
01086 delete[] data;
01087
01088 TiXmlDocument doc;
01089 doc.Parse(xml.c_str());
01090 if (doc.Error())
01091 return xml::error(doc.ErrorDesc());
01092 if (!xml::create_system(system, doc))
01093 return false;
01094
01095 return true;
01096 }
01097
01098 }
01099
01100 }
01101
01102
01103 #endif