LCOV - code coverage report
Current view: top level - pencil/include/geometry - geometry_rectangle.inl (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.71.1_covts Lines: 100.0 % 240 240
Test Date: 2026-08-09 05:59:58 Functions: 100.0 % 42 42

            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         1087 : static inline void geometry_rectangle_init ( geometry_rectangle_t *this_, double left, double top, double width, double height )
       9              : {
      10         1087 :     (*this_).left = left;
      11         1087 :     (*this_).top = top;
      12         1087 :     (*this_).width = width;
      13         1087 :     (*this_).height = height;
      14         1087 : }
      15              : 
      16          592 : static inline void geometry_rectangle_reinit ( geometry_rectangle_t *this_, double left, double top, double width, double height )
      17              : {
      18          592 :     (*this_).left = left;
      19          592 :     (*this_).top = top;
      20          592 :     (*this_).width = width;
      21          592 :     (*this_).height = height;
      22          592 : }
      23              : 
      24            1 : static inline void geometry_rectangle_copy ( geometry_rectangle_t *this_, const geometry_rectangle_t *original )
      25              : {
      26            1 :     assert( NULL != original );
      27            1 :     (*this_) = (*original);
      28            1 : }
      29              : 
      30            1 : static inline void geometry_rectangle_move ( geometry_rectangle_t *this_, geometry_rectangle_t *that )
      31              : {
      32            1 :     assert( NULL != that );
      33            1 :     (*this_) = (*that);
      34            1 : }
      35              : 
      36         1387 : static inline void geometry_rectangle_replace ( geometry_rectangle_t *this_, const geometry_rectangle_t *original )
      37              : {
      38         1387 :     assert( NULL != original );
      39         1387 :     (*this_) = (*original);
      40         1387 : }
      41              : 
      42            1 : static inline void geometry_rectangle_replacemove ( geometry_rectangle_t *this_, geometry_rectangle_t *that )
      43              : {
      44            1 :     assert( NULL != that );
      45            1 :     (*this_) = (*that);
      46            1 : }
      47              : 
      48         3552 : static inline void geometry_rectangle_init_empty ( geometry_rectangle_t *this_ )
      49              : {
      50         3552 :     (*this_).left = 0.0;
      51         3552 :     (*this_).top = 0.0;
      52         3552 :     (*this_).width = 0.0;
      53         3552 :     (*this_).height = 0.0;
      54         3552 : }
      55              : 
      56            1 : static inline void geometry_rectangle_reinit_empty ( geometry_rectangle_t *this_ )
      57              : {
      58            1 :     (*this_).left = 0.0;
      59            1 :     (*this_).top = 0.0;
      60            1 :     (*this_).width = 0.0;
      61            1 :     (*this_).height = 0.0;
      62            1 : }
      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         2881 : 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         2881 :     assert( NULL != rect_a );
     106         2881 :     assert( NULL != rect_b );
     107              : 
     108         2881 :     int result = 0;
     109              : 
     110         2881 :     const double rect_a_right = (*rect_a).left + (*rect_a).width;
     111         2881 :     const double rect_a_bottom = (*rect_a).top + (*rect_a).height;
     112         2881 :     const double rect_b_right = (*rect_b).left + (*rect_b).width;
     113         2881 :     const double rect_b_bottom = (*rect_b).top + (*rect_b).height;
     114              : 
     115         2881 :     (*this_).left = fmin( (*rect_a).left, (*rect_b).left );
     116         2881 :     (*this_).top = fmin( (*rect_a).top, (*rect_b).top );
     117         2881 :     (*this_).width = fmax( rect_a_right, rect_b_right ) - (*this_).left;
     118         2881 :     (*this_).height = fmax( rect_a_bottom, rect_b_bottom ) - (*this_).top;
     119              : 
     120         2881 :     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         3442 : static inline void geometry_rectangle_destroy ( geometry_rectangle_t *this_ )
     226              : {
     227         3442 : }
     228              : 
     229          787 : static inline geometry_rectangle_t geometry_rectangle_new ( double left, double top, double width, double height )
     230              : {
     231              :     geometry_rectangle_t result;
     232          787 :     geometry_rectangle_init( &result, left, top, width, height );
     233          787 :     return result;
     234              : }
     235              : 
     236         1572 : static inline double geometry_rectangle_get_left ( const geometry_rectangle_t *this_ )
     237              : {
     238         1572 :     return (*this_).left;
     239              : }
     240              : 
     241         1424 : static inline double geometry_rectangle_get_top ( const geometry_rectangle_t *this_ )
     242              : {
     243         1424 :     return (*this_).top;
     244              : }
     245              : 
     246          185 : static inline double geometry_rectangle_get_right ( const geometry_rectangle_t *this_ )
     247              : {
     248          185 :     return (*this_).left + (*this_).width;
     249              : }
     250              : 
     251          441 : static inline double geometry_rectangle_get_bottom ( const geometry_rectangle_t *this_ )
     252              : {
     253          441 :     return (*this_).top + (*this_).height;
     254              : }
     255              : 
     256         2438 : static inline double geometry_rectangle_get_width ( const geometry_rectangle_t *this_ )
     257              : {
     258         2438 :     return (*this_).width;
     259              : }
     260              : 
     261         2167 : static inline double geometry_rectangle_get_height ( const geometry_rectangle_t *this_ )
     262              : {
     263         2167 :     return (*this_).height;
     264              : }
     265              : 
     266          166 : static inline double geometry_rectangle_get_center_x ( const geometry_rectangle_t *this_ )
     267              : {
     268          166 :     return (*this_).left + 0.5*(*this_).width;
     269              : }
     270              : 
     271          166 : static inline double geometry_rectangle_get_center_y ( const geometry_rectangle_t *this_ )
     272              : {
     273          166 :     return (*this_).top + 0.5*(*this_).height;
     274              : }
     275              : 
     276            1 : static inline geometry_point_t geometry_rectangle_get_center ( const geometry_rectangle_t *this_ )
     277              : {
     278              :     geometry_point_t result;
     279            1 :     geometry_point_init ( &result, (*this_).left + 0.5*(*this_).width, (*this_).top + 0.5*(*this_).height );
     280            1 :     return result;
     281              : }
     282              : 
     283            1 : static inline geometry_dimensions_t geometry_rectangle_get_dimensions ( const geometry_rectangle_t *this_ )
     284              : {
     285              :     geometry_dimensions_t result;
     286            1 :     geometry_dimensions_init ( &result, (*this_).width, (*this_).height );
     287            1 :     return result;
     288              : }
     289              : 
     290          218 : static inline double geometry_rectangle_get_area ( const geometry_rectangle_t *this_ )
     291              : {
     292          218 :     return (*this_).width * (*this_).height;
     293              : }
     294              : 
     295            3 : static inline bool geometry_rectangle_contains ( const geometry_rectangle_t *this_, double x, double y )
     296              : {
     297            3 :     return (( (*this_).left <= x )&&( x < (*this_).left + (*this_).width )&&( (*this_).top <= y )&&( y < (*this_).top + (*this_).height ));
     298              : }
     299              : 
     300            1 : static inline bool geometry_rectangle_contains_point ( const geometry_rectangle_t *this_, const geometry_point_t *point )
     301              : {
     302            1 :     return geometry_rectangle_contains( this_, geometry_point_get_x( point ), geometry_point_get_y( point ) );
     303              : }
     304              : 
     305            4 : static inline double geometry_rectangle_calc_chess_distance ( const geometry_rectangle_t *this_, double x, double y )
     306              : {
     307            4 :     double result = 0.0;
     308            4 :     if ( x < (*this_).left )
     309              :     {
     310            1 :         result += ( (*this_).left - x );
     311              :     }
     312            3 :     else if ( x > (*this_).left + (*this_).width )
     313              :     {
     314            1 :         result += ( x - ((*this_).left + (*this_).width) );
     315              :     }
     316            4 :     if ( y < (*this_).top )
     317              :     {
     318            1 :         result += ( (*this_).top - y );
     319              :     }
     320            3 :     else if ( y > (*this_).top + (*this_).height )
     321              :     {
     322            1 :         result += ( y - ((*this_).top + (*this_).height) );
     323              :     }
     324            4 :     return result;
     325              : }
     326              : 
     327          352 : static inline bool geometry_rectangle_is_empty ( const geometry_rectangle_t *this_ )
     328              : {
     329          352 :     return ( ( (*this_).width < 0.000000001 )||( (*this_).height < 0.000000001 ) );
     330              : }
     331              : 
     332           32 : static inline bool geometry_rectangle_is_point ( const geometry_rectangle_t *this_ )
     333              : {
     334           32 :     return ( ( (*this_).width < 0.000000001 )&&( (*this_).height < 0.000000001 ) );
     335              : }
     336              : 
     337          146 : static inline double geometry_rectangle_get_intersect_area ( const geometry_rectangle_t *this_, const geometry_rectangle_t *that )
     338              : {
     339              :     geometry_rectangle_t intersect;
     340          146 :     geometry_rectangle_init_by_intersect( &intersect, this_, that );
     341          146 :     return geometry_rectangle_get_area(&intersect);
     342              : }
     343              : 
     344          557 : static inline void geometry_rectangle_shift ( geometry_rectangle_t *this_, double delta_x, double delta_y )
     345              : {
     346          557 :     (*this_).left += delta_x;
     347          557 :     (*this_).top += delta_y;
     348          557 : }
     349              : 
     350          175 : static inline void geometry_rectangle_enlarge ( geometry_rectangle_t *this_, double delta_width, double delta_height )
     351              : {
     352          175 :     (*this_).width += delta_width;
     353          175 :     if ( (*this_).width < 0.0 )
     354              :     {
     355            1 :         (*this_).width = 0.0;
     356              :     }
     357              : 
     358          175 :     (*this_).height += delta_height;
     359          175 :     if ( (*this_).height < 0.0 )
     360              :     {
     361           29 :         (*this_).height = 0.0;
     362              :     }
     363          175 : }
     364              : 
     365          227 : static inline void geometry_rectangle_expand_4dir ( geometry_rectangle_t *this_, double delta_width, double delta_height )
     366              : {
     367          227 :     const double double_delta_width = 2.0 * delta_width;
     368          227 :     (*this_).width += double_delta_width;
     369          227 :     (*this_).left -= delta_width;
     370          227 :     if ( (*this_).width < 0.0 )
     371              :     {
     372            2 :         (*this_).left += 0.5 * (*this_).width;
     373            2 :         (*this_).width = 0.0;
     374              :     }
     375              : 
     376          227 :     const double double_delta_height = 2.0 * delta_height;
     377          227 :     (*this_).height += double_delta_height;
     378          227 :     (*this_).top -= delta_height;
     379          227 :     if ( (*this_).height < 0.0 )
     380              :     {
     381            2 :         (*this_).top += 0.5 * (*this_).height;
     382            2 :         (*this_).height = 0.0;
     383              :     }
     384          227 : }
     385              : 
     386          122 : static inline void geometry_rectangle_embrace ( geometry_rectangle_t *this_, double x, double y )
     387              : {
     388          122 :     const double rect_this_right = (*this_).left + (*this_).width;
     389          122 :     if ( x < (*this_).left )
     390              :     {
     391           13 :         const double dx = (*this_).left - x;
     392           13 :         (*this_).left -= dx;
     393           13 :         (*this_).width += dx;
     394              :     }
     395          109 :     else if ( x > rect_this_right )
     396              :     {
     397           42 :         const double dx = x - rect_this_right;
     398           42 :         (*this_).width += dx;
     399              :     }
     400          122 :     const double rect_this_bottom = (*this_).top + (*this_).height;
     401          122 :     if ( y < (*this_).top )
     402              :     {
     403           11 :         const double dy = (*this_).top - y;
     404           11 :         (*this_).top -= dy;
     405           11 :         (*this_).height += dy;
     406              :     }
     407          111 :     else if ( y > rect_this_bottom )
     408              :     {
     409           40 :         const double dy = y - rect_this_bottom;
     410           40 :         (*this_).height += dy;
     411              :     }
     412          122 : }
     413              : 
     414            1 : static inline void geometry_rectangle_set_left ( geometry_rectangle_t *this_, double left )
     415              : {
     416            1 :     (*this_).left = left;
     417            1 : }
     418              : 
     419          193 : static inline void geometry_rectangle_set_top ( geometry_rectangle_t *this_, double top )
     420              : {
     421          193 :     (*this_).top = top;
     422          193 : }
     423              : 
     424            1 : static inline void geometry_rectangle_set_width ( geometry_rectangle_t *this_, double width )
     425              : {
     426            1 :     (*this_).width = width;
     427            1 : }
     428              : 
     429            1 : static inline void geometry_rectangle_set_height ( geometry_rectangle_t *this_, double height )
     430              : {
     431            1 :     (*this_).height = height;
     432            1 : }
     433              : 
     434         1280 : static inline void geometry_rectangle_trace ( const geometry_rectangle_t *this_ )
     435              : {
     436         1280 :     U8_TRACE_INFO( "geometry_rectangle_t" );
     437         1280 :     U8_TRACE_INFO_INT( "- left:", (*this_).left );
     438         1280 :     U8_TRACE_INFO_INT( "- top:", (*this_).top );
     439         1280 :     U8_TRACE_INFO_INT( "- width:", (*this_).width );
     440         1280 :     U8_TRACE_INFO_INT( "- height:", (*this_).height );
     441         1280 : }
     442              : 
     443              : 
     444              : /*
     445              : Copyright 2016-2026 Andreas Warnke
     446              : 
     447              : Licensed under the Apache License, Version 2.0 (the "License");
     448              : you may not use this file except in compliance with the License.
     449              : You may obtain a copy of the License at
     450              : 
     451              :     http://www.apache.org/licenses/LICENSE-2.0
     452              : 
     453              : Unless required by applicable law or agreed to in writing, software
     454              : distributed under the License is distributed on an "AS IS" BASIS,
     455              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     456              : See the License for the specific language governing permissions and
     457              : limitations under the License.
     458              : */
        

Generated by: LCOV version 2.0-1