LCOV - code coverage report
Current view: top level - pencil/include/geometry - geometry_rectangle.inl (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.65.6_covts Lines: 194 227 85.5 %
Date: 2025-09-25 21:07:53 Functions: 31 39 79.5 %

          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           2 :         (*this_).width = 0.0;
      95           2 :         (*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 1.16