1 /**
2 * Copyright 2007-2021 IMP Inventors. All rights reserved.
3 */
4
5 #include <boost/lexical_cast.hpp>
6 #include <exception>
7 #include <iostream>
8 #include <sstream>
9 #include <string>
10
11 #include "RMF/FileConstHandle.h"
12 #include "RMF/FileHandle.h"
13 #include "RMF/ID.h"
14 #include "RMF/NodeHandle.h"
15 #include "RMF/Vector.h"
16 #include "RMF/decorator/physics.h"
17 #include "RMF/decorator/shape.h"
18 #include "RMF/infrastructure_macros.h"
19 #include "RMF/log.h"
20 #include "RMF/types.h"
21 #include "RMF/utility.h"
22 #include "common.h"
23
24 #define RMF_TRANSFORM(f, Name, attribute) \
25 if (f.get_is(nh)) { \
26 RMF::decorator::Name d = f.get(nh); \
27 RMF::Vector3 cs = d.get_##attribute(); \
28 for (unsigned int i = 0; i < 3; ++i) { \
29 cs[i] = scale * (cs[i] + translation[i]); \
30 } \
31 d.set_##attribute(cs); \
32 }
33
34 #define RMF_TRANSFORM_LIST(f, Name, attribute) \
35 if (f.get_is(nh)) { \
36 RMF::decorator::Name d = f.get(nh); \
37 RMF::Vector3s cs = d.get_##attribute(); \
38 for (unsigned int j = 0; j < cs.size(); ++j) { \
39 for (unsigned int i = 0; i < 3; ++i) { \
40 cs[j][i] = scale * (cs[j][i] + translation[i]); \
41 } \
42 } \
43 d.set_##attribute(cs); \
44 }
45
46 namespace {
47 std::string description(
48 "Transform an rmf file in place. IntermediateParticle, Ball, Cylinder, "
49 "Segment, RigidParticle and ReferenceFrame nodes are handled.");
50
transform(RMF::NodeHandle nh,RMF::decorator::IntermediateParticleFactory ipf,RMF::decorator::RigidParticleFactory rpf,RMF::decorator::ReferenceFrameFactory rff,RMF::decorator::BallFactory bf,RMF::decorator::CylinderFactory cf,RMF::decorator::SegmentFactory sf,double scale,const RMF::Floats & translation)51 void transform(RMF::NodeHandle nh,
52 RMF::decorator::IntermediateParticleFactory ipf,
53 RMF::decorator::RigidParticleFactory rpf,
54 RMF::decorator::ReferenceFrameFactory rff,
55 RMF::decorator::BallFactory bf,
56 RMF::decorator::CylinderFactory cf,
57 RMF::decorator::SegmentFactory sf, double scale,
58 const RMF::Floats& translation) {
59 RMF_TRANSFORM(ipf, IntermediateParticle, coordinates)
60 else RMF_TRANSFORM(rpf, RigidParticle, coordinates);
61 if (ipf.get_is(nh)) {
62 RMF::decorator::IntermediateParticle d = ipf.get(nh);
63 d.set_radius(scale * d.get_radius());
64 }
65 RMF_TRANSFORM(rff, ReferenceFrame, translation);
66 RMF_TRANSFORM(bf, Ball, coordinates);
67 RMF_TRANSFORM_LIST(cf, Cylinder, coordinates_list);
68 RMF_TRANSFORM_LIST(sf, Segment, coordinates_list);
69 RMF::NodeHandles children = nh.get_children();
70 for (unsigned int i = 0; i < children.size(); ++i) {
71 transform(children[i], ipf, rpf, rff, bf, cf, sf, scale, translation);
72 }
73 }
74 }
75
main(int argc,char ** argv)76 int main(int argc, char** argv) {
77 try {
78 double scale = 1;
79 std::string translation_str;
80 options.add_options()("scale,s",
81 boost::program_options::value<double>(&scale),
82 "What to scale the model by")(
83 "translation,t",
84 boost::program_options::value<std::string>(&translation_str),
85 "What to translate the model by as \"x y z\"");
86 RMF_ADD_INPUT_FILE("rmf");
87 RMF_ADD_OUTPUT_FILE("rmf");
88 process_options(argc, argv);
89 RMF::Floats translation;
90 if (!translation_str.empty()) {
91 std::istringstream iss(translation_str);
92 for (unsigned int i = 0; i < 3; ++i) {
93 double c;
94 iss >> c;
95 if (!iss) {
96 std::cerr << "Bad translation" << std::endl;
97 print_help_and_exit(argv);
98 }
99 translation.push_back(c);
100 }
101 } else {
102 translation = RMF::Floats(0, 3);
103 }
104 RMF_INFO("Scaling model by " << scale);
105 RMF_INFO("Translating model by " << translation[0] << " " << translation[1]
106 << " " << translation[2]);
107
108 RMF::FileConstHandle rhi = RMF::open_rmf_file_read_only(input);
109 RMF::FileHandle rh = RMF::create_rmf_file(output);
110 RMF::clone_file_info(rhi, rh);
111 RMF::clone_hierarchy(rhi, rh);
112 RMF::clone_static_frame(rhi, rh);
113 RMF::decorator::IntermediateParticleFactory ipf(rh);
114 RMF::decorator::RigidParticleFactory rpf(rh);
115 RMF::decorator::ReferenceFrameFactory rff(rh);
116 RMF::decorator::BallFactory bf(rh);
117 RMF::decorator::CylinderFactory cf(rh);
118 RMF::decorator::SegmentFactory sf(rh);
119 RMF_FOREACH(RMF::FrameID frame, rhi.get_frames()) {
120 RMF::clone_loaded_frame(rhi, rh);
121 RMF_INFO("Processing frame " << frame);
122 rh.set_current_frame(frame);
123 transform(rh.get_root_node(), ipf, rpf, rff, bf, cf, sf, scale,
124 translation);
125 }
126 return 0;
127 }
128 catch (const std::exception& e) {
129 std::cerr << "Error: " << e.what() << std::endl;
130 print_help_and_exit(argv);
131 }
132 }
133