LCOV - code coverage report
Current view: top level - pencil/include/geometry - geometry_rectangle.inl (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.63.2_covts Lines: 85.5 % 227 194
Test Date: 2025-05-01 10:10:14 Functions: 79.5 % 39 31

            Line data    Source code
       1              : /* File: geometry_rectangle.inl; Copyright and License: see below */
       2              : 
       3              : #include "u8/u8_trace.h"
       4              : #include "u8/u8_log.h"
       5              : #include <assert.h>
       6              : #include <math.h>
       7              : 
       8          524 : static inline void geometry_rectangle_init ( geometry_rectangle_t *this_, double left, double top, double width, double height )
       9              : {
      10          524 :     (*this_).left = left;
      11          524 :     (*this_).top = top;
      12          524 :     (*this_).width = width;
      13          524 :     (*this_).height = height;
      14          524 : }
      15              : 
      16          783 : static inline void geometry_rectangle_reinit ( geometry_rectangle_t *this_, double left, double top, double width, double height )
      17              : {
      18          783 :     (*this_).left = left;
      19          783 :     (*this_).top = top;
      20          783 :     (*this_).width = width;
      21          783 :     (*this_).height = height;
      22          783 : }
      23              : 
      24          174 : static inline void geometry_rectangle_copy ( geometry_rectangle_t *this_, const geometry_rectangle_t *original )
      25              : {
      26          174 :     assert( NULL != original );
      27          174 :     (*this_) = (*original);
      28          174 : }
      29              : 
      30              : static inline void geometry_rectangle_move ( geometry_rectangle_t *this_, geometry_rectangle_t *that )
      31              : {
      32              :     assert( NULL != that );
      33              :     (*this_) = (*that);
      34              : }
      35              : 
      36         1085 : static inline void geometry_rectangle_replace ( geometry_rectangle_t *this_, const geometry_rectangle_t *original )
      37              : {
      38         1085 :     assert( NULL != original );
      39         1085 :     (*this_) = (*original);
      40         1085 : }
      41              : 
      42            0 : static inline void geometry_rectangle_replacemove ( geometry_rectangle_t *this_, geometry_rectangle_t *that )
      43              : {
      44            0 :     assert( NULL != that );
      45            0 :     (*this_) = (*that);
      46            0 : }
      47              : 
      48         3481 : static inline void geometry_rectangle_init_empty ( geometry_rectangle_t *this_ )
      49              : {
      50         3481 :     (*this_).left = 0.0;
      51         3481 :     (*this_).top = 0.0;
      52         3481 :     (*this_).width = 0.0;
      53         3481 :     (*this_).height = 0.0;
      54         3481 : }
      55              : 
      56              : static inline void geometry_rectangle_reinit_empty ( geometry_rectangle_t *this_ )
      57              : {
      58              :     (*this_).left = 0.0;
      59              :     (*this_).top = 0.0;
      60              :     (*this_).width = 0.0;
      61              :     (*this_).height = 0.0;
      62              : }
      63              : 
      64          180 : static inline int geometry_rectangle_init_by_intersect ( geometry_rectangle_t *this_,
      65              :                                                          const geometry_rectangle_t *rect_a,
      66              :                                                          const geometry_rectangle_t *rect_b )
      67              : {
      68          180 :     assert( NULL != rect_a );
      69          180 :     assert( NULL != rect_b );
      70              : 
      71          180 :     int result = 0;
      72              : 
      73          180 :     const double rect_a_right = (*rect_a).left + (*rect_a).width;
      74          180 :     const double rect_a_bottom = (*rect_a).top + (*rect_a).height;
      75          180 :     const double rect_b_right = (*rect_b).left + (*rect_b).width;
      76          180 :     const double rect_b_bottom = (*rect_b).top + (*rect_b).height;
      77              : 
      78          180 :     (*this_).left = fmax( (*rect_a).left, (*rect_b).left );
      79          180 :     (*this_).top = fmax( (*rect_a).top, (*rect_b).top );
      80          180 :     (*this_).width = fmin( rect_a_right, rect_b_right ) - (*this_).left;
      81          180 :     (*this_).height = fmin( rect_a_bottom, rect_b_bottom ) - (*this_).top;
      82          180 :     if (( (*this_).width < -0.000000001 ) || ( (*this_).height < -0.000000001 ))
      83              :     {
      84              :         /* if intersection is empty, result is -1 */
      85           25 :         (*this_).left = 0.0;
      86           25 :         (*this_).top = 0.0;
      87           25 :         (*this_).width = 0.0;
      88           25 :         (*this_).height = 0.0;
      89           25 :         result = -1;
      90              :     }
      91          155 :     else if (( (*this_).width < 0.0 ) || ( (*this_).height < 0.0 ))
      92              :     {
      93              :         /* update rounding error */
      94           63 :         (*this_).width = 0.0;
      95           63 :         (*this_).height = 0.0;
      96              :     }
      97              : 
      98          180 :     return result;
      99              : }
     100              : 
     101         1537 : static inline int geometry_rectangle_init_by_bounds ( geometry_rectangle_t *this_,
     102              :                                                       const geometry_rectangle_t *rect_a,
     103              :                                                       const geometry_rectangle_t *rect_b )
     104              : {
     105         1537 :     assert( NULL != rect_a );
     106         1537 :     assert( NULL != rect_b );
     107              : 
     108         1537 :     int result = 0;
     109              : 
     110         1537 :     const double rect_a_right = (*rect_a).left + (*rect_a).width;
     111         1537 :     const double rect_a_bottom = (*rect_a).top + (*rect_a).height;
     112         1537 :     const double rect_b_right = (*rect_b).left + (*rect_b).width;
     113         1537 :     const double rect_b_bottom = (*rect_b).top + (*rect_b).height;
     114              : 
     115         1537 :     (*this_).left = fmin( (*rect_a).left, (*rect_b).left );
     116         1537 :     (*this_).top = fmin( (*rect_a).top, (*rect_b).top );
     117         1537 :     (*this_).width = fmax( rect_a_right, rect_b_right ) - (*this_).left;
     118         1537 :     (*this_).height = fmax( rect_a_bottom, rect_b_bottom ) - (*this_).top;
     119              : 
     120         1537 :     return result;
     121              : }
     122              : 
     123           32 : static inline bool geometry_rectangle_is_intersecting ( const geometry_rectangle_t *this_, const geometry_rectangle_t *that )
     124              : {
     125           32 :     assert( NULL != that );
     126              : 
     127              :     bool result;
     128              : 
     129           32 :     const double rect_this_right = (*this_).left + (*this_).width;
     130           32 :     const double rect_this_bottom = (*this_).top + (*this_).height;
     131           32 :     const double rect_that_right = (*that).left + (*that).width;
     132           32 :     const double rect_that_bottom = (*that).top + (*that).height;
     133              : 
     134           32 :     if ( ( rect_this_right < (*that).left + 0.000000001 )
     135           25 :         || ( rect_this_bottom < (*that).top + 0.000000001 )
     136           15 :         || ( (*this_).left + 0.000000001 > rect_that_right )
     137            8 :         || ( (*this_).top + 0.000000001 > rect_that_bottom ) )
     138              :     {
     139           28 :         result = false;
     140              :     }
     141              :     else
     142              :     {
     143            4 :         result = true;
     144              :     }
     145              : 
     146           32 :     return result;
     147              : }
     148              : 
     149           52 : static inline bool geometry_rectangle_is_contiguous ( const geometry_rectangle_t *this_, const geometry_rectangle_t *that )
     150              : {
     151           52 :     assert( NULL != that );
     152              : 
     153              :     bool result;
     154              : 
     155           52 :     const double rect_this_right = (*this_).left + (*this_).width;
     156           52 :     const double rect_this_bottom = (*this_).top + (*this_).height;
     157           52 :     const double rect_that_right = (*that).left + (*that).width;
     158           52 :     const double rect_that_bottom = (*that).top + (*that).height;
     159              : 
     160           52 :     if ( ( rect_this_right + 0.000000001 < (*that).left )
     161           41 :         || ( rect_this_bottom + 0.000000001 < (*that).top )
     162           38 :         || ( (*this_).left > rect_that_right + 0.000000001 )
     163           31 :         || ( (*this_).top > rect_that_bottom + 0.000000001 ) )
     164              :     {
     165           25 :         result = false;
     166              :     }
     167              :     else
     168              :     {
     169           27 :         result = true;
     170              :     }
     171              : 
     172           52 :     return result;
     173              : }
     174              : 
     175          464 : static inline bool geometry_rectangle_is_containing ( const geometry_rectangle_t *this_, const geometry_rectangle_t *that )
     176              : {
     177          464 :     assert( NULL != that );
     178              : 
     179              :     bool result;
     180              : 
     181          464 :     const double rect_this_right = (*this_).left + (*this_).width;
     182          464 :     const double rect_this_bottom = (*this_).top + (*this_).height;
     183          464 :     const double rect_that_right = (*that).left + (*that).width;
     184          464 :     const double rect_that_bottom = (*that).top + (*that).height;
     185              : 
     186          464 :     if ( ( (*this_).left < (*that).left + 0.000000001 ) /* touching is containing */
     187          399 :         && ( (*this_).top < (*that).top + 0.000000001 )
     188          398 :         && ( rect_this_right + 0.000000001 > rect_that_right )
     189          397 :         && ( rect_this_bottom + 0.000000001 > rect_that_bottom ) )
     190              :     {
     191          397 :         result = true;
     192              :     }
     193              :     else
     194              :     {
     195           67 :         result = false;
     196              :     }
     197              : 
     198          464 :     return result;
     199              : }
     200              : 
     201           72 : static inline void geometry_rectangle_init_by_corners ( geometry_rectangle_t *this_, double x1, double y1, double x2, double y2 )
     202              : {
     203           72 :     if ( x1 < x2 )
     204              :     {
     205           16 :         (*this_).left = x1;
     206           16 :         (*this_).width = x2-x1;
     207              :     }
     208              :     else
     209              :     {
     210           56 :         (*this_).left = x2;
     211           56 :         (*this_).width = x1-x2;
     212              :     }
     213           72 :     if ( y1 < y2 )
     214              :     {
     215           19 :         (*this_).top = y1;
     216           19 :         (*this_).height = y2-y1;
     217              :     }
     218              :     else
     219              :     {
     220           53 :         (*this_).top = y2;
     221           53 :         (*this_).height = y1-y2;
     222              :     }
     223           72 : }
     224              : 
     225         3879 : static inline void geometry_rectangle_destroy ( geometry_rectangle_t *this_ )
     226              : {
     227         3879 : }
     228              : 
     229         1176 : static inline double geometry_rectangle_get_left ( const geometry_rectangle_t *this_ )
     230              : {
     231         1176 :     return (*this_).left;
     232              : }
     233              : 
     234         1368 : static inline double geometry_rectangle_get_top ( const geometry_rectangle_t *this_ )
     235              : {
     236         1368 :     return (*this_).top;
     237              : }
     238              : 
     239          184 : static inline double geometry_rectangle_get_right ( const geometry_rectangle_t *this_ )
     240              : {
     241          184 :     return (*this_).left + (*this_).width;
     242              : }
     243              : 
     244          312 : static inline double geometry_rectangle_get_bottom ( const geometry_rectangle_t *this_ )
     245              : {
     246          312 :     return (*this_).top + (*this_).height;
     247              : }
     248              : 
     249         1694 : static inline double geometry_rectangle_get_width ( const geometry_rectangle_t *this_ )
     250              : {
     251         1694 :     return (*this_).width;
     252              : }
     253              : 
     254         1454 : static inline double geometry_rectangle_get_height ( const geometry_rectangle_t *this_ )
     255              : {
     256         1454 :     return (*this_).height;
     257              : }
     258              : 
     259          166 : static inline double geometry_rectangle_get_center_x ( const geometry_rectangle_t *this_ )
     260              : {
     261          166 :     return (*this_).left + 0.5*(*this_).width;
     262              : }
     263              : 
     264          166 : static inline double geometry_rectangle_get_center_y ( const geometry_rectangle_t *this_ )
     265              : {
     266          166 :     return (*this_).top + 0.5*(*this_).height;
     267              : }
     268              : 
     269            0 : static inline geometry_point_t geometry_rectangle_get_center ( const geometry_rectangle_t *this_ )
     270              : {
     271              :     geometry_point_t result;
     272            0 :     geometry_point_init ( &result, (*this_).left + 0.5*(*this_).width, (*this_).top + 0.5*(*this_).height );
     273            0 :     return result;
     274              : }
     275              : 
     276            0 : static inline geometry_dimensions_t geometry_rectangle_get_dimensions ( const geometry_rectangle_t *this_ )
     277              : {
     278              :     geometry_dimensions_t result;
     279            0 :     geometry_dimensions_init ( &result, (*this_).width, (*this_).height );
     280            0 :     return result;
     281              : }
     282              : 
     283          218 : static inline double geometry_rectangle_get_area ( const geometry_rectangle_t *this_ )
     284              : {
     285          218 :     return (*this_).width * (*this_).height;
     286              : }
     287              : 
     288            2 : static inline bool geometry_rectangle_contains ( const geometry_rectangle_t *this_, double x, double y )
     289              : {
     290            2 :     return (( (*this_).left <= x )&&( x < (*this_).left + (*this_).width )&&( (*this_).top <= y )&&( y < (*this_).top + (*this_).height ));
     291              : }
     292              : 
     293            0 : static inline bool geometry_rectangle_contains_point ( const geometry_rectangle_t *this_, const geometry_point_t *point )
     294              : {
     295            0 :     return geometry_rectangle_contains( this_, geometry_point_get_x( point ), geometry_point_get_y( point ) );
     296              : }
     297              : 
     298            0 : static inline double geometry_rectangle_calc_chess_distance ( const geometry_rectangle_t *this_, double x, double y )
     299              : {
     300            0 :     double result = 0.0;
     301            0 :     if ( x < (*this_).left )
     302              :     {
     303            0 :         result += ( (*this_).left - x );
     304              :     }
     305            0 :     else if ( x > (*this_).left + (*this_).width )
     306              :     {
     307            0 :         result += ( x - ((*this_).left + (*this_).width) );
     308              :     }
     309            0 :     if ( y < (*this_).top )
     310              :     {
     311            0 :         result += ( (*this_).top - y );
     312              :     }
     313            0 :     else if ( y > (*this_).top + (*this_).height )
     314              :     {
     315            0 :         result += ( y - ((*this_).top + (*this_).height) );
     316              :     }
     317            0 :     return result;
     318              : }
     319              : 
     320          352 : static inline bool geometry_rectangle_is_empty ( const geometry_rectangle_t *this_ )
     321              : {
     322          352 :     return ( ( (*this_).width < 0.000000001 )||( (*this_).height < 0.000000001 ) );
     323              : }
     324              : 
     325           32 : static inline bool geometry_rectangle_is_point ( const geometry_rectangle_t *this_ )
     326              : {
     327           32 :     return ( ( (*this_).width < 0.000000001 )&&( (*this_).height < 0.000000001 ) );
     328              : }
     329              : 
     330          146 : static inline double geometry_rectangle_get_intersect_area ( const geometry_rectangle_t *this_, const geometry_rectangle_t *that )
     331              : {
     332              :     geometry_rectangle_t intersect;
     333          146 :     geometry_rectangle_init_by_intersect( &intersect, this_, that );
     334          146 :     return geometry_rectangle_get_area(&intersect);
     335              : }
     336              : 
     337          622 : static inline void geometry_rectangle_shift ( geometry_rectangle_t *this_, double delta_x, double delta_y )
     338              : {
     339          622 :     (*this_).left += delta_x;
     340          622 :     (*this_).top += delta_y;
     341          622 : }
     342              : 
     343          302 : static inline void geometry_rectangle_enlarge ( geometry_rectangle_t *this_, double delta_width, double delta_height )
     344              : {
     345          302 :     (*this_).width += delta_width;
     346          302 :     if ( (*this_).width < 0.0 )
     347              :     {
     348            0 :         (*this_).width = 0.0;
     349              :     }
     350              : 
     351          302 :     (*this_).height += delta_height;
     352          302 :     if ( (*this_).height < 0.0 )
     353              :     {
     354           92 :         (*this_).height = 0.0;
     355              :     }
     356          302 : }
     357              : 
     358          163 : static inline void geometry_rectangle_expand_4dir ( geometry_rectangle_t *this_, double delta_width, double delta_height )
     359              : {
     360          163 :     const double double_delta_width = 2.0 * delta_width;
     361          163 :     (*this_).width += double_delta_width;
     362          163 :     (*this_).left -= delta_width;
     363          163 :     if ( (*this_).width < 0.0 )
     364              :     {
     365            2 :         (*this_).left += 0.5 * (*this_).width;
     366            2 :         (*this_).width = 0.0;
     367              :     }
     368              : 
     369          163 :     const double double_delta_height = 2.0 * delta_height;
     370          163 :     (*this_).height += double_delta_height;
     371          163 :     (*this_).top -= delta_height;
     372          163 :     if ( (*this_).height < 0.0 )
     373              :     {
     374            2 :         (*this_).top += 0.5 * (*this_).height;
     375            2 :         (*this_).height = 0.0;
     376              :     }
     377          163 : }
     378              : 
     379          122 : static inline void geometry_rectangle_embrace ( geometry_rectangle_t *this_, double x, double y )
     380              : {
     381          122 :     const double rect_this_right = (*this_).left + (*this_).width;
     382          122 :     if ( x < (*this_).left )
     383              :     {
     384           13 :         const double dx = (*this_).left - x;
     385           13 :         (*this_).left -= dx;
     386           13 :         (*this_).width += dx;
     387              :     }
     388          109 :     else if ( x > rect_this_right )
     389              :     {
     390           42 :         const double dx = x - rect_this_right;
     391           42 :         (*this_).width += dx;
     392              :     }
     393          122 :     const double rect_this_bottom = (*this_).top + (*this_).height;
     394          122 :     if ( y < (*this_).top )
     395              :     {
     396           11 :         const double dy = (*this_).top - y;
     397           11 :         (*this_).top -= dy;
     398           11 :         (*this_).height += dy;
     399              :     }
     400          111 :     else if ( y > rect_this_bottom )
     401              :     {
     402           40 :         const double dy = y - rect_this_bottom;
     403           40 :         (*this_).height += dy;
     404              :     }
     405          122 : }
     406              : 
     407            0 : static inline void geometry_rectangle_set_left ( geometry_rectangle_t *this_, double left )
     408              : {
     409            0 :     (*this_).left = left;
     410            0 : }
     411              : 
     412          384 : static inline void geometry_rectangle_set_top ( geometry_rectangle_t *this_, double top )
     413              : {
     414          384 :     (*this_).top = top;
     415          384 : }
     416              : 
     417            0 : static inline void geometry_rectangle_set_width ( geometry_rectangle_t *this_, double width )
     418              : {
     419            0 :     (*this_).width = width;
     420            0 : }
     421              : 
     422            0 : static inline void geometry_rectangle_set_height ( geometry_rectangle_t *this_, double height )
     423              : {
     424            0 :     (*this_).height = height;
     425            0 : }
     426              : 
     427          960 : static inline void geometry_rectangle_trace ( const geometry_rectangle_t *this_ )
     428              : {
     429          960 :     U8_TRACE_INFO( "geometry_rectangle_t" );
     430          960 :     U8_TRACE_INFO_INT( "- left:", (*this_).left );
     431          960 :     U8_TRACE_INFO_INT( "- top:", (*this_).top );
     432          960 :     U8_TRACE_INFO_INT( "- width:", (*this_).width );
     433          960 :     U8_TRACE_INFO_INT( "- height:", (*this_).height );
     434          960 : }
     435              : 
     436              : 
     437              : /*
     438              : Copyright 2016-2025 Andreas Warnke
     439              : 
     440              : Licensed under the Apache License, Version 2.0 (the "License");
     441              : you may not use this file except in compliance with the License.
     442              : You may obtain a copy of the License at
     443              : 
     444              :     http://www.apache.org/licenses/LICENSE-2.0
     445              : 
     446              : Unless required by applicable law or agreed to in writing, software
     447              : distributed under the License is distributed on an "AS IS" BASIS,
     448              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     449              : See the License for the specific language governing permissions and
     450              : limitations under the License.
     451              : */
        

Generated by: LCOV version 2.0-1