octomap 1.5.0
|
00001 // $Id: OcTreeBaseSE.hxx 375 2012-05-23 15:39:15Z ahornung $ 00002 00011 /* 00012 * Copyright (c) 2010, K. M. Wurm, A. Hornung, University of Freiburg 00013 * All rights reserved. 00014 * 00015 * Redistribution and use in source and binary forms, with or without 00016 * modification, are permitted provided that the following conditions are met: 00017 * 00018 * * Redistributions of source code must retain the above copyright 00019 * notice, this list of conditions and the following disclaimer. 00020 * * Redistributions in binary form must reproduce the above copyright 00021 * notice, this list of conditions and the following disclaimer in the 00022 * documentation and/or other materials provided with the distribution. 00023 * * Neither the name of the University of Freiburg nor the names of its 00024 * contributors may be used to endorse or promote products derived from 00025 * this software without specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00028 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00029 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00030 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00031 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00032 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00033 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00034 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00035 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00036 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00037 * POSSIBILITY OF SUCH DAMAGE. 00038 */ 00039 00040 00041 #include <limits> 00042 #include <cmath> 00043 #include <stdio.h> 00044 #include <stdlib.h> 00045 00046 namespace octomap { 00047 00048 00049 template <class NODE> 00050 OcTreeBaseSE<NODE>::OcTreeBaseSE (double _resolution) : 00051 OcTreeBase<NODE>(_resolution) { 00052 00053 lut = new OcTreeLUT (this->tree_depth); 00054 } 00055 00056 template <class NODE> 00057 OcTreeBaseSE<NODE>::~OcTreeBaseSE () { 00058 delete lut; 00059 } 00060 00061 00062 template <class NODE> 00063 bool OcTreeBaseSE<NODE>::computeRayKeys(const point3d& origin, 00064 const point3d& end, 00065 KeyRay& ray) const { 00066 00067 // std::cout << "using key ray method\n"; 00068 00069 // see "A Faster Voxel Traversal Algorithm for Ray Tracing" by Amanatides & Woo 00070 // basically: DDA in 3D 00071 00072 ray.reset(); 00073 00074 OcTreeKey key_origin, key_end; 00075 if ( !OcTreeBase<NODE>::coordToKeyChecked(origin, key_origin) || 00076 !OcTreeBase<NODE>::coordToKeyChecked(end, key_end) ) { 00077 OCTOMAP_WARNING_STR("Coordinates out of bounds during ray casting"); 00078 return false; 00079 } 00080 00081 ray.addKey(key_origin); 00082 00083 if (key_origin == key_end) return true; // same tree cell, we're done. 00084 00085 00086 // Initialization phase ------------------------------------------------------- 00087 00088 point3d direction = (end - origin); 00089 double length = direction.norm2(); 00090 direction /= length; // normalize vector 00091 00092 int step[3]; 00093 double tMax[3]; 00094 double tDelta[3]; 00095 00096 OcTreeKey current_key = key_origin; 00097 00098 for(unsigned int i=0; i < 3; ++i) { 00099 00100 // compute step direction 00101 if (direction(i) > 0.0) step[i] = 1; 00102 else if (direction(i) < 0.0) step[i] = -1; 00103 else step[i] = 0; 00104 00105 // compute tMax, tDelta 00106 double voxelBorder = this->keyToCoord(current_key[i]); // negative corner point of voxel 00107 voxelBorder += double(step[i] * this->resolution * 0.5); 00108 00109 if (step[i] != 0) { 00110 tMax[i] = ( voxelBorder - origin(i) ) / direction(i); 00111 tDelta[i] = this->resolution / fabs( direction(i) ); 00112 } 00113 else { 00114 tMax[i] = std::numeric_limits<double>::max(); 00115 tDelta[i] = std::numeric_limits<double>::max(); 00116 } 00117 } 00118 00119 // for speedup: 00120 point3d origin_scaled = origin; 00121 origin_scaled /= this->resolution; 00122 double length_scaled = length - this->resolution/2.; // safety margin 00123 length_scaled /= this->resolution; // scale 00124 length_scaled = length_scaled*length_scaled; // avoid sqrt in dist comp. 00125 00126 // Incremental phase --------------------------------------------------------- 00127 00128 bool done = false; 00129 while (!done) { 00130 00131 unsigned int dim; 00132 00133 // find minimum tMax: 00134 if (tMax[0] < tMax[1]){ 00135 if (tMax[0] < tMax[2]) dim = 0; 00136 else dim = 2; 00137 } 00138 else { 00139 if (tMax[1] < tMax[2]) dim = 1; 00140 else dim = 2; 00141 } 00142 00143 // advance in direction "dim" 00144 current_key[dim] += step[dim]; 00145 tMax[dim] += tDelta[dim]; 00146 00147 assert ((current_key[dim] >= 0) && (current_key[dim] < 2*this->tree_max_val)); 00148 00149 // reached endpoint, key equv? 00150 if (current_key == key_end) { 00151 done = true; 00152 break; 00153 } 00154 else { 00155 00156 // reached endpoint world coords? 00157 double dist_from_endpoint = 0; 00158 for (unsigned int j = 0; j < 3; j++) { 00159 double coord = (double) current_key[j] - (double) this->tree_max_val; 00160 dist_from_endpoint += (coord - origin_scaled(j)) * (coord - origin_scaled(j)); 00161 } 00162 if (dist_from_endpoint > length_scaled) { 00163 done = true; 00164 break; 00165 } 00166 00167 else { // continue to add freespace cells 00168 ray.addKey(current_key); 00169 } 00170 } 00171 00172 assert ( ray.size() < ray.sizeMax() - 1); 00173 00174 } // end while 00175 00176 return true; 00177 } 00178 00179 00180 00181 template <class NODE> 00182 NODE* OcTreeBaseSE<NODE>::getLUTNeighbor (const point3d& node_coord, OcTreeLUT::NeighborDirection dir) const { 00183 00184 OcTreeKey start_key; 00185 00186 if (! OcTreeBase<NODE>::coordToKeyChecked(node_coord, start_key)) { 00187 OCTOMAP_ERROR_STR("Error in search: ["<< node_coord <<"] is out of OcTree bounds!"); 00188 return NULL; 00189 } 00190 00191 OcTreeKey neighbor_key; 00192 lut->genNeighborKey(start_key, (signed char&) dir, neighbor_key); 00193 return this->search(neighbor_key); 00194 } 00195 00196 00197 00198 }