Path.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright © 2009, 2010 James Legg.
00006     This program is free software: you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation, either version 3 of the License, or
00009     (at your option) any later version.
00010 */
00011 
00012 #include "Path.h"
00013 #include "../stream_loader.h"
00014 #include "../FormErrors.h"
00015 
00016 #include <limits>
00017 
00018 namespace Track
00019 {
00020 
00021 const unsigned int path_newest_version = 2;
00022 
00023 Path::Path(std::istream & source, const Theme & theme, const Track * track,
00024            bool editor)
00025     :   file_version(int_from_stream(source))
00026     ,   editor(editor)
00027     ,   theme(theme)
00028     ,   starting_edge(0)
00029 {
00030     if (file_version == 0) throw CorruptedError();
00031     if (file_version > path_newest_version) throw NewVersionError();
00032     // We store the graph in the stream as a vector of vertices, followed by a
00033     // vector of edges.
00034     std::size_t number_of_vertices;
00035     source >> number_of_vertices;
00036     // add vertices with descriptors
00037     for (std::size_t vertex_index = 0;
00038          vertex_index < number_of_vertices;
00039          vertex_index++)
00040     {
00041         boost::add_vertex(PathVertex(source, theme, track), graph);
00042     }
00043     
00044     // now on to the edges
00045     std::size_t number_of_edges;
00046     source >> number_of_edges;
00047     for (std::size_t edge_index = 0; edge_index < number_of_edges; edge_index++)
00048     {
00049         // Read vertex indices
00050         std::size_t vert_index_start, vert_index_end;
00051         source >> vert_index_start >> vert_index_end;
00052         if (   vert_index_start > num_vertices(graph)
00053             || vert_index_end   > num_vertices(graph))
00054         {
00055             // File refers to vertices that don't exist, so it must be invalid.
00056             throw CorruptedError();
00057         }
00058         
00059         // Read edge data
00060         PathEdge edge_data(source, theme);
00061         
00062         std::pair<Graph::edge_descriptor, bool> new_edge = 
00063         add_edge(vert_index_start, vert_index_end, edge_data, graph);
00064         // update the edge's information (length, meshes, and so on).
00065         PathEdge & new_edge_data = graph[new_edge.first];
00066         new_edge_data.render_mode = editor ? DrawableMesh::RM_WIREFRAME : DrawableMesh::RM_SOLID;
00067         new_edge_data.update(graph[vert_index_start].get_name(),
00068                              graph[vert_index_end].get_name(),
00069                              this);
00070         if (file_version >= 2)
00071         {
00072             bool is_start_edge;
00073             source >> is_start_edge;
00074             if(is_start_edge) starting_edge = new_edge_data.get_name();
00075         }
00076     }
00077     
00078     if (starting_edge == 0)
00079     {
00080         // Starting edge was not recorded.
00081         // Set it to the first edge if there is one.
00082         if (boost::num_edges(graph) > 0)
00083         {
00084             starting_edge = graph[*(boost::edges(graph).first)].get_name();
00085         }
00086     }
00087 }
00088     
00089 Path::Path(const Theme & theme, const Track * track, bool editor)
00090     :   file_version(0)
00091     ,   editor(editor)
00092     ,   theme(theme)
00093     ,   starting_edge(0)
00094 {
00095 }
00096 
00097 Path::~Path()
00098 {
00099     
00100 }
00101 
00102 std::ostream & operator<<(std::ostream & destination, const Path & path)
00103 {
00104     destination << path_newest_version << ' ';
00105     // vertices
00106     destination << boost::num_vertices(path.graph) << ' ';
00107     typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator;
00108     std::pair<VertexIterator, VertexIterator> vertex_range;
00109     for (vertex_range  = boost::vertices(path.graph);
00110          vertex_range.first != vertex_range.second;
00111          vertex_range.first++)
00112     {
00113         destination << path.graph[*(vertex_range.first)] << ' ';
00114     }
00115     
00116     destination << boost::num_edges(path.graph) << ' ';
00117     typedef boost::graph_traits<Path::Graph>::edge_iterator EdgeIterator;
00118     std::pair<EdgeIterator, EdgeIterator> edge_range;
00119     for (edge_range  = boost::edges(path.graph);
00120          edge_range.first != edge_range.second;
00121          edge_range.first++)
00122     {
00123         // output the vertex descriptor of the source and target vertices,
00124         // so the graph can be reconstructed.
00125         destination << boost::source(*(edge_range.first), path.graph) << ' '
00126                     << boost::target(*(edge_range.first), path.graph) << ' '
00127         // Now output the the PathEdge information.
00128                     << path.graph[*(edge_range.first)] << ' '
00129         // is this the starting edge?
00130         // we write it like this so we can safely load a Path where the 
00131         // starting edge has been deleted, even though it saves space just to
00132         // identify the right one at the end.
00133                     << (path.graph[*(edge_range.first)].get_name() == path.starting_edge) << ' ';
00134     }
00135     return destination;
00136 }
00137 
00138 AxisAlignedBoundingBox Path::get_bounding_box() const
00139 {
00140     AxisAlignedBoundingBox result;
00141     
00142     // find the bounding box of all the vertices.
00143     typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator;
00144     std::pair<VertexIterator, VertexIterator> vertex_range;
00145     for (vertex_range  = boost::vertices(graph);
00146          vertex_range.first != vertex_range.second;
00147          vertex_range.first++)
00148     {
00149         result |= graph[*(vertex_range.first)];
00150     }
00151     
00152     // now expand to include control points
00153     typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator;
00154     std::pair<EdgeIterator, EdgeIterator> edge_range;
00155     for (edge_range  = boost::edges(graph);
00156          edge_range.first != edge_range.second;
00157          edge_range.first++)
00158     {
00159         const Graph::edge_descriptor edge_descriptor = *(edge_range.first);
00160         const PathEdge & edge = graph[edge_descriptor];
00161         result |= edge;
00162     }
00163     
00164     // add some padding.
00165     result.add_border(20.0);
00166     
00167     return result;
00168 }
00169 
00170 PathVertex & Path::get_node(const std::size_t index)
00171 {
00172     return graph[get_node_descriptor(index)];
00173 }
00174 
00175 const PathVertex & Path::get_node(const std::size_t index) const
00176 {
00177     return graph[get_node_descriptor(index)];
00178 }
00179 
00180 Path::Graph::vertex_descriptor Path::get_node_descriptor(const std::size_t index)
00181 {
00182     return get_node_descriptor_internal(index);
00183 }
00184 
00185 const Path::Graph::vertex_descriptor Path::get_node_descriptor(const std::size_t index) const
00186 {
00187     return get_node_descriptor_internal(index);
00188 }
00189 
00190 Path::Graph::vertex_descriptor Path::get_node_descriptor_internal(const std::size_t index) const
00191 {
00193     typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator;
00194     std::pair<VertexIterator, VertexIterator> vertex_range;
00195     for (vertex_range  = boost::vertices(graph);
00196          vertex_range.first != vertex_range.second;
00197          vertex_range.first++)
00198     {
00199         const PathVertex & vertex = graph[*(vertex_range.first)];
00200         if (vertex.get_name() == index)
00201         {
00202             return *(vertex_range.first);
00203         }
00204     }
00205     DEBUG_MESSAGE("No node has index " << index << ", aborting.");
00206     assert(false);
00207     throw;
00208 }
00209 
00210 
00211 PathEdge & Path::get_edge(const std::size_t index)
00212 {
00213     return graph[get_edge_descriptor(index)];
00214 }
00215 
00216 const PathEdge & Path::get_edge(const std::size_t index) const
00217 {
00218     return graph[get_edge_descriptor(index)];
00219 }
00220 
00221 Path::Graph::edge_descriptor Path::get_edge_descriptor(const std::size_t index)
00222 {
00223     return get_edge_descriptor_internal(index);
00224 }
00225 
00226 const Path::Graph::edge_descriptor Path::get_edge_descriptor(const std::size_t index) const
00227 {
00228     return get_edge_descriptor_internal(index);
00229 }
00230 
00231 Path::Graph::edge_descriptor Path::get_edge_descriptor_internal(const std::size_t index) const
00232 {
00234     typedef boost::graph_traits<Path::Graph>::edge_iterator EdgeIterator;
00235     std::pair<EdgeIterator, EdgeIterator> edge_range;
00236     for (edge_range  = boost::edges(graph);
00237          edge_range.first != edge_range.second;
00238          edge_range.first++)
00239     {
00240         const PathEdge & edge = graph[*(edge_range.first)];
00241         if (edge.get_name() == index)
00242         {
00243             return *(edge_range.first);
00244         }
00245     }
00246     DEBUG_MESSAGE("No edge has index " << index << ", aborting.");
00247     assert(false);
00248     throw;
00249 }
00250 
00251 void Path::set_handle_lengths(btScalar handle_length)
00252 {
00253     typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator;
00254     std::pair<VertexIterator, VertexIterator> vertex_range;
00255     for (vertex_range  = boost::vertices(graph);
00256          vertex_range.first != vertex_range.second;
00257          vertex_range.first++)
00258     {
00259         graph[*(vertex_range.first)].set_handle_lengths(handle_length);
00260     }
00261 }
00262 
00263 void Path::update_connected_edges(Path::Graph::vertex_descriptor vertex_descriptor)
00264 {
00265     // edges out of the vertex
00266     typedef boost::graph_traits<Graph>::out_edge_iterator OutEdgeIterator;
00267     std::pair<OutEdgeIterator, OutEdgeIterator> out_edge_range;
00268     for (out_edge_range = boost::out_edges(vertex_descriptor, graph);
00269          out_edge_range.first != out_edge_range.second;
00270          out_edge_range.first++)
00271     {
00272         PathEdge & edge = graph[*(out_edge_range.first)];   
00273         edge.update();
00274     }
00275     // edges into the vertex
00276     typedef boost::graph_traits<Graph>::in_edge_iterator InEdgeIterator;
00277     std::pair<InEdgeIterator, InEdgeIterator> in_edge_range;
00278     for (in_edge_range = boost::in_edges(vertex_descriptor, graph);
00279          in_edge_range.first != in_edge_range.second;
00280          in_edge_range.first++)
00281     {
00282         PathEdge & edge = graph[*(in_edge_range.first)];   
00283         edge.update();
00284     }
00285 }
00286 
00287 const EditAssist::SegmentConnectionHandle * Path::get_nearest_segment_connection_handle(btVector3 position) const
00288 {
00289     btScalar best_distance = std::numeric_limits<btScalar>::max();
00290     typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator;
00291     std::pair<VertexIterator, VertexIterator> vertex_range;
00292     btVector3 best_handle_position(0, 0, 0);
00293     const EditAssist::SegmentConnectionHandle * best_handle = 0;
00294     for (vertex_range  = boost::vertices(graph);
00295          vertex_range.first != vertex_range.second;
00296          vertex_range.first++)
00297     {
00298         const PathVertex & vertex = graph[*(vertex_range.first)];
00299         const std::vector<boost::shared_ptr<EditAssist::SegmentConnectionHandle> > & handles =
00300             vertex.get_connection_handles();
00301         
00302         for (std::vector<boost::shared_ptr<EditAssist::SegmentConnectionHandle> >::const_iterator it = handles.begin();
00303              it != handles.end();
00304              it++)
00305         {
00306             btScalar this_distance = (**it).get_position().distance2(position);
00307             if (this_distance < best_distance)
00308             {
00309                 best_handle = &(**it);
00310                 best_distance = this_distance;
00311             }
00312         }
00313     }
00314     return best_handle;
00315 }
00316 
00317 const EditAssist::SegmentConnectionHandle * Path::get_nearest_segment_connection_handle(btVector3 position, btVector3 normal) const
00318 {
00320     return get_nearest_segment_connection_handle(position);
00321 }
00322 
00323 void Path::add_collision_faces(btTriangleMesh & shape) const
00324 {
00325     typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator;
00326     std::pair<VertexIterator, VertexIterator> vertex_range;
00327     for (vertex_range  = boost::vertices(graph);
00328          vertex_range.first != vertex_range.second;
00329          vertex_range.first++)
00330     {
00331         graph[*(vertex_range.first)].add_collision_faces(shape);
00332     }
00333     
00334     typedef boost::graph_traits<Path::Graph>::edge_iterator EdgeIterator;
00335     std::pair<EdgeIterator, EdgeIterator> edge_range;
00336     for (edge_range  = boost::edges(graph);
00337          edge_range.first != edge_range.second;
00338          edge_range.first++)
00339     {
00340         graph[*(edge_range.first)].add_collision_faces(shape);
00341     }
00342 }
00343 
00344 void Path::add_floor_faces(btTriangleMesh & shape) const
00345 {
00346     typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator;
00347     std::pair<VertexIterator, VertexIterator> vertex_range;
00348     for (vertex_range  = boost::vertices(graph);
00349          vertex_range.first != vertex_range.second;
00350          vertex_range.first++)
00351     {
00352         graph[*(vertex_range.first)].add_floor_faces(shape);
00353     }
00354     
00355     typedef boost::graph_traits<Path::Graph>::edge_iterator EdgeIterator;
00356     std::pair<EdgeIterator, EdgeIterator> edge_range;
00357     for (edge_range  = boost::edges(graph);
00358          edge_range.first != edge_range.second;
00359          edge_range.first++)
00360     {
00361         graph[*(edge_range.first)].add_floor_faces(shape);
00362     }
00363 }
00364 
00365 void Path::add_ai_faces(MeshFaces & mesh) const
00366 {
00367     typedef boost::graph_traits<Path::Graph>::vertex_iterator VertexIterator;
00368     std::pair<VertexIterator, VertexIterator> vertex_range;
00369     for (vertex_range  = boost::vertices(graph);
00370          vertex_range.first != vertex_range.second;
00371          vertex_range.first++)
00372     {
00373         graph[*(vertex_range.first)].add_ai_faces(mesh);
00374     }
00375     
00376     typedef boost::graph_traits<Path::Graph>::edge_iterator EdgeIterator;
00377     std::pair<EdgeIterator, EdgeIterator> edge_range;
00378     for (edge_range  = boost::edges(graph);
00379          edge_range.first != edge_range.second;
00380          edge_range.first++)
00381     {
00382         graph[*(edge_range.first)].add_ai_faces(mesh);
00383     }
00384 }
00385 
00386 unsigned long int Path::get_starting_edge() const
00387 {
00388     return starting_edge;
00389 }
00390 
00391 void Path::set_starting_edge(unsigned long int new_edge_name)
00392 {
00393     starting_edge = new_edge_name;
00394 }
00395 
00396 
00397 void Path::find_start_plane(btVector3 & normal, btScalar & distance) const
00398 {
00399     assert(starting_edge);
00400     const PathEdge & edge(get_edge(starting_edge));
00401     btTransform transform = edge.get_transform(1.0);
00402     // plane goes through origin
00403     btVector3 origin = transform.getOrigin();
00404     normal = transform(btVector3(0.0, 1.0, 0.0)) - origin;
00405     distance = -normal.dot(origin);
00406 }
00407 
00408 btVector3 Path::find_start_position() const
00409 {
00410     assert(starting_edge);
00411     const PathEdge & edge(get_edge(starting_edge));
00412     return edge.get_transform(1.0).getOrigin();
00413 }
00414 
00415 void Path::draw() const
00416 {
00417     // edges
00418     typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator;
00419     std::pair<EdgeIterator, EdgeIterator> edge_range;
00420     for (edge_range = boost::edges(graph);
00421          edge_range.first != edge_range.second;
00422          edge_range.first++)
00423     {
00424         const PathEdge & edge = graph[*(edge_range.first)];
00425         edge.draw();
00426     }
00427     // vertices.
00428     typedef boost::graph_traits<Graph>::vertex_iterator VertexIterator;
00429     std::pair<VertexIterator, VertexIterator> vertex_range;
00430     for (vertex_range = boost::vertices(graph);
00431          vertex_range.first != vertex_range.second;
00432          vertex_range.first++)
00433     {
00434         const PathVertex & vertex = graph[*(vertex_range.first)];
00435         vertex.draw();
00436     }
00437 }
00438 
00439 void Path::conditional_draw(const OcclusionTester & occlusion_tester) const
00440 {
00444     // edges
00445     typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator;
00446     std::pair<EdgeIterator, EdgeIterator> edge_range;
00447     for (edge_range = boost::edges(graph);
00448          edge_range.first != edge_range.second;
00449          edge_range.first++)
00450     {
00451         const PathEdge & edge = graph[*(edge_range.first)];
00452         edge.conditional_draw(occlusion_tester);
00453     }
00454     // vertices.
00455     typedef boost::graph_traits<Graph>::vertex_iterator VertexIterator;
00456     std::pair<VertexIterator, VertexIterator> vertex_range;
00457     for (vertex_range = boost::vertices(graph);
00458          vertex_range.first != vertex_range.second;
00459          vertex_range.first++)
00460     {
00461         const PathVertex & vertex = graph[*(vertex_range.first)];
00462         vertex.conditional_draw(occlusion_tester);
00463     }
00464 }
00465 
00466 AxisAlignedBoundingBox Path::get_bounds() const
00467 {
00468     // bounds of all components.
00469     AxisAlignedBoundingBox bounds;
00473     // edges
00474     typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator;
00475     std::pair<EdgeIterator, EdgeIterator> edge_range;
00476     for (edge_range = boost::edges(graph);
00477          edge_range.first != edge_range.second;
00478          edge_range.first++)
00479     {
00480         const PathEdge & edge = graph[*(edge_range.first)];
00481         bounds |= edge;
00482     }
00483     // vertices.
00484     typedef boost::graph_traits<Graph>::vertex_iterator VertexIterator;
00485     std::pair<VertexIterator, VertexIterator> vertex_range;
00486     for (vertex_range = boost::vertices(graph);
00487          vertex_range.first != vertex_range.second;
00488          vertex_range.first++)
00489     {
00490         const PathVertex & vertex = graph[*(vertex_range.first)];
00491         bounds |= vertex;
00492     }
00493     return bounds;
00494 }
00495 
00496 }

Get Racer at SourceForge.net. Fast, secure and Free Open Source software downloads

Generated at Mon Sep 6 00:41:11 2010 by Doxygen version 1.4.7 for Racer version svn335.