LCOV - code coverage report
Current view: top level - pencil/include/geometry - geometry_rectangle.inl (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.57.0_covts Lines: 192 225 85.3 %
Date: 2024-04-07 11:14:42 Functions: 31 38 81.6 %

          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         380 : static inline void geometry_rectangle_init ( geometry_rectangle_t *this_, double left, double top, double width, double height )
       9             : {
      10         380 :     (*this_).left = left;
      11         380 :     (*this_).top = top;
      12         380 :     (*this_).width = width;
      13         380 :     (*this_).height = height;
      14         380 : }
      15             : 
      16         517 : static inline void geometry_rectangle_reinit ( geometry_rectangle_t *this_, double left, double top, double width, double height )
      17             : {
      18         517 :     (*this_).left = left;
      19         517 :     (*this_).top = top;
      20         517 :     (*this_).width = width;
      21         517 :     (*this_).height = height;
      22         517 : }
      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         893 : static inline void geometry_rectangle_replace ( geometry_rectangle_t *this_, const geometry_rectangle_t *original )
      37             : {
      38         893 :     assert( NULL != original );
      39         893 :     (*this_) = (*original);
      40         893 : }
      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        4354 : static inline void geometry_rectangle_init_empty ( geometry_rectangle_t *this_ )
      49             : {
      50        4354 :     (*this_).left = 0.0;
      51        4354 :     (*this_).top = 0.0;
      52        4354 :     (*this_).width = 0.0;
      53        4354 :     (*this_).height = 0.0;
      54        4354 : }
      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         118 : 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         118 :     assert( NULL != rect_a );
      69         118 :     assert( NULL != rect_b );
      70             : 
      71         118 :     int result = 0;
      72             : 
      73         118 :     const double rect_a_right = (*rect_a).left + (*rect_a).width;
      74         118 :     const double rect_a_bottom = (*rect_a).top + (*rect_a).height;
      75         118 :     const double rect_b_right = (*rect_b).left + (*rect_b).width;
      76         118 :     const double rect_b_bottom = (*rect_b).top + (*rect_b).height;
      77             : 
      78         118 :     (*this_).left = fmax( (*rect_a).left, (*rect_b).left );
      79         118 :     (*this_).top = fmax( (*rect_a).top, (*rect_b).top );
      80         118 :     (*this_).width = fmin( rect_a_right, rect_b_right ) - (*this_).left;
      81         118 :     (*this_).height = fmin( rect_a_bottom, rect_b_bottom ) - (*this_).top;
      82         118 :     if (( (*this_).width < -0.000000001 ) || ( (*this_).height < -0.000000001 ))
      83             :     {
      84             :         /* if intersection is empty, result is -1 */
      85          19 :         (*this_).left = 0.0;
      86          19 :         (*this_).top = 0.0;
      87          19 :         (*this_).width = 0.0;
      88          19 :         (*this_).height = 0.0;
      89          19 :         result = -1;
      90             :     }
      91          99 :     else if (( (*this_).width < 0.0 ) || ( (*this_).height < 0.0 ))
      92             :     {
      93             :         /* update rounding error */
      94           0 :         (*this_).width = 0.0;
      95           0 :         (*this_).height = 0.0;
      96             :     }
      97             : 
      98         118 :     return result;
      99             : }
     100             : 
     101        1153 : 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        1153 :     assert( NULL != rect_a );
     106        1153 :     assert( NULL != rect_b );
     107             : 
     108        1153 :     int result = 0;
     109             : 
     110        1153 :     const double rect_a_right = (*rect_a).left + (*rect_a).width;
     111        1153 :     const double rect_a_bottom = (*rect_a).top + (*rect_a).height;
     112        1153 :     const double rect_b_right = (*rect_b).left + (*rect_b).width;
     113        1153 :     const double rect_b_bottom = (*rect_b).top + (*rect_b).height;
     114             : 
     115        1153 :     (*this_).left = fmin( (*rect_a).left, (*rect_b).left );
     116        1153 :     (*this_).top = fmin( (*rect_a).top, (*rect_b).top );
     117        1153 :     (*this_).width = fmax( rect_a_right, rect_b_right ) - (*this_).left;
     118        1153 :     (*this_).height = fmax( rect_a_bottom, rect_b_bottom ) - (*this_).top;
     119             : 
     120        1153 :     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         480 : static inline bool geometry_rectangle_is_containing ( const geometry_rectangle_t *this_, const geometry_rectangle_t *that )
     176             : {
     177         480 :     assert( NULL != that );
     178             : 
     179             :     bool result;
     180             : 
     181         480 :     const double rect_this_right = (*this_).left + (*this_).width;
     182         480 :     const double rect_this_bottom = (*this_).top + (*this_).height;
     183         480 :     const double rect_that_right = (*that).left + (*that).width;
     184         480 :     const double rect_that_bottom = (*that).top + (*that).height;
     185             : 
     186         480 :     if ( ( (*this_).left < (*that).left + 0.000000001 ) /* touching is containing */
     187         415 :         && ( (*this_).top < (*that).top + 0.000000001 )
     188         414 :         && ( rect_this_right + 0.000000001 > rect_that_right )
     189         413 :         && ( rect_this_bottom + 0.000000001 > rect_that_bottom ) )
     190             :     {
     191         413 :         result = true;
     192             :     }
     193             :     else
     194             :     {
     195          67 :         result = false;
     196             :     }
     197             : 
     198         480 :     return result;
     199             : }
     200             : 
     201          60 : static inline void geometry_rectangle_init_by_corners ( geometry_rectangle_t *this_, double x1, double y1, double x2, double y2 )
     202             : {
     203          60 :     if ( x1 < x2 )
     204             :     {
     205          12 :         (*this_).left = x1;
     206          12 :         (*this_).width = x2-x1;
     207             :     }
     208             :     else
     209             :     {
     210          48 :         (*this_).left = x2;
     211          48 :         (*this_).width = x1-x2;
     212             :     }
     213          60 :     if ( y1 < y2 )
     214             :     {
     215          15 :         (*this_).top = y1;
     216          15 :         (*this_).height = y2-y1;
     217             :     }
     218             :     else
     219             :     {
     220          45 :         (*this_).top = y2;
     221          45 :         (*this_).height = y1-y2;
     222             :     }
     223          60 : }
     224             : 
     225        4620 : static inline void geometry_rectangle_destroy ( geometry_rectangle_t *this_ )
     226             : {
     227        4620 : }
     228             : 
     229         995 : static inline double geometry_rectangle_get_left ( const geometry_rectangle_t *this_ )
     230             : {
     231         995 :     return (*this_).left;
     232             : }
     233             : 
     234         871 : static inline double geometry_rectangle_get_top ( const geometry_rectangle_t *this_ )
     235             : {
     236         871 :     return (*this_).top;
     237             : }
     238             : 
     239          71 : static inline double geometry_rectangle_get_right ( const geometry_rectangle_t *this_ )
     240             : {
     241          71 :     return (*this_).left + (*this_).width;
     242             : }
     243             : 
     244          71 : static inline double geometry_rectangle_get_bottom ( const geometry_rectangle_t *this_ )
     245             : {
     246          71 :     return (*this_).top + (*this_).height;
     247             : }
     248             : 
     249        1512 : static inline double geometry_rectangle_get_width ( const geometry_rectangle_t *this_ )
     250             : {
     251        1512 :     return (*this_).width;
     252             : }
     253             : 
     254        1474 : static inline double geometry_rectangle_get_height ( const geometry_rectangle_t *this_ )
     255             : {
     256        1474 :     return (*this_).height;
     257             : }
     258             : 
     259         128 : static inline double geometry_rectangle_get_center_x ( const geometry_rectangle_t *this_ )
     260             : {
     261         128 :     return (*this_).left + 0.5*(*this_).width;
     262             : }
     263             : 
     264         128 : static inline double geometry_rectangle_get_center_y ( const geometry_rectangle_t *this_ )
     265             : {
     266         128 :     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         153 : static inline double geometry_rectangle_get_area ( const geometry_rectangle_t *this_ )
     284             : {
     285         153 :     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 double geometry_rectangle_calc_chess_distance ( const geometry_rectangle_t *this_, double x, double y )
     294             : {
     295           0 :     double result = 0.0;
     296           0 :     if ( x < (*this_).left )
     297             :     {
     298           0 :         result += ( (*this_).left - x );
     299             :     }
     300           0 :     else if ( x > (*this_).left + (*this_).width )
     301             :     {
     302           0 :         result += ( x - ((*this_).left + (*this_).width) );
     303             :     }
     304           0 :     if ( y < (*this_).top )
     305             :     {
     306           0 :         result += ( (*this_).top - y );
     307             :     }
     308           0 :     else if ( y > (*this_).top + (*this_).height )
     309             :     {
     310           0 :         result += ( y - ((*this_).top + (*this_).height) );
     311             :     }
     312           0 :     return result;
     313             : }
     314             : 
     315         352 : static inline bool geometry_rectangle_is_empty ( const geometry_rectangle_t *this_ )
     316             : {
     317         352 :     return ( ( (*this_).width < 0.000000001 )||( (*this_).height < 0.000000001 ) );
     318             : }
     319             : 
     320          32 : static inline bool geometry_rectangle_is_point ( const geometry_rectangle_t *this_ )
     321             : {
     322          32 :     return ( ( (*this_).width < 0.000000001 )&&( (*this_).height < 0.000000001 ) );
     323             : }
     324             : 
     325         114 : static inline double geometry_rectangle_get_intersect_area ( const geometry_rectangle_t *this_, const geometry_rectangle_t *that )
     326             : {
     327             :     geometry_rectangle_t intersect;
     328         114 :     geometry_rectangle_init_by_intersect( &intersect, this_, that );
     329         114 :     return geometry_rectangle_get_area(&intersect);
     330             : }
     331             : 
     332         558 : static inline void geometry_rectangle_shift ( geometry_rectangle_t *this_, double delta_x, double delta_y )
     333             : {
     334         558 :     (*this_).left += delta_x;
     335         558 :     (*this_).top += delta_y;
     336         558 : }
     337             : 
     338         302 : static inline void geometry_rectangle_enlarge ( geometry_rectangle_t *this_, double delta_width, double delta_height )
     339             : {
     340         302 :     (*this_).width += delta_width;
     341         302 :     if ( (*this_).width < 0.0 )
     342             :     {
     343           0 :         (*this_).width = 0.0;
     344             :     }
     345             : 
     346         302 :     (*this_).height += delta_height;
     347         302 :     if ( (*this_).height < 0.0 )
     348             :     {
     349          92 :         (*this_).height = 0.0;
     350             :     }
     351         302 : }
     352             : 
     353         163 : static inline void geometry_rectangle_expand_4dir ( geometry_rectangle_t *this_, double delta_width, double delta_height )
     354             : {
     355         163 :     const double double_delta_width = 2.0 * delta_width;
     356         163 :     (*this_).width += double_delta_width;
     357         163 :     (*this_).left -= delta_width;
     358         163 :     if ( (*this_).width < 0.0 )
     359             :     {
     360           2 :         (*this_).left += 0.5 * (*this_).width;
     361           2 :         (*this_).width = 0.0;
     362             :     }
     363             : 
     364         163 :     const double double_delta_height = 2.0 * delta_height;
     365         163 :     (*this_).height += double_delta_height;
     366         163 :     (*this_).top -= delta_height;
     367         163 :     if ( (*this_).height < 0.0 )
     368             :     {
     369           2 :         (*this_).top += 0.5 * (*this_).height;
     370           2 :         (*this_).height = 0.0;
     371             :     }
     372         163 : }
     373             : 
     374         122 : static inline void geometry_rectangle_embrace ( geometry_rectangle_t *this_, double x, double y )
     375             : {
     376         122 :     const double rect_this_right = (*this_).left + (*this_).width;
     377         122 :     if ( x < (*this_).left )
     378             :     {
     379          13 :         const double dx = (*this_).left - x;
     380          13 :         (*this_).left -= dx;
     381          13 :         (*this_).width += dx;
     382             :     }
     383         109 :     else if ( x > rect_this_right )
     384             :     {
     385          42 :         const double dx = x - rect_this_right;
     386          42 :         (*this_).width += dx;
     387             :     }
     388         122 :     const double rect_this_bottom = (*this_).top + (*this_).height;
     389         122 :     if ( y < (*this_).top )
     390             :     {
     391          11 :         const double dy = (*this_).top - y;
     392          11 :         (*this_).top -= dy;
     393          11 :         (*this_).height += dy;
     394             :     }
     395         111 :     else if ( y > rect_this_bottom )
     396             :     {
     397          40 :         const double dy = y - rect_this_bottom;
     398          40 :         (*this_).height += dy;
     399             :     }
     400         122 : }
     401             : 
     402           0 : static inline void geometry_rectangle_set_left ( geometry_rectangle_t *this_, double left )
     403             : {
     404           0 :     (*this_).left = left;
     405           0 : }
     406             : 
     407         256 : static inline void geometry_rectangle_set_top ( geometry_rectangle_t *this_, double top )
     408             : {
     409         256 :     (*this_).top = top;
     410         256 : }
     411             : 
     412           0 : static inline void geometry_rectangle_set_width ( geometry_rectangle_t *this_, double width )
     413             : {
     414           0 :     (*this_).width = width;
     415           0 : }
     416             : 
     417           0 : static inline void geometry_rectangle_set_height ( geometry_rectangle_t *this_, double height )
     418             : {
     419           0 :     (*this_).height = height;
     420           0 : }
     421             : 
     422         768 : static inline void geometry_rectangle_trace ( const geometry_rectangle_t *this_ )
     423             : {
     424         768 :     U8_TRACE_INFO( "geometry_rectangle_t" );
     425         768 :     U8_TRACE_INFO_INT( "- left:", (*this_).left );
     426         768 :     U8_TRACE_INFO_INT( "- top:", (*this_).top );
     427         768 :     U8_TRACE_INFO_INT( "- width:", (*this_).width );
     428         768 :     U8_TRACE_INFO_INT( "- height:", (*this_).height );
     429         768 : }
     430             : 
     431             : 
     432             : /*
     433             : Copyright 2016-2024 Andreas Warnke
     434             : 
     435             : Licensed under the Apache License, Version 2.0 (the "License");
     436             : you may not use this file except in compliance with the License.
     437             : You may obtain a copy of the License at
     438             : 
     439             :     http://www.apache.org/licenses/LICENSE-2.0
     440             : 
     441             : Unless required by applicable law or agreed to in writing, software
     442             : distributed under the License is distributed on an "AS IS" BASIS,
     443             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     444             : See the License for the specific language governing permissions and
     445             : limitations under the License.
     446             : */

Generated by: LCOV version 1.16