Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

physics/HeightField.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: HeightField.cpp 1031 2004-02-11 20:46:36Z jungd $
00019   $Revision: 1.2 $
00020   $Date: 2004-02-11 15:46:36 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #include <physics/HeightField>
00026 
00027 #include <fstream>
00028 
00029 
00030 using std::valarray;
00031 using physics::HeightField;
00032 
00033 
00034 HeightField::HeightField()
00035   : _nx(10), _ny(10), _dx(0.5), _dy(0.5), hf(new valarray<Real>(_nx*_ny))
00036 {
00037 }
00038 
00039 
00040 HeightField::HeightField(const HeightField& heightfield)
00041   : _nx(heightfield._nx), _ny(heightfield._ny), _dx(heightfield._dx), _dy(heightfield._dy),
00042   hf(new valarray<Real>(*heightfield.hf))
00043 {
00044 }
00045 
00046 
00047 HeightField::HeightField(Int nx, Int ny, Real dx, Real dy) throw(std::invalid_argument)
00048   : _nx(nx), _ny(ny), _dx(dx), _dy(dy), hf(0)
00049 {
00050   if ((nx<2) || (ny<2) || (dx<=0.0) || (dy<=0.0))
00051     throw std::invalid_argument(Exception("Dimension or resolution arguments too small"));
00052 
00053   hf = new valarray<Real>(nx*ny);
00054 }
00055 
00056 
00057 HeightField::HeightField(ref<base::VFile> file) throw(std::invalid_argument, base::io_error)
00058   : hf(0)
00059 {
00060   load(file);
00061 }
00062 
00063 
00064 HeightField::~HeightField()
00065 {
00066   if (hf!=0)
00067     delete hf;
00068 }
00069 
00070 
00071 Real& HeightField::height(Real x, Real y) throw(std::out_of_range)
00072 {
00073   Int offset = Int((y/_dy)*Real(_nx) + x/_dx);
00074   if (offset >= hf->size())
00075     throw std::out_of_range(Exception("x or y out of range"));
00076 
00077   return (*hf)[offset];
00078 }
00079 
00080 const Real& HeightField::height(Real x, Real y) const throw(std::out_of_range)
00081 {
00082   Int offset = Int((y/_dy)*Real(_nx) + x/_dx);
00083   if (offset >= hf->size())
00084     throw std::out_of_range(Exception("x or y out of range"));
00085 
00086   return (*hf)[offset];
00087 }
00088 
00089 
00090 void HeightField::scale(Real s)
00091 {
00092   _dx *= s;
00093   _dy *= s;
00094   scaleHeights(s);
00095 }
00096 
00097 
00098 void HeightField::scaleHeights(Real s)
00099 {
00100   (*hf) *= s;
00101 }
00102 
00103 Real HeightField::maxHeight()
00104 {
00105   return hf->max();
00106 }
00107 
00108 Real HeightField::minHeight()
00109 {
00110   return hf->min();
00111 }
00112 
00113 
00114 void HeightField::setResolution(Real dx, Real dy) throw(std::invalid_argument)
00115 {
00116   if ((dx<=0.0) || (dy<=0.0))
00117     throw std::invalid_argument(Exception("Resolution parameters too small"));
00118 
00119   _dx = dx; 
00120   _dy = dy;
00121 }
00122 
00123 
00124 void HeightField::load(ref<base::VFile> file) throw(std::invalid_argument, base::io_error)
00125 {
00126   String extension = file->extension();
00127   std::istream& in = ((extension=="dat") || (extension=="thf"))?file->istream() // ASCII
00128                       :file->iostream(std::istream::in | std::istream::binary); // BINARY
00129 
00130   if (extension=="dat") {
00131     loadDATFile(in);
00132     return;
00133   }
00134   if (extension=="thf") {
00135     loadTHFFile(in);
00136     return;
00137   }
00138 
00139   throw std::invalid_argument(Exception("unsupported/unknown image file extension"));
00140 }
00141 
00142 
00143 void HeightField::save(ref<base::VFile> file) throw(std::invalid_argument, base::io_error)
00144 {
00145   throw std::runtime_error(Exception("unimplemented"));
00146 }
00147 
00148 void HeightField::loadDATFile(std::istream& in) throw(base::io_error)
00149 {
00150   throw base::io_error(Exception("DAT file loading not yet supported, sorry."));
00151 }
00152 
00153 
00154 void HeightField::loadTHFFile(std::istream& in) throw(base::io_error)
00155 {
00156   valarray<Real>* hf;
00157   Int nx, ny;
00158   Real dx,dy;
00159 
00160   // !!!This is currently not very flexible about the layout of # directives etc.
00161   String header, version;
00162   in >> header;
00163   if (header != "#TextHeightField")
00164     throw base::io_error(Exception("not a valid TextHeightField (.thf) file - doesn't have correct #TextHeightField header line"));
00165 
00166   in >> version;
00167   if (version != "#version")
00168     throw base::io_error(Exception("not a valid TextHeightField (.thf) file - no #version directive"));
00169 
00170   Real v;
00171   in >> v;
00172   if (v != 1.0)
00173     throw base::io_error(Exception(String("unknown/unsupported TextHeightField (.thf) version ")+base::realToString(v)));
00174 
00175   String tag;
00176   in >> tag;
00177   if (tag=="xdim")
00178     in >> nx;
00179   else
00180     throw base::io_error(Exception(String(String("expected xdim got ")+tag)));
00181 
00182   in >> tag;
00183   if (tag=="ydim")
00184     in >> ny;
00185   else
00186     throw base::io_error(Exception(String(String("expected ydim got ")+tag)));
00187 
00188   in >> tag;
00189   if (tag=="xres")
00190     in >> dx;
00191   else
00192     throw base::io_error(Exception(String(String("expected xres got ")+tag)));
00193 
00194   in >> tag;
00195   if (tag=="yres")
00196     in >> dy;
00197   else
00198     throw base::io_error(Exception(String(String("expected yres got ")+tag)));
00199   
00200   if ((nx<2) || (ny<2) || (dx<=0.0) || (dy<=0.0))
00201     throw base::io_error(Exception("Dimension or resolution parameters too small"));
00202 
00203   hf = new valarray<Real>(nx*ny);
00204 
00205   Int i=0;
00206   while ( i<(nx*ny) && in>>(*hf)[i]) i++;
00207 
00208   this->hf = hf;
00209   _nx = nx;
00210   _ny = ny;
00211   _dx = dx;
00212   _dy = dy;
00213 }
00214 
00215 

Generated on Thu Jul 29 15:56:23 2004 for OpenSim by doxygen 1.3.6