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_B2DHOMPOINT_HXX 25 #define _BGFX_POINT_B2DHOMPOINT_HXX 26 27 #include <basegfx/point/b2dpoint.hxx> 28 #include <basegfx/basegfxdllapi.h> 29 30 namespace basegfx 31 { 32 /** Basic homogen Point class with two double values and one homogen factor 33 34 This class provides access to homogen coordinates in 2D. 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 B2DTuple 44 */ 45 class BASEGFX_DLLPUBLIC B2DHomPoint 46 { 47 protected: 48 /// This member contains the coordinate part of the point 49 ::basegfx::B2DTuple 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 inline bool implIsHomogenized() const 59 { 60 const double fOne(1.0); 61 return ::basegfx::fTools::equal(fOne, mfW); 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 inline void implTestAndHomogenize() const 83 { 84 if(!implIsHomogenized()) 85 ((B2DHomPoint*)this)->implHomogenize(); 86 } 87 88 public: 89 /** Create a homogen point 90 91 The point is initialized to (0.0, 0.0) 92 */ B2DHomPoint()93 B2DHomPoint() 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 */ B2DHomPoint(double fX,double fY)108 B2DHomPoint(double fX, double fY) 109 : maTuple(fX, fY), 110 mfW(1.0) 111 {} 112 113 /** Create a copy of a 2D Point 114 115 @param rVec 116 The 2D point which will be copied. The homogenous part 117 is initialized to 1.0. 118 */ B2DHomPoint(const B2DPoint & rVec)119 B2DHomPoint(const B2DPoint& rVec) 120 : maTuple(rVec), 121 mfW(1.0) 122 {} 123 124 /** Create a copy of a homogen point 125 126 @param rVec 127 The homogen point which will be copied. The homogenous part 128 is copied, too. 129 */ B2DHomPoint(const B2DHomPoint & rVec)130 B2DHomPoint(const B2DHomPoint& rVec) 131 : maTuple(rVec.maTuple.getX(), rVec.maTuple.getY()), 132 mfW(rVec.mfW) 133 {} 134 ~B2DHomPoint()135 ~B2DHomPoint() 136 {} 137 138 /** Get a 2D point from this homogenous point 139 140 This method normalizes this homogen point if necessary and 141 returns the corresponding 2D point for this homogen point. 142 143 @attention Even when this method is const it may change all 144 members of this instance. 145 */ getB2DPoint() const146 inline B2DPoint getB2DPoint() const 147 { 148 implTestAndHomogenize(); 149 return B2DPoint(maTuple.getX(), maTuple.getY()); 150 } 151 152 /** Get X-coordinate 153 154 This method normalizes this homogen point if necessary and 155 returns the corresponding X-coordinate for this homogen point. 156 157 @attention Even when this method is const it may change all 158 members of this instance. 159 */ getX() const160 inline double getX() const 161 { 162 implTestAndHomogenize(); 163 return maTuple.getX(); 164 } 165 166 /** Get Y-coordinate 167 168 This method normalizes this homogen point if necessary and 169 returns the corresponding Y-coordinate for this homogen point. 170 171 @attention Even when this method is const it may change all 172 members of this instance. 173 */ getY() const174 inline double getY() const 175 { 176 implTestAndHomogenize(); 177 return maTuple.getY(); 178 } 179 180 /** Set X-coordinate of the homogen point. 181 182 This method sets the X-coordinate of the homogen point. If 183 the point does have a homogenous part this is taken into account. 184 185 @param fX 186 The to-be-set X-coordinate without homogenous part. 187 */ setX(double fX)188 inline void setX(double fX) 189 { 190 maTuple.setX(implIsHomogenized() ? fX : fX * mfW ); 191 } 192 193 /** Set Y-coordinate of the homogen point. 194 195 This method sets the Y-coordinate of the homogen point. If 196 the point does have a homogenous part this is taken into account. 197 198 @param fY 199 The to-be-set Y-coordinate without homogenous part. 200 */ setY(double fY)201 inline void setY(double fY) 202 { 203 maTuple.setY(implIsHomogenized() ? fY : fY * mfW ); 204 } 205 206 // operators 207 ////////////////////////////////////////////////////////////////////// 208 operator +=(const B2DHomPoint & rPnt)209 inline B2DHomPoint& operator+=( const B2DHomPoint& rPnt ) 210 { 211 maTuple.setX(getX() * rPnt.mfW + rPnt.getX() * mfW); 212 maTuple.setY(getY() * rPnt.mfW + rPnt.getY() * mfW); 213 mfW = mfW * rPnt.mfW; 214 215 return *this; 216 } 217 operator -=(const B2DHomPoint & rPnt)218 inline B2DHomPoint& operator-=( const B2DHomPoint& rPnt ) 219 { 220 maTuple.setX(getX() * rPnt.mfW - rPnt.getX() * mfW); 221 maTuple.setY(getY() * rPnt.mfW - rPnt.getY() * mfW); 222 mfW = mfW * rPnt.mfW; 223 224 return *this; 225 } 226 operator *=(double t)227 inline B2DHomPoint& operator*=(double t) 228 { 229 if(!::basegfx::fTools::equalZero(t)) 230 { 231 mfW /= t; 232 } 233 234 return *this; 235 } 236 237 B2DHomPoint& operator*=( const B2DHomMatrix& rMat ); 238 operator /=(double t)239 inline B2DHomPoint& operator/=(double t) 240 { 241 mfW *= t; 242 return *this; 243 } 244 operator -(void)245 inline B2DHomPoint& operator-(void) 246 { 247 mfW = -mfW; 248 return *this; 249 } 250 operator ==(const B2DHomPoint & rPnt) const251 inline bool operator==( const B2DHomPoint& rPnt ) const 252 { 253 implTestAndHomogenize(); 254 return (maTuple == rPnt.maTuple); 255 } 256 operator !=(const B2DHomPoint & rPnt) const257 inline bool operator!=( const B2DHomPoint& rPnt ) const 258 { 259 implTestAndHomogenize(); 260 return (maTuple != rPnt.maTuple); 261 } 262 operator =(const B2DHomPoint & rPnt)263 inline B2DHomPoint& operator=( const B2DHomPoint& rPnt ) 264 { 265 maTuple = rPnt.maTuple; 266 mfW = rPnt.mfW; 267 return *this; 268 } 269 }; 270 271 // external operators 272 ////////////////////////////////////////////////////////////////////////// 273 minimum(const B2DHomPoint & rVecA,const B2DHomPoint & rVecB)274 inline B2DHomPoint minimum(const B2DHomPoint& rVecA, const B2DHomPoint& rVecB) 275 { 276 return B2DHomPoint( // getX()/getY() homogenizes already 277 std::min(rVecB.getX(), rVecA.getX()), 278 std::min(rVecB.getY(), rVecA.getY())); 279 } 280 maximum(const B2DHomPoint & rVecA,const B2DHomPoint & rVecB)281 inline B2DHomPoint maximum(const B2DHomPoint& rVecA, const B2DHomPoint& rVecB) 282 { 283 return B2DHomPoint( // getX()/getY() homogenizes already 284 std::max(rVecB.getX(), rVecA.getX()), 285 std::max(rVecB.getY(), rVecA.getY())); 286 } 287 absolute(const B2DHomPoint & rVec)288 inline B2DHomPoint absolute(const B2DHomPoint& rVec) 289 { 290 return B2DHomPoint( // getX()/getY() homogenizes already 291 fabs(rVec.getX()), 292 fabs(rVec.getY())); 293 } 294 interpolate(B2DHomPoint & rOld1,B2DHomPoint & rOld2,double t)295 inline B2DHomPoint interpolate(B2DHomPoint& rOld1, B2DHomPoint& rOld2, double t) 296 { 297 if(0.0 >= t) 298 { 299 return rOld1; 300 } 301 else if(1.0 <= t) 302 { 303 return rOld2; 304 } 305 else if(rOld1 == rOld2) // this call homogenizes already 306 { 307 return rOld1; 308 } 309 else 310 { 311 return B2DHomPoint( 312 ((rOld2.getX() - rOld1.getX()) * t) + rOld1.getX(), 313 ((rOld2.getY() - rOld1.getY()) * t) + rOld1.getY()); 314 } 315 } 316 average(B2DHomPoint & rOld1,B2DHomPoint & rOld2)317 inline B2DHomPoint average(B2DHomPoint& rOld1, B2DHomPoint& rOld2) 318 { 319 return B2DHomPoint( // getX()/ getY() homogenizes already 320 rOld1.getX() == rOld2.getX() ? rOld1.getX() : (rOld1.getX() + rOld2.getX()) * 0.5, 321 rOld1.getY() == rOld2.getY() ? rOld1.getY() : (rOld1.getY() + rOld2.getY()) * 0.5); 322 } 323 average(B2DHomPoint & rOld1,B2DHomPoint & rOld2,B2DHomPoint & rOld3)324 inline B2DHomPoint average(B2DHomPoint& rOld1, B2DHomPoint& rOld2, B2DHomPoint& rOld3) 325 { 326 return B2DHomPoint( // getX()/ getY() homogenizes already 327 (rOld1.getX() == rOld2.getX() && rOld2.getX() == rOld3.getX()) ? rOld1.getX() : (rOld1.getX() + rOld2.getX() + rOld3.getX()) * (1.0 / 3.0), 328 (rOld1.getY() == rOld2.getY() && rOld2.getY() == rOld3.getY()) ? rOld1.getY() : (rOld1.getY() + rOld2.getY() + rOld3.getY()) * (1.0 / 3.0)); 329 } 330 operator +(const B2DHomPoint & rVecA,const B2DHomPoint & rVecB)331 inline B2DHomPoint operator+(const B2DHomPoint& rVecA, const B2DHomPoint& rVecB) 332 { 333 B2DHomPoint aSum(rVecA); 334 aSum += rVecB; 335 return aSum; 336 } 337 operator -(const B2DHomPoint & rVecA,const B2DHomPoint & rVecB)338 inline B2DHomPoint operator-(const B2DHomPoint& rVecA, const B2DHomPoint& rVecB) 339 { 340 B2DHomPoint aSub(rVecA); 341 aSub -= rVecB; 342 return aSub; 343 } 344 operator *(const B2DHomPoint & rVec,double t)345 inline B2DHomPoint operator*(const B2DHomPoint& rVec, double t) 346 { 347 B2DHomPoint aNew(rVec); 348 aNew *= t; 349 return aNew; 350 } 351 operator *(double t,const B2DHomPoint & rVec)352 inline B2DHomPoint operator*(double t, const B2DHomPoint& rVec) 353 { 354 B2DHomPoint aNew(rVec); 355 aNew *= t; 356 return aNew; 357 } 358 operator *(const B2DHomMatrix & rMat,const B2DHomPoint & rPoint)359 inline B2DHomPoint operator*( const B2DHomMatrix& rMat, const B2DHomPoint& rPoint ) 360 { 361 B2DHomPoint aNew(rPoint); 362 return aNew*=rMat; 363 } 364 operator /(const B2DHomPoint & rVec,double t)365 inline B2DHomPoint operator/(const B2DHomPoint& rVec, double t) 366 { 367 B2DHomPoint aNew(rVec); 368 aNew /= t; 369 return aNew; 370 } 371 operator /(double t,const B2DHomPoint & rVec)372 inline B2DHomPoint operator/(double t, const B2DHomPoint& rVec) 373 { 374 B2DHomPoint aNew(rVec); 375 aNew /= t; 376 return aNew; 377 } 378 } // end of namespace basegfx 379 380 #endif /* _BGFX_POINT_B2DHOMPOINT_HXX */ 381