/
path.cpp
128 lines (110 loc) · 3.39 KB
/
path.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// SuperTux Path
// Copyright (C) 2005 Philipp <balinor@pnxs.de>
// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "object/path.hpp"
#include <sstream>
#include <stdexcept>
#include "lisp/list_iterator.hpp"
#include "util/log.hpp"
Path::Path() :
nodes(),
mode()
{
}
Path::~Path()
{
}
void
Path::read(const Reader& reader)
{
lisp::ListIterator iter(&reader);
mode = CIRCULAR;
while(iter.next()) {
if(iter.item() == "mode") {
std::string mode_string;
if(!iter.value()->get(mode_string))
throw std::runtime_error("Pathmode not a string");
if(mode_string == "oneshot")
mode = ONE_SHOT;
else if(mode_string == "pingpong")
mode = PING_PONG;
else if(mode_string == "circular")
mode = CIRCULAR;
else {
std::ostringstream msg;
msg << "Unknown pathmode '" << mode_string << "' found";
throw std::runtime_error(msg.str());
}
continue;
}
if(iter.item() != "node") {
log_warning << "unknown token '" << iter.item() << "' in Path nodes list. Ignored." << std::endl;
continue;
}
const lisp::Lisp* node_lisp = iter.lisp();
// each new node will inherit all values from the last one
Node node;
node.time = 1;
if( (!node_lisp->get("x", node.position.x) ||
!node_lisp->get("y", node.position.y)))
throw std::runtime_error("Path node without x and y coordinate specified");
node_lisp->get("time", node.time);
if(node.time <= 0)
throw std::runtime_error("Path node with non-positive time");
nodes.push_back(node);
}
if (nodes.empty())
throw std::runtime_error("Path with zero nodes");
}
Vector
Path::get_base() const
{
if(nodes.empty())
return Vector(0, 0);
return nodes[0].position;
}
int
Path::get_nearest_node_no(Vector reference_point) const
{
int nearest_node_id = -1;
float nearest_node_dist = 0;
int id = 0;
for (std::vector<Node>::const_iterator i = nodes.begin(); i != nodes.end(); ++i, ++id) {
float dist = (i->position - reference_point).norm();
if ((nearest_node_id == -1) || (dist < nearest_node_dist)) {
nearest_node_id = id;
nearest_node_dist = dist;
}
}
return nearest_node_id;
}
int
Path::get_farthest_node_no(Vector reference_point) const
{
int farthest_node_id = -1;
float farthest_node_dist = 0;
int id = 0;
for (std::vector<Node>::const_iterator i = nodes.begin(); i != nodes.end(); ++i, ++id) {
float dist = (i->position - reference_point).norm();
if ((farthest_node_id == -1) || (dist > farthest_node_dist)) {
farthest_node_id = id;
farthest_node_dist = dist;
}
}
return farthest_node_id;
}
/* EOF */