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