1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef _BGFX_POINT_B3DHOMPOINT_HXX 25 #define _BGFX_POINT_B3DHOMPOINT_HXX 26 27 #include <basegfx/point/b3dpoint.hxx> 28 29 namespace basegfx 30 { 31 /** Basic homogen Point class with three double values and one homogen factor 32 33 This class provides access to homogen coordinates in 3D. 34 For this purpose all the operators which need to do specific 35 action due to their homogenity are implemented here. 36 The only caveat are member methods which are declared as const 37 but do change the content. These are documented for that reason. 38 The class is designed to provide homogenous coordinates without 39 direct access to the homogen part (mfW). This is also the reason 40 for leaving out the [] operators which return references to members. 41 42 @see B3DTuple 43 */ 44 class B3DHomPoint 45 { 46 protected: 47 /// This member contains the coordinate part of the point 48 ::basegfx::B3DTuple maTuple; 49 50 /// This Member holds the homogenous part of the point 51 double mfW; 52 53 /** Test if this homogen point does have a homogenous part 54 55 @return Returns true if this point has no homogenous part 56 */ implIsHomogenized() const57 bool implIsHomogenized() const 58 { 59 const double fOne(1.0); 60 return ::basegfx::fTools::equal(mfW, fOne); 61 } 62 63 /** Remove homogenous part of this Point 64 65 This method does necessary calculations to remove 66 the evtl. homogenous part of this Point. This may 67 change all members. 68 */ 69 void implHomogenize(); 70 71 /** Test and on demand remove homogenous part 72 73 This method tests if this Point does have a homogenous part 74 and then evtl. takes actions to remove that part. 75 76 @attention Even when this method is const it may change all 77 members of this instance. This is due to the fact that changing 78 the homogenous part of a homogenous point does from a mathematical 79 point of view not change the point at all. 80 */ implTestAndHomogenize() const81 void implTestAndHomogenize() const 82 { 83 if(!implIsHomogenized()) 84 ((B3DHomPoint*)this)->implHomogenize(); 85 } 86 87 public: 88 /** Create a homogen point 89 90 The point is initialized to (0.0, 0.0, 0.0) 91 */ B3DHomPoint()92 B3DHomPoint() 93 : maTuple(), 94 mfW(1.0) 95 {} 96 97 /** Create a homogen point 98 99 @param fX 100 This parameter is used to initialize the X-coordinate 101 of the Point. The homogenous part is initialized to 1.0. 102 103 @param fY 104 This parameter is used to initialize the Y-coordinate 105 of the Point. The homogenous part is initialized to 1.0. 106 107 @param fZ 108 This parameter is used to initialize the Z-coordinate 109 of the Point. The homogenous part is initialized to 1.0. 110 */ B3DHomPoint(double fX,double fY,double fZ)111 B3DHomPoint(double fX, double fY, double fZ) 112 : maTuple(fX, fY, fZ), 113 mfW(1.0) 114 {} 115 116 /** Create a copy of a 3D Point 117 118 @param rVec 119 The 3D point which will be copied. The homogenous part 120 is initialized to 1.0. 121 */ B3DHomPoint(const B3DPoint & rVec)122 B3DHomPoint(const B3DPoint& rVec) 123 : maTuple(rVec), 124 mfW(1.0) 125 {} 126 127 /** Create a copy of a homogen point 128 129 @param rVec 130 The homogen point which will be copied. The homogenous part 131 is copied, too. 132 */ B3DHomPoint(const B3DHomPoint & rVec)133 B3DHomPoint(const B3DHomPoint& rVec) 134 : maTuple(rVec.maTuple.getX(), rVec.maTuple.getY(), rVec.maTuple.getZ()), 135 mfW(rVec.mfW) 136 {} 137 ~B3DHomPoint()138 ~B3DHomPoint() 139 {} 140 141 /** get a 3D point from this homogenous point 142 143 This method normalizes this homogen point if necessary and 144 returns the corresponding 3D point for this homogen point. 145 146 @attention Even when this method is const it may change all 147 members of this instance. 148 */ getB3DPoint() const149 B3DPoint getB3DPoint() const 150 { 151 implTestAndHomogenize(); 152 return B3DPoint(maTuple.getX(), maTuple.getY(), maTuple.getZ()); 153 } 154 155 /** get X-coordinate 156 157 This method normalizes this homogen point if necessary and 158 returns the corresponding X-coordinate for this homogen point. 159 160 @attention Even when this method is const it may change all 161 members of this instance. 162 */ getX() const163 double getX() const 164 { 165 implTestAndHomogenize(); 166 return maTuple.getX(); 167 } 168 169 /** get Y-coordinate 170 171 This method normalizes this homogen point if necessary and 172 returns the corresponding Y-coordinate for this homogen point. 173 174 @attention Even when this method is const it may change all 175 members of this instance. 176 */ getY() const177 double getY() const 178 { 179 implTestAndHomogenize(); 180 return maTuple.getY(); 181 } 182 183 /** get Z-coordinate 184 185 This method normalizes this homogen point if necessary and 186 returns the corresponding Z-coordinate for this homogen point. 187 188 @attention Even when this method is const it may change all 189 members of this instance. 190 */ getZ() const191 double getZ() const 192 { 193 implTestAndHomogenize(); 194 return maTuple.getY(); 195 } 196 197 /** Set X-coordinate of the homogen point. 198 199 This method sets the X-coordinate of the homogen point. If 200 the point does have a homogenous part this is taken into account. 201 202 @param fX 203 The to-be-set X-coordinate without homogenous part. 204 */ setX(double fX)205 void setX(double fX) 206 { 207 maTuple.setX(implIsHomogenized() ? fX : fX * mfW ); 208 } 209 210 /** Set Y-coordinate of the homogen point. 211 212 This method sets the Y-coordinate of the homogen point. If 213 the point does have a homogenous part this is taken into account. 214 215 @param fY 216 The to-be-set Y-coordinate without homogenous part. 217 */ setY(double fY)218 void setY(double fY) 219 { 220 maTuple.setY(implIsHomogenized() ? fY : fY * mfW ); 221 } 222 223 /** Set Z-coordinate of the homogen point. 224 225 This method sets the Z-coordinate of the homogen point. If 226 the point does have a homogenous part this is taken into account. 227 228 @param fZ 229 The to-be-set Z-coordinate without homogenous part. 230 */ setZ(double fZ)231 void setZ(double fZ) 232 { 233 maTuple.setZ(implIsHomogenized() ? fZ : fZ * mfW ); 234 } 235 236 // operators 237 ////////////////////////////////////////////////////////////////////// 238 operator +=(const B3DHomPoint & rPnt)239 B3DHomPoint& operator+=( const B3DHomPoint& rPnt ) 240 { 241 maTuple.setX(getX() * rPnt.mfW + rPnt.getX() * mfW); 242 maTuple.setY(getY() * rPnt.mfW + rPnt.getY() * mfW); 243 maTuple.setZ(getZ() * rPnt.mfW + rPnt.getZ() * mfW); 244 mfW = mfW * rPnt.mfW; 245 246 return *this; 247 } 248 operator -=(const B3DHomPoint & rPnt)249 B3DHomPoint& operator-=( const B3DHomPoint& rPnt ) 250 { 251 maTuple.setX(getX() * rPnt.mfW - rPnt.getX() * mfW); 252 maTuple.setY(getY() * rPnt.mfW - rPnt.getY() * mfW); 253 maTuple.setZ(getZ() * rPnt.mfW - rPnt.getZ() * mfW); 254 mfW = mfW * rPnt.mfW; 255 256 return *this; 257 } 258 operator *=(double t)259 B3DHomPoint& operator*=(double t) 260 { 261 if(!::basegfx::fTools::equalZero(t)) 262 { 263 mfW /= t; 264 } 265 266 return *this; 267 } 268 operator /=(double t)269 B3DHomPoint& operator/=(double t) 270 { 271 mfW *= t; 272 return *this; 273 } 274 operator -(void)275 B3DHomPoint& operator-(void) 276 { 277 mfW = -mfW; 278 return *this; 279 } 280 operator ==(const B3DHomPoint & rPnt) const281 bool operator==( const B3DHomPoint& rPnt ) const 282 { 283 implTestAndHomogenize(); 284 return (maTuple == rPnt.maTuple); 285 } 286 operator !=(const B3DHomPoint & rPnt) const287 bool operator!=( const B3DHomPoint& rPnt ) const 288 { 289 implTestAndHomogenize(); 290 return (maTuple != rPnt.maTuple); 291 } 292 operator =(const B3DHomPoint & rPnt)293 B3DHomPoint& operator=( const B3DHomPoint& rPnt ) 294 { 295 maTuple = rPnt.maTuple; 296 mfW = rPnt.mfW; 297 return *this; 298 } 299 }; 300 301 // external operators 302 ////////////////////////////////////////////////////////////////////////// 303 minimum(const B3DHomPoint & rVecA,const B3DHomPoint & rVecB)304 inline B3DHomPoint minimum(const B3DHomPoint& rVecA, const B3DHomPoint& rVecB) 305 { 306 return B3DHomPoint( // getX()/getY()/getZ() homogenizes already 307 std::min(rVecB.getX(), rVecA.getX()), 308 std::min(rVecB.getY(), rVecA.getY()), 309 std::min(rVecB.getZ(), rVecA.getZ())); 310 } 311 maximum(const B3DHomPoint & rVecA,const B3DHomPoint & rVecB)312 inline B3DHomPoint maximum(const B3DHomPoint& rVecA, const B3DHomPoint& rVecB) 313 { 314 return B3DHomPoint(// getX()/getY()/getZ() homogenizes already 315 std::max(rVecB.getX(), rVecA.getX()), 316 std::max(rVecB.getY(), rVecA.getY()), 317 std::max(rVecB.getZ(), rVecA.getZ())); 318 } 319 absolute(const B3DHomPoint & rVec)320 inline B3DHomPoint absolute(const B3DHomPoint& rVec) 321 { 322 return B3DHomPoint(// getX()/getY()/getZ() homogenizes already 323 fabs(rVec.getX()), 324 fabs(rVec.getY()), 325 fabs(rVec.getZ())); 326 } 327 interpolate(B3DHomPoint & rOld1,B3DHomPoint & rOld2,double t)328 inline B3DHomPoint interpolate(B3DHomPoint& rOld1, B3DHomPoint& rOld2, double t) 329 { 330 if(0.0 >= t) 331 { 332 return rOld1; 333 } 334 else if(1.0 <= t) 335 { 336 return rOld2; 337 } 338 else if(rOld1 == rOld2) // this call homogenizes already 339 { 340 return rOld1; 341 } 342 else 343 { 344 return B3DHomPoint( 345 ((rOld2.getX() - rOld1.getX()) * t) + rOld1.getX(), 346 ((rOld2.getY() - rOld1.getY()) * t) + rOld1.getY(), 347 ((rOld2.getZ() - rOld1.getZ()) * t) + rOld1.getZ()); 348 } 349 } 350 average(B3DHomPoint & rOld1,B3DHomPoint & rOld2)351 inline B3DHomPoint average(B3DHomPoint& rOld1, B3DHomPoint& rOld2) 352 { 353 return B3DHomPoint( // getX()/getY()/getZ() homogenizes already 354 rOld1.getX() == rOld2.getX() ? rOld1.getX() : (rOld1.getX() + rOld2.getX()) * 0.5, 355 rOld1.getY() == rOld2.getY() ? rOld1.getY() : (rOld1.getY() + rOld2.getY()) * 0.5, 356 rOld1.getY() == rOld2.getY() ? rOld1.getY() : (rOld1.getY() + rOld2.getY()) * 0.5); 357 } 358 average(B3DHomPoint & rOld1,B3DHomPoint & rOld2,B3DHomPoint & rOld3)359 inline B3DHomPoint average(B3DHomPoint& rOld1, B3DHomPoint& rOld2, B3DHomPoint& rOld3) 360 { 361 return B3DHomPoint( // getX()/getY()/getZ() homogenizes already 362 (rOld1.getX() == rOld2.getX() && rOld2.getX() == rOld3.getX()) ? rOld1.getX() : (rOld1.getX() + rOld2.getX() + rOld3.getX()) * (1.0 / 3.0), 363 (rOld1.getY() == rOld2.getY() && rOld2.getY() == rOld3.getY()) ? rOld1.getY() : (rOld1.getY() + rOld2.getY() + rOld3.getY()) * (1.0 / 3.0), 364 (rOld1.getZ() == rOld2.getZ() && rOld2.getZ() == rOld3.getZ()) ? rOld1.getZ() : (rOld1.getZ() + rOld2.getZ() + rOld3.getZ()) * (1.0 / 3.0)); 365 } 366 operator +(const B3DHomPoint & rVecA,const B3DHomPoint & rVecB)367 inline B3DHomPoint operator+(const B3DHomPoint& rVecA, const B3DHomPoint& rVecB) 368 { 369 B3DHomPoint aSum(rVecA); 370 aSum += rVecB; 371 return aSum; 372 } 373 operator -(const B3DHomPoint & rVecA,const B3DHomPoint & rVecB)374 inline B3DHomPoint operator-(const B3DHomPoint& rVecA, const B3DHomPoint& rVecB) 375 { 376 B3DHomPoint aSub(rVecA); 377 aSub -= rVecB; 378 return aSub; 379 } 380 operator *(const B3DHomPoint & rVec,double t)381 inline B3DHomPoint operator*(const B3DHomPoint& rVec, double t) 382 { 383 B3DHomPoint aNew(rVec); 384 aNew *= t; 385 return aNew; 386 } 387 operator *(double t,const B3DHomPoint & rVec)388 inline B3DHomPoint operator*(double t, const B3DHomPoint& rVec) 389 { 390 B3DHomPoint aNew(rVec); 391 aNew *= t; 392 return aNew; 393 } 394 operator /(const B3DHomPoint & rVec,double t)395 inline B3DHomPoint operator/(const B3DHomPoint& rVec, double t) 396 { 397 B3DHomPoint aNew(rVec); 398 aNew /= t; 399 return aNew; 400 } 401 operator /(double t,const B3DHomPoint & rVec)402 inline B3DHomPoint operator/(double t, const B3DHomPoint& rVec) 403 { 404 B3DHomPoint aNew(rVec); 405 aNew /= t; 406 return aNew; 407 } 408 } // end of namespace basegfx 409 410 #endif /* _BGFX_POINT_B3DHOMPOINT_HXX */ 411