Line data Source code
1 : /* File: geometry_rectangle.c; Copyright and License: see below */ 2 : 3 : #include "geometry/geometry_rectangle.h" 4 : #include "u8/u8_trace.h" 5 : #include "u8/u8_log.h" 6 : #include <assert.h> 7 : #include <math.h> 8 : 9 35 : int geometry_rectangle_init_by_difference ( geometry_rectangle_t *this_, 10 : const geometry_rectangle_t *rect_a, 11 : const geometry_rectangle_t *rect_b ) 12 : { 13 35 : U8_TRACE_BEGIN(); 14 35 : assert( NULL != rect_a ); 15 35 : assert( NULL != rect_b ); 16 : 17 35 : int result = 0; 18 : 19 35 : const double a_left = geometry_rectangle_get_left( rect_a ); 20 35 : const double a_right = geometry_rectangle_get_right( rect_a ); 21 35 : const double a_top = geometry_rectangle_get_top( rect_a ); 22 35 : const double a_bottom = geometry_rectangle_get_bottom( rect_a ); 23 35 : const double b_left = geometry_rectangle_get_left( rect_b ); 24 35 : const double b_right = geometry_rectangle_get_right( rect_b ); 25 35 : const double b_top = geometry_rectangle_get_top( rect_b ); 26 35 : const double b_bottom = geometry_rectangle_get_bottom( rect_b ); 27 : 28 35 : if ( ( b_right <= a_left ) 29 35 : || ( b_bottom <= a_top ) 30 35 : || ( b_left >= a_right ) 31 34 : || ( b_top >= a_bottom ) ) 32 : { 33 : /* no intersection */ 34 1 : (*this_) = (*rect_a); 35 : } 36 : else 37 : { 38 : /* determine where to check for a suitable, maximum sub-rectangle */ 39 34 : const bool check_top = (( b_top > a_top )&&( b_top < a_bottom )); 40 34 : const bool check_bottom = (( b_bottom > a_top )&&( b_bottom < a_bottom )); 41 34 : const bool check_left = (( b_left > a_left )&&( b_left < a_right )); 42 34 : const bool check_right = (( b_right > a_left )&&( b_right < a_right )); 43 34 : bool keep_top_part = false; 44 34 : bool keep_bottom_part = false; 45 34 : bool keep_left_part = false; 46 34 : bool keep_right_part = false; 47 34 : if ( check_top ) 48 : { 49 20 : if ( check_bottom ) 50 : { 51 13 : if ( check_left ) 52 : { 53 7 : if ( check_right ) 54 : { 55 4 : U8_TRACE_INFO( "to.bo.le.ri." ); 56 : /* 4 possible solutions */ 57 4 : const double area_top = geometry_rectangle_get_width( rect_a ) * ( b_top-a_top ); 58 4 : const double area_bottom = geometry_rectangle_get_width( rect_a ) * ( a_bottom-b_bottom ); 59 4 : const double area_left = ( b_left-a_left ) * geometry_rectangle_get_height( rect_a ); 60 4 : const double area_right = ( a_right-b_right ) * geometry_rectangle_get_height( rect_a ); 61 4 : if (area_top>area_bottom) 62 : { 63 1 : if (area_top>area_left) 64 : { 65 1 : if (area_top>area_right) 66 : { 67 1 : keep_top_part = true; 68 : } 69 : else /* area_right is bigger */ 70 : { 71 0 : keep_right_part = true; 72 : } 73 : } 74 : else /* area_left is bigger */ 75 : { 76 0 : if (area_left>area_right) 77 : { 78 0 : keep_left_part = true; 79 : } 80 : else /* area_right is bigger */ 81 : { 82 0 : keep_right_part = true; 83 : } 84 : } 85 : } 86 : else /* area_bottom is bigger */ 87 : { 88 3 : if (area_bottom>area_left) 89 : { 90 2 : if (area_bottom>area_right) 91 : { 92 1 : keep_bottom_part = true; 93 : } 94 : else /* area_right is bigger */ 95 : { 96 1 : keep_right_part = true; 97 : } 98 : } 99 : else /* area_left is bigger */ 100 : { 101 1 : if (area_left>area_right) 102 : { 103 1 : keep_left_part = true; 104 : } 105 : else /* area_right is bigger */ 106 : { 107 0 : keep_right_part = true; 108 : } 109 : } 110 : } 111 : } 112 : else /* ! check_right */ 113 : { 114 3 : U8_TRACE_INFO( "to.bo.le." ); 115 : /* 3 possible solutions */ 116 3 : const double area_top = geometry_rectangle_get_width( rect_a ) * ( b_top-a_top ); 117 3 : const double area_bottom = geometry_rectangle_get_width( rect_a ) * ( a_bottom-b_bottom ); 118 3 : const double area_left = ( b_left-a_left ) * geometry_rectangle_get_height( rect_a ); 119 3 : if (area_top>area_bottom) 120 : { 121 1 : if (area_top>area_left) 122 : { 123 1 : keep_top_part = true; 124 : } 125 : else /* area_left is bigger */ 126 : { 127 0 : keep_left_part = true; 128 : } 129 : } 130 : else /* area_bottom is bigger */ 131 : { 132 2 : if (area_bottom>area_left) 133 : { 134 1 : keep_bottom_part = true; 135 : } 136 : else /* area_left is bigger */ 137 : { 138 1 : keep_left_part = true; 139 : } 140 : } 141 : } 142 : } 143 : else /* ! check_left */ 144 : { 145 6 : if ( check_right ) 146 : { 147 4 : U8_TRACE_INFO( "to.bo.ri." ); 148 : /* 3 possible solutions */ 149 4 : const double area_top = geometry_rectangle_get_width( rect_a ) * ( b_top-a_top ); 150 4 : const double area_bottom = geometry_rectangle_get_width( rect_a ) * ( a_bottom-b_bottom ); 151 4 : const double area_right = ( a_right-b_right ) * geometry_rectangle_get_height( rect_a ); 152 4 : if (area_top>area_bottom) 153 : { 154 1 : if (area_top>area_right) 155 : { 156 1 : keep_top_part = true; 157 : } 158 : else /* area_right is bigger */ 159 : { 160 0 : keep_right_part = true; 161 : } 162 : } 163 : else /* area_bottom is bigger */ 164 : { 165 3 : if (area_bottom>area_right) 166 : { 167 2 : keep_bottom_part = true; 168 : } 169 : else /* area_right is bigger */ 170 : { 171 1 : keep_right_part = true; 172 : } 173 : } 174 : } 175 : else /* ! check_right */ 176 : { 177 2 : U8_TRACE_INFO( "to.bo." ); 178 : /* 2 possible solutions */ 179 2 : if (( b_top-a_top )>( a_bottom-b_bottom )) 180 : { 181 1 : keep_top_part = true; 182 : } 183 : else 184 : { 185 1 : keep_bottom_part = true; 186 : } 187 : } 188 : } 189 : } 190 : else /* ! check_bottom */ 191 : { 192 7 : if ( check_left ) 193 : { 194 5 : if ( check_right ) 195 : { 196 3 : U8_TRACE_INFO( "to.le.ri." ); 197 : /* 3 possible solutions */ 198 3 : const double area_top = geometry_rectangle_get_width( rect_a ) * ( b_top-a_top ); 199 3 : const double area_left = ( b_left-a_left ) * geometry_rectangle_get_height( rect_a ); 200 3 : const double area_right = ( a_right-b_right ) * geometry_rectangle_get_height( rect_a ); 201 3 : if (area_top>area_left) 202 : { 203 1 : if (area_top>area_right) 204 : { 205 1 : keep_top_part = true; 206 : } 207 : else /* area_right is bigger */ 208 : { 209 0 : keep_right_part = true; 210 : } 211 : } 212 : else /* area_left is bigger */ 213 : { 214 2 : if (area_left>area_right) 215 : { 216 1 : keep_left_part = true; 217 : } 218 : else /* area_right is bigger */ 219 : { 220 1 : keep_right_part = true; 221 : } 222 : } 223 : } 224 : else /* ! check_right */ 225 : { 226 2 : U8_TRACE_INFO( "to.le." ); 227 : /* 2 possible solutions */ 228 2 : const double area_top = geometry_rectangle_get_width( rect_a ) * ( b_top-a_top ); 229 2 : const double area_left = ( b_left-a_left ) * geometry_rectangle_get_height( rect_a ); 230 2 : if (area_top>area_left) 231 : { 232 1 : keep_top_part = true; 233 : } 234 : else /* area_left is bigger */ 235 : { 236 1 : keep_left_part = true; 237 : } 238 : } 239 : 240 : } 241 : else /* ! check_left */ 242 : { 243 2 : if ( check_right ) 244 : { 245 1 : U8_TRACE_INFO( "to.ri." ); 246 : /* 2 possible solutions */ 247 1 : const double area_top = geometry_rectangle_get_width( rect_a ) * ( b_top-a_top ); 248 1 : const double area_right = ( a_right-b_right ) * geometry_rectangle_get_height( rect_a ); 249 1 : if (area_top>area_right) 250 : { 251 0 : keep_top_part = true; 252 : } 253 : else /* area_right is bigger */ 254 : { 255 1 : keep_right_part = true; 256 : } 257 : } 258 : else /* ! check_right */ 259 : { 260 1 : U8_TRACE_INFO( "to." ); 261 : /* 1 solution */ 262 1 : keep_top_part = true; 263 : } 264 : } 265 : } 266 : } 267 : else /* ! check_top */ 268 : { 269 14 : if ( check_bottom ) 270 : { 271 9 : if ( check_left ) 272 : { 273 6 : if ( check_right ) 274 : { 275 3 : U8_TRACE_INFO( "bo.le.ri." ); 276 : /* 3 possible solutions */ 277 3 : const double area_bottom = geometry_rectangle_get_width( rect_a ) * ( a_bottom-b_bottom ); 278 3 : const double area_left = ( b_left-a_left ) * geometry_rectangle_get_height( rect_a ); 279 3 : const double area_right = ( a_right-b_right ) * geometry_rectangle_get_height( rect_a ); 280 3 : if (area_bottom>area_left) 281 : { 282 1 : if (area_bottom>area_right) 283 : { 284 1 : keep_bottom_part = true; 285 : } 286 : else /* area_right is bigger */ 287 : { 288 0 : keep_right_part = true; 289 : } 290 : } 291 : else /* area_left is bigger */ 292 : { 293 2 : if (area_left>area_right) 294 : { 295 1 : keep_left_part = true; 296 : } 297 : else /* area_right is bigger */ 298 : { 299 1 : keep_right_part = true; 300 : } 301 : } 302 : } 303 : else /* ! check_right */ 304 : { 305 3 : U8_TRACE_INFO( "bo.le." ); 306 : /* 2 possible solutions */ 307 3 : const double area_bottom = geometry_rectangle_get_width( rect_a ) * ( a_bottom-b_bottom ); 308 3 : const double area_left = ( b_left-a_left ) * geometry_rectangle_get_height( rect_a ); 309 3 : if (area_bottom>area_left) 310 : { 311 1 : keep_bottom_part = true; 312 : } 313 : else /* area_left is bigger */ 314 : { 315 2 : keep_left_part = true; 316 : } 317 : } 318 : 319 : } 320 : else /* ! check_left */ 321 : { 322 3 : if ( check_right ) 323 : { 324 2 : U8_TRACE_INFO( "bo.ri." ); 325 : /* 2 possible solutions */ 326 2 : const double area_bottom = geometry_rectangle_get_width( rect_a ) * ( a_bottom-b_bottom ); 327 2 : const double area_right = ( a_right-b_right ) * geometry_rectangle_get_height( rect_a ); 328 2 : if (area_bottom>area_right) 329 : { 330 1 : keep_bottom_part = true; 331 : } 332 : else /* area_right is bigger */ 333 : { 334 1 : keep_right_part = true; 335 : } 336 : } 337 : else /* ! check_right */ 338 : { 339 1 : U8_TRACE_INFO( "bo." ); 340 : /* 1 solution */ 341 1 : keep_bottom_part = true; 342 : } 343 : } 344 : } 345 : else /* ! check_bottom */ 346 : { 347 5 : if ( check_left ) 348 : { 349 3 : if ( check_right ) 350 : { 351 2 : U8_TRACE_INFO( "le.ri." ); 352 : /* 2 possible solutions */ 353 2 : if (( b_left-a_left )>( a_right-b_right )) 354 : { 355 1 : keep_left_part = true; 356 : } 357 : else 358 : { 359 1 : keep_right_part = true; 360 : } 361 : } 362 : else /* ! check_right */ 363 : { 364 1 : U8_TRACE_INFO( "le." ); 365 : /* 1 solution */ 366 1 : keep_left_part = true; 367 : } 368 : 369 : } 370 : else /* ! check_left */ 371 : { 372 2 : if ( check_right ) 373 : { 374 1 : U8_TRACE_INFO( "ri." ); 375 : /* 1 solution */ 376 1 : keep_right_part = true; 377 : } 378 : else /* ! check_right */ 379 : { 380 1 : U8_TRACE_INFO( "0." ); 381 : /* rect_b contains rect_a, result is empty */ 382 : } 383 : } 384 : } 385 : } 386 : 387 34 : if ( keep_top_part ) 388 : { 389 7 : assert ( check_top ); 390 7 : U8_TRACE_INFO( "-top-" ); 391 7 : geometry_rectangle_init ( this_, a_left, a_top, geometry_rectangle_get_width( rect_a ), b_top-a_top ); 392 : } 393 27 : else if ( keep_bottom_part ) 394 : { 395 9 : assert ( check_bottom ); 396 9 : U8_TRACE_INFO( "-bottom-" ); 397 9 : geometry_rectangle_init ( this_, a_left, b_bottom, geometry_rectangle_get_width( rect_a ), a_bottom-b_bottom ); 398 : } 399 18 : else if ( keep_left_part ) 400 : { 401 9 : assert ( check_left ); 402 9 : U8_TRACE_INFO( "-left-" ); 403 9 : geometry_rectangle_init ( this_, a_left, a_top, b_left-a_left, geometry_rectangle_get_height( rect_a ) ); 404 : } 405 9 : else if ( keep_right_part ) 406 : { 407 8 : assert ( check_right ); 408 8 : U8_TRACE_INFO( "-right-" ); 409 8 : geometry_rectangle_init ( this_, b_right, a_top, a_right-b_right, geometry_rectangle_get_height( rect_a ) ); 410 : } 411 : else 412 : { 413 1 : U8_TRACE_INFO( "-none-" ); 414 1 : geometry_rectangle_init ( this_, a_left, a_top, 0.0, 0.0 ); 415 : } 416 : } 417 : 418 35 : U8_TRACE_END_ERR( result ); 419 35 : return result; 420 : } 421 : 422 : 423 : /* 424 : Copyright 2020-2024 Andreas Warnke 425 : 426 : Licensed under the Apache License, Version 2.0 (the "License"); 427 : you may not use this file except in compliance with the License. 428 : You may obtain a copy of the License at 429 : 430 : http://www.apache.org/licenses/LICENSE-2.0 431 : 432 : Unless required by applicable law or agreed to in writing, software 433 : distributed under the License is distributed on an "AS IS" BASIS, 434 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 435 : See the License for the specific language governing permissions and 436 : limitations under the License. 437 : */