geometry_3d.cpp

Go to the documentation of this file.
00001 /*
00002  * geometry_3d.cpp
00003  *
00004  * Copyright (C) 2006-2010  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Implementation of 3D geometry methods.  See geometry_3d.h
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "geometry_3d.h"                // always include our own header first
00036 
00037 #include <math.h>
00038 
00039 #include "util/parsing.h"
00040 #include "util/token_stream.h"
00041 
00042 
00043 ////////////////////////////////////////////////////////////////////////////////
00044 //
00045 //      static helper methods
00046 //
00047 ////////////////////////////////////////////////////////////////////////////////
00048 
00049 static void
00050 getDictionaryFromLine
00051 (
00052 IO std::istream& stream,
00053 IN const char * debug_info,
00054 OUT dictionary_t& d
00055 )
00056 {
00057         ASSERT(stream.good(), "bad?");
00058         ASSERT(debug_info, "null");
00059 
00060         eParseBehavior behavior = (eParseBehavior)
00061             (eParse_StripComments | eParse_StripBogus);
00062 
00063         std::string line = getNextLineFromStream(stream, behavior);
00064 
00065         getDictionaryFromString(line.c_str(), debug_info, d);
00066 }
00067 
00068 
00069 
00070 static float
00071 getOptionalFloat
00072 (
00073 IN const dictionary_t& d,
00074 IN const char * key
00075 )
00076 {
00077         ASSERT(key, "null");
00078 
00079         return atof(getOptionalValue(d, key, "0"));
00080 }
00081 
00082 
00083 
00084 void
00085 parsePointFromDictionary
00086 (
00087 IN const dictionary_t& d,
00088 OUT point3d_t& p
00089 )
00090 {
00091         p.x = getOptionalFloat(d, "x");
00092         p.y = getOptionalFloat(d, "y");
00093         p.z = getOptionalFloat(d, "z");
00094 }
00095 
00096 
00097 
00098 void
00099 parseRectFromDictionary
00100 (
00101 IN const dictionary_t& d,
00102 OUT rect3d_t& rect
00103 )
00104 {
00105         rect.x0 = getOptionalFloat(d, "x0");
00106         rect.x1 = getOptionalFloat(d, "x1");
00107         rect.y0 = getOptionalFloat(d, "y0");
00108         rect.y1 = getOptionalFloat(d, "y1");
00109         rect.z0 = getOptionalFloat(d, "z0");
00110         rect.z1 = getOptionalFloat(d, "z1");
00111 }
00112 
00113 
00114 ////////////////////////////////////////////////////////////////////////////////
00115 //
00116 //      public API
00117 //
00118 ////////////////////////////////////////////////////////////////////////////////
00119 
00120 point3d_t
00121 rect3d_t::getCorner
00122 (
00123 IN int index
00124 )
00125 const
00126 throw()
00127 {
00128         ASSERT(index >= 0 && index < eMaxCorners,
00129             "Bad rectangle corner index: %d", index);
00130 
00131         point3d_t retval;
00132         retval.x = (index % 2) ? x0 : x1;
00133         index /= 2;
00134         retval.y = (index % 2) ? y0 : y1;
00135         index /= 2;
00136         retval.z = (index % 2) ? z0 : z1;
00137 
00138         return retval;
00139 }
00140 
00141 
00142 
00143 void
00144 rect3d_t::getEdge
00145 (
00146 IN int index,
00147 OUT point3d_t& p0,
00148 OUT point3d_t& p1
00149 )
00150 const
00151 throw()
00152 {
00153         switch (index) {
00154         case 0:
00155                 p0 = this->getCorner(0);
00156                 p1 = this->getCorner(1);
00157                 return;
00158 
00159         case 1:
00160                 p0 = this->getCorner(0);
00161                 p1 = this->getCorner(2);
00162                 return;
00163 
00164         case 2:
00165                 p0 = this->getCorner(0);
00166                 p1 = this->getCorner(4);
00167                 return;
00168 
00169         case 3:
00170                 p0 = this->getCorner(1);
00171                 p1 = this->getCorner(3);
00172                 return;
00173 
00174         case 4:
00175                 p0 = this->getCorner(1);
00176                 p1 = this->getCorner(5);
00177                 return;
00178 
00179         case 5:
00180                 p0 = this->getCorner(2);
00181                 p1 = this->getCorner(3);
00182                 return;
00183 
00184         case 6:
00185                 p0 = this->getCorner(2);
00186                 p1 = this->getCorner(6);
00187                 return;
00188 
00189         case 7:
00190                 p0 = this->getCorner(3);
00191                 p1 = this->getCorner(7);
00192                 return;
00193 
00194         case 8:
00195                 p0 = this->getCorner(4);
00196                 p1 = this->getCorner(5);
00197                 return;
00198 
00199         case 9:
00200                 p0 = this->getCorner(4);
00201                 p1 = this->getCorner(6);
00202                 return;
00203 
00204         case 10:
00205                 p0 = this->getCorner(5);
00206                 p1 = this->getCorner(7);
00207                 return;
00208 
00209         case 11:
00210                 p0 = this->getCorner(6);
00211                 p1 = this->getCorner(7);
00212                 return;
00213         }
00214 
00215         ASSERT(index >= 0 && index <= eMaxEdges,
00216             "Bad rectangle edge index: %d", index);
00217         ASSERT(false, "should never get here");
00218 }
00219 
00220 
00221 
00222 point3d_t
00223 operator *
00224 (
00225 IN const point3d_t& p,
00226 IN float r
00227 )
00228 throw()
00229 {
00230         point3d_t x = p;
00231         x.scale(r);
00232         return x;
00233 }
00234 
00235 
00236 
00237 const vector3d_t&
00238 normalize
00239 (
00240 IO vector3d_t& v
00241 )
00242 throw()
00243 {
00244         float sum = v.x * v.x + v.y * v.y + v.z * v.z;
00245         if (0 == sum)
00246                 return v;
00247 
00248         sum = 1.0 / sqrt(sum);
00249         v.x *= sum;
00250         v.y *= sum;
00251         v.z *= sum;
00252 
00253         return v;
00254 }
00255 
00256 
00257 
00258 point3d_t
00259 readPoint
00260 (
00261 IN std::istream& stream
00262 )
00263 {
00264         point3d_t p;
00265         std::string token;
00266 
00267         expectToken(stream, "{");
00268         expectToken(stream, "x");
00269         p.x = readFloat(stream, token);
00270         expectToken(stream, "y");
00271         p.y = readFloat(stream, token);
00272         expectToken(stream, "z");
00273         p.z = readFloat(stream, token);
00274         expectToken(stream, "}");
00275 
00276         return p;
00277 }
00278 
00279 
00280 
00281 rect3d_t
00282 readRect
00283 (
00284 IN std::istream& stream
00285 )
00286 {
00287         rect3d_t r;
00288         std::string token;
00289 
00290         expectToken(stream, "{");
00291         expectToken(stream, "x0");
00292         r.x0 = readFloat(stream, token);
00293         expectToken(stream, "x1");
00294         r.x1 = readFloat(stream, token);
00295         expectToken(stream, "y0");
00296         r.y0 = readFloat(stream, token);
00297         expectToken(stream, "y1");
00298         r.y1 = readFloat(stream, token);
00299         expectToken(stream, "z0");
00300         r.z0 = readFloat(stream, token);
00301         expectToken(stream, "z1");
00302         r.z1 = readFloat(stream, token);
00303         expectToken(stream, "}");
00304 
00305         return r;
00306 }
00307 
00308 
00309 
00310 void
00311 parsePoint3d
00312 (
00313 IO std::istream& stream,
00314 OUT point3d_t& p
00315 )
00316 {
00317         ASSERT(stream.good(), "bad?");
00318 
00319         dictionary_t d;
00320         getDictionaryFromLine(stream, "3D point", d);
00321 //      DPRINTF("Point dictionary:");
00322 //      for (Dictionary::iterator i = d.begin(); i != d.end(); ++i) {
00323 //              DPRINTF("  '%s' = '%s'", i->first.c_str(), i->second.c_str());
00324 //      }
00325         parsePointFromDictionary(d, p);
00326 }
00327 
00328 
00329 
00330 void
00331 parseRect3d
00332 (
00333 IO std::istream& stream,
00334 OUT rect3d_t& rect
00335 )
00336 {
00337         ASSERT(stream.good(), "bad?");
00338 
00339         dictionary_t d;
00340         getDictionaryFromLine(stream, "3D rectangle", d);
00341         parseRectFromDictionary(d, rect);
00342 }
00343 
00344 
00345 
00346 void
00347 parsePoint3d
00348 (
00349 IN const char * string,
00350 OUT point3d_t& p
00351 )
00352 {
00353         ASSERT(string, "null");
00354 
00355         dictionary_t d;
00356         getDictionaryFromString(string, "3D point", d);
00357         parsePointFromDictionary(d, p);
00358 }
00359 
00360 
00361 
00362 void
00363 parseRect3d
00364 (
00365 IN const char * string,
00366 OUT rect3d_t& r
00367 )
00368 {
00369         ASSERT(string, "null");
00370 
00371         dictionary_t d;
00372         getDictionaryFromString(string, "3D rectangle", d);
00373         parseRectFromDictionary(d, r);
00374 }
00375