Virtual Testbed
Ship dynamics simulator for extreme conditions
guile/ship.cc
1 #include <vtestbed/config/real_type.hh>
2 #include <vtestbed/core/ship.hh>
3 #include <vtestbed/guile/macros.hh>
4 #include <vtestbed/guile/traits.hh>
5 
14 
15 namespace {
16  SCM type;
17  SCM kw_hull, kw_compartments, kw_mass, kw_displacement, kw_draught;
18 }
19 
20 namespace vtb {
21 
22  namespace guile {
23 
24  template <> SCM traits_type::type() { return ::type; }
25 
32  SCM make_ship(SCM rest) {
33  using T = VTB_REAL_TYPE;
34  SCM hull = SCM_UNDEFINED, compartments = SCM_UNDEFINED, mass = SCM_UNDEFINED,
35  displacement = SCM_UNDEFINED, draught = SCM_UNDEFINED;
36  scm_c_bind_keyword_arguments("make-ship", rest,
37  scm_t_keyword_arguments_flags{},
38  kw_hull, &hull, kw_compartments, &compartments,
39  kw_mass, &mass, kw_displacement, &displacement,
40  kw_draught, &draught, SCM_UNDEFINED);
41  auto* wrapper = make_wrapper<object_type>();
42  if (is_bound(hull)) {
43  SCM s_class = scm_class_of(hull);
44  if (s_class == Traits<polyhedron_type>::type()) {
45  auto* hull_wrapper = get_wrapper<polyhedron_type>(hull);
46  wrapper->get()->hull(*hull_wrapper->get());
47  } else if (s_class == Traits<hull_type>::type()) {
48  auto* hull_wrapper = get_wrapper<hull_type>(hull);
49  wrapper->get()->hull(*hull_wrapper->get());
50  } else {
51  throw_error("hull should be of type polyhedron or hull");
52  return SCM_UNSPECIFIED;
53  }
54  }
55  if (is_bound(compartments)) {
56  compartment_array rooms;
57  while (compartments != SCM_EOL) {
58  SCM comp = scm_car(compartments);
59  auto* comp_wrapper = get_wrapper<compartment_type>(comp);
60  rooms.emplace_back(*comp_wrapper->get());
61  compartments = scm_cdr(compartments);
62  }
63  wrapper->get()->compartments(rooms);
64  }
65  if (is_bound(mass) + is_bound(displacement) + is_bound(draught) >= 2) {
66  throw_error("specify only one of the following: mass, displacement, draught");
67  return SCM_UNSPECIFIED;
68  }
69  if (is_bound(mass)) {
70  wrapper->get()->mass(from_scm<T>(mass));
71  }
72  if (is_bound(displacement)) {
73  wrapper->get()->displacement(from_scm<T>(displacement));
74  }
75  if (is_bound(draught)) {
76  wrapper->get()->draught(from_scm<T>(draught));
77  }
78  return make_object<object_type>(traits_type::type(), wrapper);
79  }
80 
87  SCM ship_mass(SCM object) {
88  auto* wrapper = get_wrapper<object_type>(object);
89  return to_scm(wrapper->get()->mass());
90  }
91 
92  template <> void
93  traits_type::define() {
94  ::type = define_type<object_type>("<compartment>");
95  kw_hull = scm_from_utf8_keyword("hull");
96  kw_compartments = scm_from_utf8_keyword("compartments");
97  kw_mass = scm_from_utf8_keyword("mass");
98  kw_displacement = scm_from_utf8_keyword("displacement");
99  kw_draught = scm_from_utf8_keyword("draught");
100  define_procedure("make-ship", 0, 0, 1, VTB_GUILE_1(make_ship));
101  define_procedure("ship-mass", 1, 0, 0, VTB_GUILE_1(ship_mass));
102  }
103 
104  }
105 
106 }
SCM ship_mass(SCM object)
Get ship mass.
Definition: guile/ship.cc:87
Rigid ship with a mass and translational and angular velocity.
Definition: core/ship.hh:186
OBJ importer/exporter.
Definition: object.hh:28
Main namespace.
Definition: convert.hh:9
SCM make_ship(SCM rest)
Construct ship from hull and compartments mass/displacement/draught.
Definition: guile/ship.cc:32