DHART
Loading...
Searching...
No Matches
visibility_graph.cpp
Go to the documentation of this file.
1
7
8#include <visibility_graph.h>
9
10#include <array>
11#include <thread>
12#include <omp.h>
13#include<algorithm>
14
15#include <robin_hood.h>
16#include <graph.h>
17#include <embree_raytracer.h>
18#include <Edge.h>
19#include <node.h>
20#include <Constants.h>
21
22using namespace HF;
23using namespace HF::SpatialStructures;
25using std::vector;
26using std::array;
27
47 inline bool HeightCheck(const Node& Node, float height, EmbreeRayTracer& ert) {
48 const array<float, 3> up{ 0,0,1 };
49 // Create a copy of this node that's slightly offset off of the ground to ensure
50 // it doesn't intersect with the ground
51 auto node_copy = array<float, 3>{Node[0], Node[1], Node[2] + ROUNDING_PRECISION};
52
53 // Cast an occlusion ray straight up with a distance of height.
54 return !ert.Occluded(node_copy, up, height);
55 }
56
57
69 vector<int> HeightCheckAllNodes(const vector<Node>& nodes_to_filter, float height, EmbreeRayTracer& ert) {
70 vector<int> valid_nodes;
71
72 // Loop through every node in nodes_to_filter
73 for (int i = 0; i < nodes_to_filter.size(); i++) {
74
75 // If the node passes the height check, insert its index
76 // into valid_nodes.
77 const auto& node = nodes_to_filter[i];
78 if (HeightCheck(node, height, ert))
79 valid_nodes.push_back(i);
80 }
81 return valid_nodes;
82 }
83
104 const Node& node_a,
105 const Node& node_b,
106 EmbreeRayTracer& ert,
107 float height = 1.7f,
108 float pre_calculated_distance = 0.0f
109 ) {
110 // Raise node A (this only matters for the origin);
111 auto heightened_node = node_a;
112 heightened_node[2] += height;
113
114 // Only calculate distance if it wasn't already passed to us
115 float distance;
116 if (pre_calculated_distance == 0.0f)
117 distance = node_a.distanceTo(node_b);
118 else
119 distance = pre_calculated_distance;
120
121 // Calculate the direction between node_a and node_b
122 auto direction = node_a.directionTo(node_b);
123
124 // Cast the ray and return the result.
125 return ert.Occluded(heightened_node, direction, distance);
126 }
127
128 Graph AllToAll(EmbreeRayTracer& ert, const vector<Node>& nodes, float height) {
129
130 // Create a jagged array for edges and costs
131 const int n = nodes.size();
132 vector<vector<int>> edges(n);
133 vector<vector<float>> costs(n);
134
135 // Set the degree of parallelism to the number of cores of the client machine
136 int cores = -1;
137 if (cores < 0) {
138 cores = std::thread::hardware_concurrency();
139 omp_set_num_threads(cores);
140 }
141 else if (cores > 0)
142 omp_set_num_threads(cores);
143
144 // Discard nodes that don't pass the height check.
145 auto valid_nodes = HeightCheckAllNodes(nodes, height, ert);
146
147 // Calculate edges for every node in parallel
148#pragma omp parallel for schedule(static)
149 for (int i = 0; i < valid_nodes.size(); i++) {
150
151 // Acquire the id of the node we're calculating this for
152 int node_id = valid_nodes[i];
153
154 // Get the node we're calculating the edges for
155 const Node& node_a = nodes[node_id];
156
157 // Get references to the cost and edge arrays for this node
158 // to save an index operation for every check.
159 vector<int>& edge_list = edges[node_id];
160 vector<float>& cost_list = costs[node_id];
161
162 // Check connection between this node and every other valid node
163 for (int k = 0; k < valid_nodes.size(); k++) {
164
165 // Don't check this node against itself
166 if (i == k) continue;
167
168 // Get the next node from its index in valid_nodes
169 int node_b_id = valid_nodes[k];
170
171 // Calculate distance between node_a and node_b
172 const Node& node_b = nodes[node_b_id];
173 float distance = node_a.distanceTo(node_b);
174
175 // Check if they have a clear line of sight. If they do, then add the distance
176 // between them, and node_b's id to node_a's edge and cost array.
177 if (!IsOcclusionBetween(node_a, nodes[node_b_id], ert, height, distance)) {
178 edge_list.push_back(node_b_id);
179 cost_list.push_back(distance);
180 }
181 }
182 }
183 // Construct and return a graph from the set of nodes, the edge array
184 // and the node array.
185 return Graph(edges, costs, nodes);
186 }
187
188
189 Graph GroupToGroup(EmbreeRayTracer& ert, const vector<Node>& from, const vector<Node>& to, float height) {
190 // Determine how many nodes are in both arrays
191 const int from_count = from.size();
192 const int to_count = to.size();
193
194 // Create an jagged array of edges and costs based on how many nodes
195 // are in from and to. Note that elements in the to part of the array
196 // will not be used. since edges are only created from nodes in from
197 vector<vector<int>> edges(from_count + to_count);
198 vector<vector<float>> costs(from_count + to_count);
199
200
201 // Use as many cores as the host machine can
202 int cores = -1;
203 if (cores < 0) {
204 cores = std::thread::hardware_concurrency();
205 omp_set_num_threads(cores);
206 }
207 else if (cores > 0) omp_set_num_threads(cores);
208
209 // Perform height check on every node in nodes.
210 auto valid_nodes = HeightCheckAllNodes(from, height, ert);
211 auto valid_to_nodes = HeightCheckAllNodes(to, height, ert);
212
213 // Iterate through every node in valid_nodes in parallel
214#pragma omp parallel for schedule(static)
215 for (int i = 0; i < valid_nodes.size(); i++) {
216
217 // Get the id, node, and references to its arrays.
218 int id = valid_nodes[i];
219 const Node& node_a = from[id];
220 vector<int>& edge_list = edges[id];
221 vector<float>& cost_list = costs[id];
222
223 // Check if it has a connection to every node in to
224 for (int k = 0; k < valid_to_nodes.size(); k++) {
225
226 // Get the node at this ID in to
227 int to_id = valid_to_nodes[k];
228 const Node& node_b = to[to_id];
229
230 // Calculate the distance between node_a and node_b
231 float distance = node_a.distanceTo(node_b);
232
233 // Check if there's an occlusion between node_a and node_b. If they have
234 // a clear line of sight, then add the edge and cost to node_a's arrays.
235 if (!IsOcclusionBetween(node_a, node_b, ert, height, distance)) {
236
237 edge_list.push_back(to_id + from_count);
238 cost_list.push_back(distance);
239 }
240 }
241 }
242
243 // Copy all nodes into a single array.
244 vector<Node> graph_nodes(from.size() + to.size());
245 std::copy(from.begin(), from.end(), graph_nodes.begin());
246 std::copy(to.begin(), to.end(), graph_nodes.begin() + from.size());
247
248 // Create a new graph.
249 return Graph(edges, costs, graph_nodes);
250 }
251
252 Graph AllToAllUndirected(EmbreeRayTracer& ert, const vector<Node>& nodes, float height, int cores) {
253 const int n = nodes.size();
254 vector<vector<int>> edges(n);
255 vector<vector<float>> costs(n);
256
257 // Use as many cores as this machine has or the number of cores in cores
258 if (cores < 0) {
259 cores = std::thread::hardware_concurrency();
260 omp_set_num_threads(cores);
261 }
262 else if (cores > 0)
263 omp_set_num_threads(cores);
264
265 // Perform a height check on every node
266 const auto valid_nodes = HeightCheckAllNodes(nodes, height, ert);
267
268 // Iterate through every node in nodes
269#pragma omp parallel
270 {
271#pragma omp for schedule(dynamic)
272 for (int i = 0; i < valid_nodes.size(); i++) {
273
274 // Get the node and a reference to its edge/cost arrays
275 int node_a_id = valid_nodes[i];
276 const Node& node_a = nodes[node_a_id];
277 vector<int>& edge_list = edges[node_a_id];
278 vector<float>& cost_list = costs[node_a_id];
279
280
281 // Check if it has a line of sight between every other node
282 // in nodes.
283 for (int k = i + 1; k < valid_nodes.size(); k++) {
284
285 // Get the second node in nodes
286 int node_b_id = valid_nodes[k];
287 const Node& node_b = nodes[node_b_id];
288 float distance = node_a.distanceTo(node_b);
289
290 // Add an edge to this node's arrays if it has a line of sight
291 if (!IsOcclusionBetween(node_a, nodes[k], ert, height, distance)) {
292 edge_list.emplace_back(node_b_id);
293 cost_list.emplace_back(distance);
294 }
295 }
296 }
297 }
298 // Create and return a new graph from this information.
299 return Graph(edges, costs, nodes);
300 }
301}
Contains definitions for the VisibilityGraph class.
Contains definitions for the EmbreeRayTracer
Contains definitions for the HF::SpatialStructures namespace.
Contains definitions for the Edge structure.
Contains definitions for the Graph class.
Contains definitions for the Node structure.
Perform human scale analysis on 3D environments.
Contains standard fundamental data structures for representing space used throughout DHARTAPI.
constexpr float ROUNDING_PRECISION
Minimum value that can be represented in DHART_API.
Definition: Constants.h:30
Evaluate visibility between points in a set of locations.
vector< int > HeightCheckAllNodes(const vector< Node > &nodes_to_filter, float height, EmbreeRayTracer &ert)
Obtain the indexes of all nodes that pass the HeightCheck.
Graph AllToAll(EmbreeRayTracer &ert, const vector< Node > &nodes, float height)
Generate a Visibility Graph between every node in a set of nodes in parallel.
bool IsOcclusionBetween(const Node &node_a, const Node &node_b, EmbreeRayTracer &ert, float height=1.7f, float pre_calculated_distance=0.0f)
Perform a line of sight check between two nodes.
Graph AllToAllUndirected(EmbreeRayTracer &ert, const vector< Node > &nodes, float height, int cores)
Generate a Visibility Graph with every edge stored twice.
Graph GroupToGroup(EmbreeRayTracer &ert, const vector< Node > &from, const vector< Node > &to, float height)
Generate a Visibility Graph from a set of nodes to another set of nodes.
bool HeightCheck(const Node &Node, float height, EmbreeRayTracer &ert)
Check if Node can be raised by height without clipping into any geometry.
A wrapper for Intel's Embree Library.
bool Occluded(const N &origin, const V &direction, float max_distance=-1.0f, int mesh_id=-1)
Determine if there is an intersection with any geometry.
A Graph of nodes connected by edges that supports both integers and HF::SpatialStructures::Node.
Definition: graph.h:486
int size() const
Determine how many nodes are in the graph.
A point in space with an ID.
Definition: node.h:38
float distanceTo(const Node &n2) const
Calculate the distance between this node and n2.
Definition: node.cpp:40
std::array< float, 3 > directionTo(const Node &n2) const
Get the direction between this node and another node
Definition: node.cpp:131