LCOV - code coverage report
Current view: top level - pencil/source/geometry - geometry_rectangle.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.57.0_covts Lines: 156 166 94.0 %
Date: 2024-04-07 11:14:42 Functions: 1 1 100.0 %

          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             : */

Generated by: LCOV version 1.16