00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "QhullError.h"
00010 #include "QhullPoint.h"
00011 #include "PointCoordinates.h"
00012
00013 #include <iterator>
00014 #include <iostream>
00015
00016 using std::istream;
00017 using std::string;
00018 using std::ws;
00019
00020 #ifdef _MSC_VER // Microsoft Visual C++ -- warning level 4
00021 #pragma warning( disable : 4996) // function was declared deprecated(strcpy, localtime, etc.)
00022 #endif
00023
00024 namespace orgQhull {
00025
00026 #//! PointCoordinates -- vector of PointCoordinates
00027
00028 #//Construct
00029 PointCoordinates::
00030 PointCoordinates()
00031 : QhullPoints()
00032 , point_coordinates()
00033 , point_comment()
00034 {
00035 makeValid();
00036 }
00037
00038 #//Construct
00039 PointCoordinates::
00040 PointCoordinates(int pointDimension)
00041 : QhullPoints(pointDimension)
00042 , point_coordinates()
00043 , point_comment()
00044 {
00045 makeValid();
00046 }
00047
00048 PointCoordinates::
00049 PointCoordinates(const std::string &aComment)
00050 : QhullPoints()
00051 , point_coordinates()
00052 , point_comment(aComment)
00053 {
00054 makeValid();
00055 }
00056
00057 PointCoordinates::
00058 PointCoordinates(int pointDimension, const std::string &aComment)
00059 : QhullPoints(pointDimension)
00060 , point_coordinates()
00061 , point_comment(aComment)
00062 {
00063 makeValid();
00064 }
00065
00066 PointCoordinates::
00067 PointCoordinates(int pointDimension, const std::string &aComment, int coordinatesCount, const coordT *c)
00068 : QhullPoints(pointDimension)
00069 , point_coordinates()
00070 , point_comment(aComment)
00071 {
00072 append(coordinatesCount, c);
00073 }
00074
00075 PointCoordinates::
00076 PointCoordinates(const PointCoordinates &other)
00077 : QhullPoints(other)
00078 , point_coordinates(other.point_coordinates)
00079 , point_comment(other.point_comment)
00080 {
00081 makeValid();
00082 }
00083
00084 PointCoordinates & PointCoordinates::
00085 operator=(const PointCoordinates &other)
00086 {
00087 point_coordinates= other.point_coordinates;
00088 point_comment= other.point_comment;
00089 makeValid();
00090 return *this;
00091 }
00092
00093 PointCoordinates::
00094 ~PointCoordinates()
00095 { }
00096
00097 #//GetSet
00098
00099 void PointCoordinates::
00100 checkValid() const
00101 {
00102 if(getCoordinates().data()!=data()
00103 || getCoordinates().count()!=coordinateCount()){
00104 throw QhullError(10060, "Qhull error: first point (%x) is not PointCoordinates.data() or count (%d) is not PointCoordinates.count (%d)", coordinateCount(), getCoordinates().count(), 0.0, data());
00105 }
00106 }
00107
00108 void PointCoordinates::
00109 setDimension(int i)
00110 {
00111 if(i<0){
00112 throw QhullError(10062, "Qhull error: can not set PointCoordinates dimension to %d", i);
00113 }
00114 int currentDimension=QhullPoints::dimension();
00115 if(currentDimension!=0 && i!=currentDimension){
00116 throw QhullError(10063, "Qhull error: can not change PointCoordinates dimension (from %d to %d)", currentDimension, i);
00117 }
00118 QhullPoints::setDimension(i);
00119 }
00120
00121
00122
00123 Coordinates::ConstIterator PointCoordinates::
00124 beginCoordinates(int pointIndex) const
00125 {
00126 return point_coordinates.begin()+indexOffset(pointIndex);
00127 }
00128
00129 Coordinates::Iterator PointCoordinates::
00130 beginCoordinates(int pointIndex)
00131 {
00132 return point_coordinates.begin()+indexOffset(pointIndex);
00133 }
00134
00135 #//Modify
00136
00137 void PointCoordinates::
00138 append(int coordinatesCount, const coordT *c)
00139 {
00140 if(coordinatesCount<=0){
00141 return;
00142 }
00143 if(includesCoordinates(c)){
00144 throw QhullError(10065, "Qhull error: can not append a subset of PointCoordinates to itself. The coordinates for point %d may move.", indexOf(c, QhullError::NOthrow));
00145 }
00146 reserveCoordinates(coordinatesCount);
00147 std::copy(c, c+coordinatesCount, std::back_inserter(point_coordinates));
00148 makeValid();
00149 }
00150
00151 void PointCoordinates::
00152 append(const PointCoordinates &other)
00153 {
00154 setDimension(other.dimension());
00155 append(other.coordinateCount(), other.data());
00156 }
00157
00158 void PointCoordinates::
00159 append(const QhullPoint &p)
00160 {
00161 setDimension(p.dimension());
00162 append(p.dimension(), p.coordinates());
00163 }
00164
00165 void PointCoordinates::
00166 appendComment(const std::string &s){
00167 if(char c= s[0] && point_comment.empty()){
00168 if(c=='-' || isdigit(c)){
00169 throw QhullError(10028, "Qhull argument error: comments can not start with a number or minus, %s", 0, 0, 0.0, s.c_str());
00170 }
00171 }
00172 point_comment += s;
00173 }
00174
00177 void PointCoordinates::
00178 appendPoints(istream &in)
00179 {
00180 int inDimension, inCount;
00181 in >> ws >> inDimension >> ws;
00182 if(!in.good()){
00183 in.clear();
00184 string remainder;
00185 getline(in, remainder);
00186 throw QhullError(10005, "Qhull error: input did not start with dimension or count -- %s", 0, 0, 0, remainder.c_str());
00187 }
00188 char c= (char)in.peek();
00189 if(c!='-' && !isdigit(c)){
00190 getline(in, point_comment);
00191 in >> ws;
00192 }
00193 in >> inCount >> ws;
00194 if(!in.good()){
00195 in.clear();
00196 string remainder;
00197 getline(in, remainder);
00198 throw QhullError(10009, "Qhull error: input did not start with dimension and count -- %d %s", inDimension, 0, 0, remainder.c_str());
00199 }
00200 c= (char)in.peek();
00201 if(c!='-' && !isdigit(c)){
00202 getline(in, point_comment);
00203 in >> ws;
00204 }
00205 if(inCount<inDimension){
00206 std::swap(inCount, inDimension);
00207 }
00208 setDimension(inDimension);
00209 reserveCoordinates(inCount*inDimension);
00210 int coordinatesCount= 0;
00211 while(!in.eof()){
00212 realT p;
00213 in >> p >> ws;
00214 if(in.fail()){
00215 in.clear();
00216 string remainder;
00217 getline(in, remainder);
00218 throw QhullError(10008, "Qhull error: failed to read coordinate %d of point %d\n %s", coordinatesCount % inDimension, coordinatesCount/inDimension, 0, remainder.c_str());
00219 }else{
00220 point_coordinates.push_back(p);
00221 coordinatesCount++;
00222 }
00223 }
00224 if(coordinatesCount != inCount*inDimension){
00225 if(coordinatesCount%inDimension==0){
00226 throw QhullError(10006, "Qhull error: expected %d %d-d PointCoordinates but read %i PointCoordinates", int(inCount), inDimension, 0.0, int(coordinatesCount/inDimension));
00227 }else{
00228 throw QhullError(10012, "Qhull error: expected %d %d-d PointCoordinates but read %i PointCoordinates plus %f extra coordinates", inCount, inDimension, float(coordinatesCount%inDimension), coordinatesCount/inDimension);
00229 }
00230 }
00231 makeValid();
00232 }
00233
00234 PointCoordinates PointCoordinates::
00235 operator+(const PointCoordinates &other) const
00236 {
00237 PointCoordinates pc= *this;
00238 pc << other;
00239 return pc;
00240 }
00241
00242 void PointCoordinates::
00243 reserveCoordinates(int newCoordinates)
00244 {
00245
00246 point_coordinates.reserve((int)point_coordinates.size()+newCoordinates);
00247 makeValid();
00248 }
00249
00250 #//Helpers
00251
00252 int PointCoordinates::
00253 indexOffset(int i) const {
00254 int n= i*dimension();
00255 int coordinatesCount= point_coordinates.count();
00256 if(i<0 || n>coordinatesCount){
00257 throw QhullError(10061, "Qhull error: point_coordinates is too short (%d) for point %d", coordinatesCount, i);
00258 }
00259 return n;
00260 }
00261
00262 }
00263
00264 #//Global functions
00265
00266 using std::endl;
00267 using std::ostream;
00268
00269 using orgQhull::Coordinates;
00270 using orgQhull::PointCoordinates;
00271
00272 ostream&
00273 operator<<(ostream &os, const PointCoordinates &p)
00274 {
00275 p.checkValid();
00276 int count= p.count();
00277 int dimension= p.dimension();
00278 string comment= p.comment();
00279 if(comment.empty()){
00280 os << dimension << endl;
00281 }else{
00282 os << dimension << " " << comment << endl;
00283 }
00284 os << count << endl;
00285 Coordinates::ConstIterator c= p.beginCoordinates();
00286 for(int i=0; i<count; i++){
00287 for(int j=0; j<dimension; j++){
00288 os << *c++ << " ";
00289 }
00290 os << endl;
00291 }
00292 return os;
00293 }
00294