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