-
Notifications
You must be signed in to change notification settings - Fork 1
/
arena.cc
108 lines (93 loc) · 3.56 KB
/
arena.cc
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
// Navigating with grid and place cells in cluttered environments
// Edvardsen et al. (2020). Hippocampus, 30(3), 220-232.
//
// Licensed under the EUPL-1.2-or-later.
// Copyright (c) 2019 NTNU - Norwegian University of Science and Technology.
// Author: Vegard Edvardsen (https://github.com/evegard).
#include "arena.h"
#include <fstream>
#include <ostream>
#include <string>
#include <vector>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
namespace bg = boost::geometry;
typedef bg::model::d2::point_xy<double> point_t;
typedef bg::model::polygon<point_t> polygon_t;
class BoostGeometryArena : public Arena
{
public:
BoostGeometryArena(const char *wkt_string);
virtual void update_sensors(double x, double y,
double range, real *sensors, int sensor_count);
virtual bool line_intersects(double ax, double ay, double bx, double by);
protected:
bg::model::multi_polygon<polygon_t> multipolygon;
};
Arena *Arena::load_arena(const char *wkt_string)
{
return new BoostGeometryArena(wkt_string);
}
BoostGeometryArena::BoostGeometryArena(const char *wkt_string)
{
bg::read_wkt(wkt_string, this->multipolygon);
for (polygon_t polygon : this->multipolygon) {
this->polygons.push_back({});
point_t last_point;
bool not_first_point = false;
for (point_t point : bg::exterior_ring(polygon)) {
this->polygons.back().push_back(std::make_tuple(
bg::get<0>(point), bg::get<1>(point)));
if (not_first_point++) {
this->lines.push_back(std::make_tuple(
bg::get<0>(last_point),
bg::get<1>(last_point),
bg::get<0>(point),
bg::get<1>(point)));
}
last_point = point;
}
}
}
void BoostGeometryArena::update_sensors(double x, double y,
double range, real *sensors, int sensor_count)
{
point_t start_point(x, y);
for (int sensor = 0; sensor < sensor_count; sensor++) {
double sensor_direction = sensor * (2 * M_PI / sensor_count);
point_t end_point(
x + range * std::cos(sensor_direction),
y + range * std::sin(sensor_direction));
bg::model::linestring<point_t> sensor_beam;
bg::append(sensor_beam, start_point);
bg::append(sensor_beam, end_point);
std::vector<point_t> intersection_points;
bg::intersection(this->multipolygon, sensor_beam, intersection_points);
bool got_intersection = false;
double closest_distance = HUGE_VAL;
point_t closest_intersection;
for (point_t intersection_point : intersection_points) {
double intersection_distance = bg::distance(
start_point, intersection_point);
if (!got_intersection ||
intersection_distance < closest_distance) {
got_intersection = true;
closest_distance = intersection_distance;
closest_intersection = intersection_point;
}
}
sensors[sensor] = 0.0;
if (got_intersection) {
sensors[sensor] = 2.0 * std::exp(-5.0 * (closest_distance / range));
}
}
}
bool BoostGeometryArena::line_intersects(double ax, double ay, double bx, double by)
{
bg::model::linestring<point_t> line;
bg::append(line, point_t(ax, ay));
bg::append(line, point_t(bx, by));
return bg::intersects(this->multipolygon, line);
}