LCOV - code coverage report
Current view: top level - pencil/include/geometry - geometry_connector.inl (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.63.2_covts Lines: 100.0 % 524 524
Test Date: 2025-05-01 10:10:14 Functions: 100.0 % 30 30

            Line data    Source code
       1              : /* File: geometry_connector.inl; Copyright and License: see below */
       2              : 
       3              : #include "u8/u8_trace.h"
       4              : #include "u8/u8_log.h"
       5              : #include "u8/u8_interval.h"
       6              : #include <math.h>
       7              : 
       8           17 : static inline void geometry_connector_init_vertical ( geometry_connector_t *this_,
       9              :                                                       double source_end_x,
      10              :                                                       double source_end_y,
      11              :                                                       double destination_end_x,
      12              :                                                       double destination_end_y,
      13              :                                                       double main_line_x )
      14              : {
      15           17 :     (*this_).source_end_x = source_end_x;
      16           17 :     (*this_).source_end_y = source_end_y;
      17           17 :     (*this_).main_line_source_x = main_line_x;
      18           17 :     (*this_).main_line_source_y = source_end_y;
      19           17 :     (*this_).main_line_destination_x = main_line_x;
      20           17 :     (*this_).main_line_destination_y = destination_end_y;
      21           17 :     (*this_).destination_end_x = destination_end_x;
      22           17 :     (*this_).destination_end_y = destination_end_y;
      23           17 : }
      24              : 
      25           15 : static inline void geometry_connector_init_horizontal ( geometry_connector_t *this_,
      26              :                                                         double source_end_x,
      27              :                                                         double source_end_y,
      28              :                                                         double destination_end_x,
      29              :                                                         double destination_end_y,
      30              :                                                         double main_line_y )
      31              : {
      32           15 :     (*this_).source_end_x = source_end_x;
      33           15 :     (*this_).source_end_y = source_end_y;
      34           15 :     (*this_).main_line_source_x = source_end_x;
      35           15 :     (*this_).main_line_source_y = main_line_y;
      36           15 :     (*this_).main_line_destination_x = destination_end_x;
      37           15 :     (*this_).main_line_destination_y = main_line_y;
      38           15 :     (*this_).destination_end_x = destination_end_x;
      39           15 :     (*this_).destination_end_y = destination_end_y;
      40           15 : }
      41              : 
      42            5 : static inline void geometry_connector_reinit_vertical ( geometry_connector_t *this_,
      43              :                                                         double source_end_x,
      44              :                                                         double source_end_y,
      45              :                                                         double destination_end_x,
      46              :                                                         double destination_end_y,
      47              :                                                         double main_line_x )
      48              : {
      49            5 :     (*this_).source_end_x = source_end_x;
      50            5 :     (*this_).source_end_y = source_end_y;
      51            5 :     (*this_).main_line_source_x = main_line_x;
      52            5 :     (*this_).main_line_source_y = source_end_y;
      53            5 :     (*this_).main_line_destination_x = main_line_x;
      54            5 :     (*this_).main_line_destination_y = destination_end_y;
      55            5 :     (*this_).destination_end_x = destination_end_x;
      56            5 :     (*this_).destination_end_y = destination_end_y;
      57            5 : }
      58              : 
      59            3 : static inline void geometry_connector_reinit_horizontal ( geometry_connector_t *this_,
      60              :                                                           double source_end_x,
      61              :                                                           double source_end_y,
      62              :                                                           double destination_end_x,
      63              :                                                           double destination_end_y,
      64              :                                                           double main_line_y )
      65              : {
      66            3 :     (*this_).source_end_x = source_end_x;
      67            3 :     (*this_).source_end_y = source_end_y;
      68            3 :     (*this_).main_line_source_x = source_end_x;
      69            3 :     (*this_).main_line_source_y = main_line_y;
      70            3 :     (*this_).main_line_destination_x = destination_end_x;
      71            3 :     (*this_).main_line_destination_y = main_line_y;
      72            3 :     (*this_).destination_end_x = destination_end_x;
      73            3 :     (*this_).destination_end_y = destination_end_y;
      74            3 : }
      75              : 
      76              : static inline void geometry_connector_copy ( geometry_connector_t *this_, const geometry_connector_t *original )
      77              : {
      78              :     (*this_) = (*original);
      79              : }
      80              : 
      81            1 : static inline void geometry_connector_replace ( geometry_connector_t *this_, const geometry_connector_t *original )
      82              : {
      83            1 :     (*this_) = (*original);
      84            1 : }
      85              : 
      86          859 : static inline void geometry_connector_init_empty ( geometry_connector_t *this_ )
      87              : {
      88          859 :     (*this_).source_end_x = 0.0;
      89          859 :     (*this_).source_end_y = 0.0;
      90          859 :     (*this_).main_line_source_x = 0.0;
      91          859 :     (*this_).main_line_source_y = 0.0;
      92          859 :     (*this_).main_line_destination_x = 0.0;
      93          859 :     (*this_).main_line_destination_y = 0.0;
      94          859 :     (*this_).destination_end_x = 0.0;
      95          859 :     (*this_).destination_end_y = 0.0;
      96          859 : }
      97              : 
      98              : static inline void geometry_connector_reinit_empty ( geometry_connector_t *this_ )
      99              : {
     100              :     (*this_).source_end_x = 0.0;
     101              :     (*this_).source_end_y = 0.0;
     102              :     (*this_).main_line_source_x = 0.0;
     103              :     (*this_).main_line_source_y = 0.0;
     104              :     (*this_).main_line_destination_x = 0.0;
     105              :     (*this_).main_line_destination_y = 0.0;
     106              :     (*this_).destination_end_x = 0.0;
     107              :     (*this_).destination_end_y = 0.0;
     108              : }
     109              : 
     110          873 : static inline void geometry_connector_destroy ( geometry_connector_t *this_ )
     111              : {
     112          873 : }
     113              : 
     114            1 : static inline double geometry_connector_get_source_end_x ( const geometry_connector_t *this_ )
     115              : {
     116            1 :     return (*this_).source_end_x;
     117              : }
     118              : 
     119            1 : static inline double geometry_connector_get_source_end_y ( const geometry_connector_t *this_ )
     120              : {
     121            1 :     return (*this_).source_end_y;
     122              : }
     123              : 
     124            1 : static inline double geometry_connector_get_main_line_source_x ( const geometry_connector_t *this_ )
     125              : {
     126            1 :     return (*this_).main_line_source_x;
     127              : }
     128              : 
     129            1 : static inline double geometry_connector_get_main_line_source_y ( const geometry_connector_t *this_ )
     130              : {
     131            1 :     return (*this_).main_line_source_y;
     132              : }
     133              : 
     134            1 : static inline double geometry_connector_get_main_line_destination_x ( const geometry_connector_t *this_ )
     135              : {
     136            1 :     return (*this_).main_line_destination_x;
     137              : }
     138              : 
     139            1 : static inline double geometry_connector_get_main_line_destination_y ( const geometry_connector_t *this_ )
     140              : {
     141            1 :     return (*this_).main_line_destination_y;
     142              : }
     143              : 
     144            1 : static inline double geometry_connector_get_destination_end_x ( const geometry_connector_t *this_ )
     145              : {
     146            1 :     return (*this_).destination_end_x;
     147              : }
     148              : 
     149            1 : static inline double geometry_connector_get_destination_end_y ( const geometry_connector_t *this_ )
     150              : {
     151            1 :     return (*this_).destination_end_y;
     152              : }
     153              : 
     154            8 : static inline geometry_point_t geometry_connector_calculate_waypoint ( const geometry_connector_t *this_,
     155              :                                                                        double distance_covered )
     156              : {
     157              :     geometry_point_t result;
     158              : 
     159            8 :     const double source_end_length = fabs( (*this_).source_end_x - (*this_).main_line_source_x )
     160            8 :                                      + fabs( (*this_).source_end_y - (*this_).main_line_source_y );
     161            8 :     const double main_line_length = fabs( (*this_).main_line_source_x - (*this_).main_line_destination_x )
     162            8 :                                     + fabs( (*this_).main_line_source_y - (*this_).main_line_destination_y );
     163            8 :     const double dest_end_length = fabs( (*this_).main_line_destination_x - (*this_).destination_end_x )
     164            8 :                                    + fabs( (*this_).main_line_destination_y - (*this_).destination_end_y );
     165              : 
     166            8 :     if ( distance_covered < source_end_length ) {
     167            2 :         if (( distance_covered <= 0.0 )||( source_end_length < 0.000000001 ))
     168              :         {
     169            1 :             geometry_point_init ( &result, (*this_).source_end_x, (*this_).source_end_y );
     170              :         }
     171              :         else
     172              :         {
     173            1 :             geometry_point_init ( &result, (*this_).source_end_x, (*this_).source_end_y );
     174            1 :             const double segment_part1 = distance_covered / source_end_length;
     175            1 :             geometry_point_shift( &result,
     176            1 :                                   segment_part1 * ( (*this_).main_line_source_x - (*this_).source_end_x ),
     177            1 :                                   segment_part1 * ( (*this_).main_line_source_y - (*this_).source_end_y )
     178              :                                 );
     179              :         }
     180              :     }
     181              :     else {
     182            6 :         const double shifted_distance = distance_covered - source_end_length;
     183            6 :         if (( shifted_distance < main_line_length )&&( main_line_length >= 0.000000001 ))
     184            2 :         {
     185            2 :             geometry_point_init ( &result, (*this_).main_line_source_x, (*this_).main_line_source_y );
     186            2 :             const double segment_part2 = shifted_distance / main_line_length;
     187            2 :             geometry_point_shift( &result,
     188            2 :                                   segment_part2 * ( (*this_).main_line_destination_x - (*this_).main_line_source_x ),
     189            2 :                                   segment_part2 * ( (*this_).main_line_destination_y - (*this_).main_line_source_y )
     190              :                                 );
     191              :         }
     192              :         else
     193              :         {
     194            4 :             const double shifted2_distance = shifted_distance - main_line_length;
     195            4 :             if (( shifted2_distance < dest_end_length )&&( dest_end_length >= 0.000000001 ))
     196            2 :             {
     197            2 :                 geometry_point_init ( &result, (*this_).main_line_destination_x, (*this_).main_line_destination_y );
     198            2 :                 const double segment_part3 = shifted2_distance / dest_end_length;
     199            2 :                 geometry_point_shift( &result,
     200            2 :                                     segment_part3 * ( (*this_).destination_end_x - (*this_).main_line_destination_x ),
     201            2 :                                     segment_part3 * ( (*this_).destination_end_y - (*this_).main_line_destination_y )
     202              :                                     );
     203              :             }
     204              :             else
     205              :             {
     206            2 :                 geometry_point_init ( &result, (*this_).destination_end_x, (*this_).destination_end_y );
     207              :             }
     208              :         }
     209              :     }
     210              : 
     211            8 :     return result;
     212              : }
     213              : 
     214            2 : static inline double geometry_connector_get_length ( const geometry_connector_t *this_ )
     215              : {
     216            2 :     const double source_end_length
     217            2 :         = fabs( (*this_).source_end_x - (*this_).main_line_source_x )
     218            2 :         + fabs( (*this_).source_end_y - (*this_).main_line_source_y );
     219            2 :     const double main_line_length
     220            2 :         = fabs( (*this_).main_line_source_x - (*this_).main_line_destination_x )
     221            2 :         + fabs( (*this_).main_line_source_y - (*this_).main_line_destination_y );
     222            2 :     const double dest_end_length
     223            2 :         = fabs( (*this_).main_line_destination_x - (*this_).destination_end_x )
     224            2 :         + fabs( (*this_).main_line_destination_y - (*this_).destination_end_y );
     225            2 :     return source_end_length + main_line_length + dest_end_length;
     226              : }
     227              : 
     228            1 : static inline double geometry_connector_get_source_length ( const geometry_connector_t *this_ )
     229              : {
     230            1 :     const double source_end_length
     231            1 :         = fabs( (*this_).source_end_x - (*this_).main_line_source_x )
     232            1 :         + fabs( (*this_).source_end_y - (*this_).main_line_source_y );
     233            1 :     return source_end_length;
     234              : }
     235              : 
     236            1 : static inline double geometry_connector_get_main_length ( const geometry_connector_t *this_ )
     237              : {
     238            1 :     const double main_line_length
     239            1 :         = fabs( (*this_).main_line_source_x - (*this_).main_line_destination_x )
     240            1 :         + fabs( (*this_).main_line_source_y - (*this_).main_line_destination_y );
     241            1 :     return main_line_length;
     242              : }
     243              : 
     244            1 : static inline double geometry_connector_get_destination_length ( const geometry_connector_t *this_ )
     245              : {
     246            1 :     const double dest_end_length
     247            1 :         = fabs( (*this_).main_line_destination_x - (*this_).destination_end_x )
     248            1 :         + fabs( (*this_).main_line_destination_y - (*this_).destination_end_y );
     249            1 :     return dest_end_length;
     250              : }
     251              : 
     252            6 : static inline bool geometry_connector_is_close ( const geometry_connector_t *this_, double x, double y, double max_distance )
     253              : {
     254            6 :     const bool close_to_source_end_line
     255            4 :         = ((( (*this_).source_end_x - max_distance < x ) && ( x < (*this_).main_line_source_x + max_distance ))
     256            3 :         || (( (*this_).main_line_source_x - max_distance < x ) && ( x < (*this_).source_end_x + max_distance )))
     257           14 :         && ((( (*this_).source_end_y - max_distance < y ) && ( y < (*this_).main_line_source_y + max_distance ))
     258            2 :         || (( (*this_).main_line_source_y - max_distance < y ) && ( y < (*this_).source_end_y + max_distance )));
     259            6 :     const bool close_to_main_line
     260            6 :         = ((( (*this_).main_line_destination_x - max_distance < x ) && ( x < (*this_).main_line_source_x + max_distance ))
     261            1 :         || (( (*this_).main_line_source_x - max_distance < x ) && ( x < (*this_).main_line_destination_x + max_distance )))
     262           17 :         && ((( (*this_).main_line_destination_y - max_distance < y ) && ( y < (*this_).main_line_source_y + max_distance ))
     263            5 :         || (( (*this_).main_line_source_y - max_distance < y ) && ( y < (*this_).main_line_destination_y + max_distance )));
     264            6 :     const bool close_to_destination_end_line
     265            6 :         = ((( (*this_).main_line_destination_x - max_distance < x ) && ( x < (*this_).destination_end_x + max_distance ))
     266            1 :         || (( (*this_).destination_end_x - max_distance < x ) && ( x < (*this_).main_line_destination_x + max_distance )))
     267           17 :         && ((( (*this_).main_line_destination_y - max_distance < y ) && ( y < (*this_).destination_end_y + max_distance ))
     268            5 :         || (( (*this_).destination_end_y - max_distance < y ) && ( y < (*this_).main_line_destination_y + max_distance )));
     269            6 :     return ( close_to_source_end_line || close_to_main_line || close_to_destination_end_line );
     270              : }
     271              : 
     272           10 : static inline bool geometry_connector_is_intersecting_rectangle ( const geometry_connector_t *this_,
     273              :                                                                   const geometry_rectangle_t *rect )
     274              : {
     275              :     geometry_rectangle_t source;
     276              :     geometry_rectangle_t main_line;
     277              :     geometry_rectangle_t destination;
     278           10 :     geometry_rectangle_init_by_corners( &source,
     279           10 :                                         (*this_).source_end_x, (*this_).source_end_y,
     280           10 :                                         (*this_).main_line_source_x, (*this_).main_line_source_y
     281              :                                       );
     282           10 :     geometry_rectangle_init_by_corners( &main_line,
     283           10 :                                         (*this_).main_line_source_x, (*this_).main_line_source_y,
     284           10 :                                         (*this_).main_line_destination_x, (*this_).main_line_destination_y
     285              :                                       );
     286           10 :     geometry_rectangle_init_by_corners( &destination,
     287           10 :                                         (*this_).main_line_destination_x, (*this_).main_line_destination_y,
     288           10 :                                         (*this_).destination_end_x, (*this_).destination_end_y
     289              :                                       );
     290              : 
     291           10 :     const bool result
     292           10 :         = geometry_rectangle_is_intersecting( &source, rect )
     293           10 :         || geometry_rectangle_is_intersecting( &main_line, rect )
     294           20 :         || geometry_rectangle_is_intersecting( &destination, rect );
     295              : 
     296           10 :     geometry_rectangle_destroy( &source );
     297           10 :     geometry_rectangle_destroy( &main_line );
     298           10 :     geometry_rectangle_destroy( &destination );
     299              : 
     300           10 :     return result;
     301              : }
     302              : 
     303            4 : static inline double geometry_connector_get_transit_length ( const geometry_connector_t *this_,
     304              :                                                              const geometry_rectangle_t *rect )
     305              : {
     306            4 :     double result = 0.0;
     307              : 
     308              :     geometry_rectangle_t source;
     309              :     geometry_rectangle_t main_line;
     310              :     geometry_rectangle_t destination;
     311            4 :     geometry_rectangle_init_by_corners( &source,
     312            4 :                                         (*this_).source_end_x, (*this_).source_end_y,
     313            4 :                                         (*this_).main_line_source_x, (*this_).main_line_source_y
     314              :                                       );
     315            4 :     geometry_rectangle_init_by_corners( &main_line,
     316            4 :                                         (*this_).main_line_source_x, (*this_).main_line_source_y,
     317            4 :                                         (*this_).main_line_destination_x, (*this_).main_line_destination_y
     318              :                                       );
     319            4 :     geometry_rectangle_init_by_corners( &destination,
     320            4 :                                         (*this_).main_line_destination_x, (*this_).main_line_destination_y,
     321            4 :                                         (*this_).destination_end_x, (*this_).destination_end_y
     322              :                                       );
     323            4 :     const int src_err = geometry_rectangle_init_by_intersect( &source, &source, rect );
     324            4 :     const int main_err = geometry_rectangle_init_by_intersect( &main_line, &main_line, rect );
     325            4 :     const int dst_err = geometry_rectangle_init_by_intersect( &destination, &destination, rect );
     326            4 :     if ( src_err == 0 )
     327              :     {
     328            2 :         result += geometry_rectangle_get_width( &source ) + geometry_rectangle_get_height( &source );
     329              :     }
     330            4 :     if ( main_err == 0 )
     331              :     {
     332            3 :         result += geometry_rectangle_get_width( &main_line ) + geometry_rectangle_get_height( &main_line );
     333              :     }
     334            4 :     if ( dst_err == 0 )
     335              :     {
     336            3 :         result += geometry_rectangle_get_width( &destination ) + geometry_rectangle_get_height( &destination );
     337              :     }
     338            4 :     geometry_rectangle_destroy( &source );
     339            4 :     geometry_rectangle_destroy( &main_line );
     340            4 :     geometry_rectangle_destroy( &destination );
     341              : 
     342            4 :     return result;
     343              : }
     344              : 
     345            6 : static inline uint32_t geometry_connector_count_connector_intersects ( const geometry_connector_t *this_,
     346              :                                                                        const geometry_connector_t *that )
     347              : {
     348            6 :     uint32_t result = 0;
     349              : 
     350              :     /* do some simple prechecks */
     351              :     geometry_rectangle_t this_bounds;
     352              :     geometry_rectangle_t that_bounds;
     353              : 
     354            6 :     this_bounds = geometry_connector_get_bounding_rectangle( this_ );
     355            6 :     that_bounds = geometry_connector_get_bounding_rectangle( that );
     356              : 
     357            6 :     if ( geometry_rectangle_is_contiguous( &this_bounds, &that_bounds ) )
     358              :     {
     359              :         /* do some more complicated checks */
     360              :         geometry_rectangle_t this_source_end;
     361              :         geometry_rectangle_t this_main_line;
     362              :         geometry_rectangle_t this_destination_end;
     363              :         geometry_rectangle_t that_source_end;
     364              :         geometry_rectangle_t that_main_line;
     365              :         geometry_rectangle_t that_destination_end;
     366              : 
     367            5 :         geometry_rectangle_init_by_corners( &this_source_end,
     368            5 :                                             (*this_).main_line_source_x, (*this_).main_line_source_y, (*this_).source_end_x, (*this_).source_end_y
     369              :                                           );
     370            5 :         geometry_rectangle_init_by_corners( &this_main_line,
     371            5 :                                             (*this_).main_line_destination_x, (*this_).main_line_destination_y, (*this_).main_line_source_x, (*this_).main_line_source_y
     372              :                                           );
     373            5 :         geometry_rectangle_init_by_corners( &this_destination_end,
     374            5 :                                             (*this_).destination_end_x, (*this_).destination_end_y, (*this_).main_line_destination_x, (*this_).main_line_destination_y
     375              :                                           );
     376            5 :         geometry_rectangle_init_by_corners( &that_source_end,
     377            5 :                                             (*that).main_line_source_x, (*that).main_line_source_y, (*that).source_end_x, (*that).source_end_y
     378              :                                           );
     379            5 :         geometry_rectangle_init_by_corners( &that_main_line,
     380            5 :                                             (*that).main_line_destination_x, (*that).main_line_destination_y, (*that).main_line_source_x, (*that).main_line_source_y
     381              :                                           );
     382            5 :         geometry_rectangle_init_by_corners( &that_destination_end,
     383            5 :                                             (*that).destination_end_x, (*that).destination_end_y, (*that).main_line_destination_x, (*that).main_line_destination_y
     384              :                                           );
     385              : 
     386            5 :         if ( geometry_rectangle_is_contiguous( &this_source_end, &that_source_end ) )
     387              :         {
     388            3 :             result += 1;
     389              :         }
     390            5 :         if ( geometry_rectangle_is_contiguous( &this_main_line, &that_source_end ) )
     391              :         {
     392            3 :             result += 1;
     393              :         }
     394            5 :         if ( geometry_rectangle_is_contiguous( &this_destination_end, &that_source_end ) )
     395              :         {
     396            1 :             result += 1;
     397              :         }
     398            5 :         if ( geometry_rectangle_is_contiguous( &this_source_end, &that_main_line ) )
     399              :         {
     400            2 :             result += 1;
     401              :         }
     402            5 :         if ( geometry_rectangle_is_contiguous( &this_main_line, &that_main_line ) )
     403              :         {
     404            2 :             result += 1;
     405              :         }
     406            5 :         if ( geometry_rectangle_is_contiguous( &this_destination_end, &that_main_line ) )
     407              :         {
     408            2 :             result += 1;
     409              :         }
     410            5 :         if ( geometry_rectangle_is_contiguous( &this_source_end, &that_destination_end ) )
     411              :         {
     412            2 :             result += 1;
     413              :         }
     414            5 :         if ( geometry_rectangle_is_contiguous( &this_main_line, &that_destination_end ) )
     415              :         {
     416            3 :             result += 1;
     417              :         }
     418            5 :         if ( geometry_rectangle_is_contiguous( &this_destination_end, &that_destination_end ) )
     419              :         {
     420            3 :             result += 1;
     421              :         }
     422              : 
     423            5 :         geometry_rectangle_destroy( &this_source_end );
     424            5 :         geometry_rectangle_destroy( &this_main_line );
     425            5 :         geometry_rectangle_destroy( &this_destination_end );
     426            5 :         geometry_rectangle_destroy( &that_source_end );
     427            5 :         geometry_rectangle_destroy( &that_main_line );
     428            5 :         geometry_rectangle_destroy( &that_destination_end );
     429              :     }
     430              :     /* else no intersects, result = 0 */
     431              : 
     432            6 :     geometry_rectangle_destroy( &this_bounds );
     433            6 :     geometry_rectangle_destroy( &that_bounds );
     434              : 
     435            6 :     return result;
     436              : }
     437              : 
     438            7 : static inline double geometry_connector_get_same_path_length_rect( const geometry_connector_t *this_,
     439              :                                                                    const geometry_rectangle_t *rect,
     440              :                                                                    double max_distance )
     441              : {
     442            7 :     double result = 0.0;
     443              : 
     444            7 :     const double left = geometry_rectangle_get_left( rect );
     445            7 :     const double top = geometry_rectangle_get_top( rect );
     446            7 :     const double right = geometry_rectangle_get_right( rect );
     447            7 :     const double bottom = geometry_rectangle_get_bottom( rect );
     448            7 :     const u8_interval_t x_length = u8_interval_new( left, right );
     449            7 :     const u8_interval_t y_length = u8_interval_new( top, bottom );
     450              : 
     451              :     /* check same path with left side of rectangle */
     452              :     {
     453            7 :         const double left_lo = left - max_distance;
     454            7 :         const double left_hi = left + max_distance;
     455              : 
     456            7 :         const bool source_end_is_on_left_side
     457            7 :             = ( left_lo < (*this_).source_end_x )&&( (*this_).source_end_x < left_hi );
     458            7 :         const bool main_line_source_is_on_left_side
     459            7 :             = ( left_lo < (*this_).main_line_source_x )&&( (*this_).main_line_source_x < left_hi );
     460            7 :         const bool main_line_end_is_on_left_side
     461            7 :             = ( left_lo < (*this_).main_line_destination_x )&&( (*this_).main_line_destination_x < left_hi );
     462            7 :         const bool destination_end_is_on_left_side
     463            7 :             = ( left_lo < (*this_).destination_end_x )&&( (*this_).destination_end_x < left_hi );
     464            7 :         if ( source_end_is_on_left_side && main_line_source_is_on_left_side )
     465              :         {
     466            1 :             const u8_interval_t section_y = u8_interval_new_unordered( (*this_).source_end_y, (*this_).main_line_source_y );
     467            1 :             const u8_interval_t intersect = u8_interval_new_intersect( &y_length, &section_y );
     468            1 :             result += u8_interval_get_size( &intersect );
     469              :         }
     470            7 :         if ( main_line_source_is_on_left_side && main_line_end_is_on_left_side )
     471              :         {
     472            1 :             const u8_interval_t section_y = u8_interval_new_unordered( (*this_).main_line_source_y, (*this_).main_line_destination_y );
     473            1 :             const u8_interval_t intersect = u8_interval_new_intersect( &y_length, &section_y );
     474            1 :             result += u8_interval_get_size( &intersect );
     475              :         }
     476            7 :         if ( main_line_end_is_on_left_side && destination_end_is_on_left_side )
     477              :         {
     478            2 :             const u8_interval_t section_y = u8_interval_new_unordered( (*this_).main_line_destination_y, (*this_).destination_end_y );
     479            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &y_length, &section_y );
     480            2 :             result += u8_interval_get_size( &intersect );
     481              :         }
     482              :     }
     483              : 
     484              :     /* check same path with top side of rectangle */
     485              :     {
     486            7 :         const double top_lo = top - max_distance;
     487            7 :         const double top_hi = top + max_distance;
     488              : 
     489            7 :         const bool source_end_is_on_top_side
     490            7 :             = ( top_lo < (*this_).source_end_y )&&( (*this_).source_end_y < top_hi );
     491            7 :         const bool main_line_source_is_on_top_side
     492            7 :             = ( top_lo < (*this_).main_line_source_y )&&( (*this_).main_line_source_y < top_hi );
     493            7 :         const bool main_line_end_is_on_top_side
     494            7 :             = ( top_lo < (*this_).main_line_destination_y )&&( (*this_).main_line_destination_y < top_hi );
     495            7 :         const bool destination_end_is_on_top_side
     496            7 :             = ( top_lo < (*this_).destination_end_y )&&( (*this_).destination_end_y < top_hi );
     497            7 :         if ( source_end_is_on_top_side && main_line_source_is_on_top_side )
     498              :         {
     499            2 :             const u8_interval_t section_x = u8_interval_new_unordered( (*this_).source_end_x, (*this_).main_line_source_x );
     500            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &x_length, &section_x );
     501            2 :             result += u8_interval_get_size( &intersect );
     502              :         }
     503            7 :         if ( main_line_source_is_on_top_side && main_line_end_is_on_top_side )
     504              :         {
     505            2 :             const u8_interval_t section_x = u8_interval_new_unordered( (*this_).main_line_source_x, (*this_).main_line_destination_x );
     506            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &x_length, &section_x );
     507            2 :             result += u8_interval_get_size( &intersect );
     508              :         }
     509            7 :         if ( main_line_end_is_on_top_side && destination_end_is_on_top_side )
     510              :         {
     511            1 :             const u8_interval_t section_x = u8_interval_new_unordered( (*this_).main_line_destination_x, (*this_).destination_end_x );
     512            1 :             const u8_interval_t intersect = u8_interval_new_intersect( &x_length, &section_x );
     513            1 :             result += u8_interval_get_size( &intersect );
     514              :         }
     515              :     }
     516              :     /* check same path with right side of rectangle */
     517              :     {
     518            7 :         const double right_lo = right - max_distance;
     519            7 :         const double right_hi = right + max_distance;
     520              : 
     521            7 :         const bool source_end_is_on_right_side
     522            7 :             = ( right_lo < (*this_).source_end_x )&&( (*this_).source_end_x < right_hi );
     523            7 :         const bool main_line_source_is_on_right_side
     524            7 :             = ( right_lo < (*this_).main_line_source_x )&&( (*this_).main_line_source_x < right_hi );
     525            7 :         const bool main_line_end_is_on_right_side
     526            7 :             = ( right_lo < (*this_).main_line_destination_x )&&( (*this_).main_line_destination_x < right_hi );
     527            7 :         const bool destination_end_is_on_right_side
     528            7 :             = ( right_lo < (*this_).destination_end_x )&&( (*this_).destination_end_x < right_hi );
     529            7 :         if ( source_end_is_on_right_side && main_line_source_is_on_right_side )
     530              :         {
     531            1 :             const u8_interval_t section_y = u8_interval_new_unordered( (*this_).source_end_y, (*this_).main_line_source_y );
     532            1 :             const u8_interval_t intersect = u8_interval_new_intersect( &y_length, &section_y );
     533            1 :             result += u8_interval_get_size( &intersect );
     534              :         }
     535            7 :         if ( main_line_source_is_on_right_side && main_line_end_is_on_right_side )
     536              :         {
     537            1 :             const u8_interval_t section_y = u8_interval_new_unordered( (*this_).main_line_source_y, (*this_).main_line_destination_y );
     538            1 :             const u8_interval_t intersect = u8_interval_new_intersect( &y_length, &section_y );
     539            1 :             result += u8_interval_get_size( &intersect );
     540              :         }
     541            7 :         if ( main_line_end_is_on_right_side && destination_end_is_on_right_side )
     542              :         {
     543            3 :             const u8_interval_t section_y = u8_interval_new_unordered( (*this_).main_line_destination_y, (*this_).destination_end_y );
     544            3 :             const u8_interval_t intersect = u8_interval_new_intersect( &y_length, &section_y );
     545            3 :             result += u8_interval_get_size( &intersect );
     546              :         }
     547              :     }
     548              :     /* check same path with bottom side of rectangle */
     549              :     {
     550            7 :         const double bottom_lo = bottom - max_distance;
     551            7 :         const double bottom_hi = bottom + max_distance;
     552              : 
     553            7 :         const bool source_end_is_on_bottom_side
     554            7 :             = ( bottom_lo < (*this_).source_end_y )&&( (*this_).source_end_y < bottom_hi );
     555            7 :         const bool main_line_source_is_on_bottom_side
     556            7 :             = ( bottom_lo < (*this_).main_line_source_y )&&( (*this_).main_line_source_y < bottom_hi );
     557            7 :         const bool main_line_end_is_on_bottom_side
     558            7 :             = ( bottom_lo < (*this_).main_line_destination_y )&&( (*this_).main_line_destination_y < bottom_hi );
     559            7 :         const bool destination_end_is_on_bottom_side
     560            7 :             = ( bottom_lo < (*this_).destination_end_y )&&( (*this_).destination_end_y < bottom_hi );
     561            7 :         if ( source_end_is_on_bottom_side && main_line_source_is_on_bottom_side )
     562              :         {
     563            1 :             const u8_interval_t section_x = u8_interval_new_unordered( (*this_).source_end_x, (*this_).main_line_source_x );
     564            1 :             const u8_interval_t intersect = u8_interval_new_intersect( &x_length, &section_x );
     565            1 :             result += u8_interval_get_size( &intersect );
     566              :         }
     567            7 :         if ( main_line_source_is_on_bottom_side && main_line_end_is_on_bottom_side )
     568              :         {
     569            3 :             const u8_interval_t section_x = u8_interval_new_unordered( (*this_).main_line_source_x, (*this_).main_line_destination_x );
     570            3 :             const u8_interval_t intersect = u8_interval_new_intersect( &x_length, &section_x );
     571            3 :             result += u8_interval_get_size( &intersect );
     572              :         }
     573            7 :         if ( main_line_end_is_on_bottom_side && destination_end_is_on_bottom_side )
     574              :         {
     575            2 :             const u8_interval_t section_x = u8_interval_new_unordered( (*this_).main_line_destination_x, (*this_).destination_end_x );
     576            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &x_length, &section_x );
     577            2 :             result += u8_interval_get_size( &intersect );
     578              :         }
     579              :     }
     580              : 
     581            7 :     return result;
     582              : }
     583              : 
     584           20 : static inline double geometry_connector_get_same_path_length_conn( const geometry_connector_t *this_,
     585              :                                                                    const geometry_connector_t *that,
     586              :                                                                    double max_distance )
     587              : {
     588           20 :     double result = 0.0;
     589              : 
     590           20 :     const double source_x = (*that).main_line_source_x;
     591           20 :     const double source_y = (*that).main_line_source_y;
     592           20 :     const double destination_x = (*that).main_line_destination_x;
     593           20 :     const double destination_y = (*that).main_line_destination_y;
     594              : 
     595           20 :     const double source_x_lo = source_x - max_distance;
     596           20 :     const double source_x_hi = source_x + max_distance;
     597           20 :     const double source_y_lo = source_y - max_distance;
     598           20 :     const double source_y_hi = source_y + max_distance;
     599           20 :     const double destination_x_lo = destination_x - max_distance;
     600           20 :     const double destination_x_hi = destination_x + max_distance;
     601           20 :     const double destination_y_lo = destination_y - max_distance;
     602           20 :     const double destination_y_hi = destination_y + max_distance;
     603           20 :     const bool source_x_on_source_x
     604           20 :         = ( source_x_lo < (*this_).main_line_source_x )&&( (*this_).main_line_source_x < source_x_hi );
     605           20 :     const bool source_y_on_source_y
     606           20 :         = ( source_y_lo < (*this_).main_line_source_y )&&( (*this_).main_line_source_y < source_y_hi );
     607           20 :     const bool destination_x_on_source_x
     608           20 :         = ( source_x_lo < (*this_).main_line_destination_x )&&( (*this_).main_line_destination_x < source_x_hi );
     609           20 :     const bool destination_y_on_source_y
     610           20 :         = ( source_y_lo < (*this_).main_line_destination_y )&&( (*this_).main_line_destination_y < source_y_hi );
     611           20 :     const bool source_x_on_destination_x
     612           20 :         = ( destination_x_lo < (*this_).main_line_source_x )&&( (*this_).main_line_source_x < destination_x_hi );
     613           20 :     const bool source_y_on_destination_y
     614           20 :         = ( destination_y_lo < (*this_).main_line_source_y )&&( (*this_).main_line_source_y < destination_y_hi );
     615           20 :     const bool destination_x_on_destination_x
     616           20 :         = ( destination_x_lo < (*this_).main_line_destination_x )&&( (*this_).main_line_destination_x < destination_x_hi );
     617           20 :     const bool destination_y_on_destination_y
     618           20 :         = ( destination_y_lo < (*this_).main_line_destination_y )&&( (*this_).main_line_destination_y < destination_y_hi );
     619              : 
     620           20 :     const geometry_3dir_t this_dir = geometry_connector_get_directions( this_ );
     621           20 :     const geometry_3dir_t that_dir = geometry_connector_get_directions( that );
     622              : 
     623              :     /* check same path with source segment of that */
     624           20 :     if ( geometry_3dir_is_first_v( &that_dir ) )
     625              :     {
     626            9 :         const u8_interval_t source_dy = u8_interval_new_unordered( (*that).source_end_y, (*that).main_line_source_y );
     627              : 
     628            9 :         if ( geometry_3dir_is_first_v( &this_dir ) && source_x_on_source_x )
     629              :         {
     630            1 :             const u8_interval_t section_dy = u8_interval_new_unordered( (*this_).source_end_y, (*this_).main_line_source_y );
     631            1 :             const u8_interval_t intersect = u8_interval_new_intersect( &source_dy, &section_dy );
     632            1 :             result += u8_interval_get_size( &intersect );
     633              :         }
     634            9 :         if ( geometry_3dir_is_second_v( &this_dir ) && source_x_on_source_x )
     635              :         {
     636            2 :             const u8_interval_t section_dy = u8_interval_new_unordered( (*this_).main_line_source_y, (*this_).main_line_destination_y );
     637            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &source_dy, &section_dy );
     638            2 :             result += u8_interval_get_size( &intersect );
     639              :         }
     640            9 :         if ( geometry_3dir_is_third_v( &this_dir ) && destination_x_on_source_x )
     641              :         {
     642            2 :             const u8_interval_t section_dy = u8_interval_new_unordered( (*this_).main_line_destination_y, (*this_).destination_end_y );
     643            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &source_dy, &section_dy );
     644            2 :             result += u8_interval_get_size( &intersect );
     645              :         }
     646              :     }
     647              :     else /* geometry_3dir_is_first_h( &that_dir ) */
     648              :     {
     649           11 :         const u8_interval_t source_dx = u8_interval_new_unordered( (*that).source_end_x, (*that).main_line_source_x );
     650              : 
     651           11 :         if ( geometry_3dir_is_first_h( &this_dir ) && source_y_on_source_y )
     652              :         {
     653            3 :             const u8_interval_t section_dx = u8_interval_new_unordered( (*this_).source_end_x, (*this_).main_line_source_x );
     654            3 :             const u8_interval_t intersect = u8_interval_new_intersect( &source_dx, &section_dx );
     655            3 :             result += u8_interval_get_size( &intersect );
     656              :         }
     657           11 :         if ( geometry_3dir_is_second_h( &this_dir ) && source_y_on_source_y )
     658              :         {
     659            2 :             const u8_interval_t section_dx = u8_interval_new_unordered( (*this_).main_line_source_x, (*this_).main_line_destination_x );
     660            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &source_dx, &section_dx );
     661            2 :             result += u8_interval_get_size( &intersect );
     662              :         }
     663           11 :         if ( geometry_3dir_is_third_h( &this_dir ) && destination_y_on_source_y )
     664              :         {
     665            2 :             const u8_interval_t section_dx = u8_interval_new_unordered( (*this_).main_line_destination_x, (*this_).destination_end_x );
     666            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &source_dx, &section_dx );
     667            2 :             result += u8_interval_get_size( &intersect );
     668              :         }
     669              :     }
     670              : 
     671              :     /* check same path with main segment of that */
     672           20 :     if ( geometry_3dir_is_second_v( &that_dir ) )
     673              :     {
     674           11 :         const u8_interval_t main_dy = u8_interval_new_unordered( (*that).main_line_source_y, (*that).main_line_destination_y );
     675              : 
     676           11 :         if ( geometry_3dir_is_first_v( &this_dir ) && source_x_on_source_x )
     677              :         {
     678            2 :             const u8_interval_t section_dy = u8_interval_new_unordered( (*this_).source_end_y, (*this_).main_line_source_y );
     679            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &main_dy, &section_dy );
     680            2 :             result += u8_interval_get_size( &intersect );
     681              :         }
     682           11 :         if ( geometry_3dir_is_second_v( &this_dir ) && source_x_on_source_x )
     683              :         {
     684            5 :             const u8_interval_t section_dy = u8_interval_new_unordered( (*this_).main_line_source_y, (*this_).main_line_destination_y );
     685            5 :             const u8_interval_t intersect = u8_interval_new_intersect( &main_dy, &section_dy );
     686            5 :             result += u8_interval_get_size( &intersect );
     687              :         }
     688           11 :         if ( geometry_3dir_is_third_v( &this_dir ) && destination_x_on_source_x )
     689              :         {
     690            2 :             const u8_interval_t section_dy = u8_interval_new_unordered( (*this_).main_line_destination_y, (*this_).destination_end_y );
     691            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &main_dy, &section_dy );
     692            2 :             result += u8_interval_get_size( &intersect );
     693              :         }
     694              :     }
     695              :     else /* geometry_3dir_is_second_h( &that_dir ) */
     696              :     {
     697            9 :         const u8_interval_t main_dx = u8_interval_new_unordered( (*that).main_line_source_x, (*that).main_line_destination_x );
     698              : 
     699            9 :         if ( geometry_3dir_is_first_h( &this_dir ) && source_y_on_source_y )
     700              :         {
     701            2 :             const u8_interval_t section_dx = u8_interval_new_unordered( (*this_).source_end_x, (*this_).main_line_source_x );
     702            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &main_dx, &section_dx );
     703            2 :             result += u8_interval_get_size( &intersect );
     704              :         }
     705            9 :         if ( geometry_3dir_is_second_h( &this_dir ) && source_y_on_source_y )
     706              :         {
     707            3 :             const u8_interval_t section_dx = u8_interval_new_unordered( (*this_).main_line_source_x, (*this_).main_line_destination_x );
     708            3 :             const u8_interval_t intersect = u8_interval_new_intersect( &main_dx, &section_dx );
     709            3 :             result += u8_interval_get_size( &intersect );
     710              :         }
     711            9 :         if ( geometry_3dir_is_third_h( &this_dir ) && destination_y_on_source_y )
     712              :         {
     713            3 :             const u8_interval_t section_dx = u8_interval_new_unordered( (*this_).main_line_destination_x, (*this_).destination_end_x );
     714            3 :             const u8_interval_t intersect = u8_interval_new_intersect( &main_dx, &section_dx );
     715            3 :             result += u8_interval_get_size( &intersect );
     716              :         }
     717              :     }
     718              : 
     719              :     /* check same path with destination segment of that */
     720           20 :     if ( geometry_3dir_is_third_v( &that_dir ) )
     721              :     {
     722            9 :         const u8_interval_t destination_dy = u8_interval_new_unordered( (*that).main_line_destination_y, (*that).destination_end_y );
     723              : 
     724            9 :         if ( geometry_3dir_is_first_v( &this_dir ) && source_x_on_destination_x )
     725              :         {
     726            2 :             const u8_interval_t section_dy = u8_interval_new_unordered( (*this_).source_end_y, (*this_).main_line_source_y );
     727            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &destination_dy, &section_dy );
     728            2 :             result += u8_interval_get_size( &intersect );
     729              :         }
     730            9 :         if ( geometry_3dir_is_second_v( &this_dir ) && source_x_on_destination_x )
     731              :         {
     732            2 :             const u8_interval_t section_dy = u8_interval_new_unordered( (*this_).main_line_source_y, (*this_).main_line_destination_y );
     733            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &destination_dy, &section_dy );
     734            2 :             result += u8_interval_get_size( &intersect );
     735              :         }
     736            9 :         if ( geometry_3dir_is_third_v( &this_dir ) && destination_x_on_destination_x )
     737              :         {
     738            1 :             const u8_interval_t section_dy = u8_interval_new_unordered( (*this_).main_line_destination_y, (*this_).destination_end_y );
     739            1 :             const u8_interval_t intersect = u8_interval_new_intersect( &destination_dy, &section_dy );
     740            1 :             result += u8_interval_get_size( &intersect );
     741              :         }
     742              :     }
     743              :     else /* geometry_3dir_is_third_h( &that_dir ) */
     744              :     {
     745           11 :         const u8_interval_t destination_dx = u8_interval_new_unordered( (*that).main_line_destination_x, (*that).destination_end_x );
     746              : 
     747           11 :         if ( geometry_3dir_is_first_h( &this_dir ) && source_y_on_destination_y )
     748              :         {
     749            2 :             const u8_interval_t section_dx = u8_interval_new_unordered( (*this_).source_end_x, (*this_).main_line_source_x );
     750            2 :             const u8_interval_t intersect = u8_interval_new_intersect( &destination_dx, &section_dx );
     751            2 :             result += u8_interval_get_size( &intersect );
     752              :         }
     753           11 :         if ( geometry_3dir_is_second_h( &this_dir ) && source_y_on_destination_y )
     754              :         {
     755            3 :             const u8_interval_t section_dx = u8_interval_new_unordered( (*this_).main_line_source_x, (*this_).main_line_destination_x );
     756            3 :             const u8_interval_t intersect = u8_interval_new_intersect( &destination_dx, &section_dx );
     757            3 :             result += u8_interval_get_size( &intersect );
     758              :         }
     759           11 :         if ( geometry_3dir_is_third_h( &this_dir ) && destination_y_on_destination_y )
     760              :         {
     761            1 :             const u8_interval_t section_dx = u8_interval_new_unordered( (*this_).main_line_destination_x, (*this_).destination_end_x );
     762            1 :             const u8_interval_t intersect = u8_interval_new_intersect( &destination_dx, &section_dx );
     763            1 :             result += u8_interval_get_size( &intersect );
     764              :         }
     765              :     }
     766              : 
     767           20 :     return result;
     768              : }
     769              : 
     770           15 : static inline geometry_rectangle_t geometry_connector_get_bounding_rectangle ( const geometry_connector_t *this_ )
     771              : {
     772              :     geometry_rectangle_t result;
     773              : 
     774           15 :     const double left = fmin ( (*this_).main_line_source_x, fmin( (*this_).source_end_x, (*this_).destination_end_x ) );
     775           15 :     const double right = fmax ( (*this_).main_line_source_x, fmax( (*this_).source_end_x, (*this_).destination_end_x ) );
     776           15 :     const double top = fmin ( (*this_).main_line_source_y, fmin( (*this_).source_end_y, (*this_).destination_end_y ) );
     777           15 :     const double bottom = fmax ( (*this_).main_line_source_y, fmax( (*this_).source_end_y, (*this_).destination_end_y ) );
     778              : 
     779           15 :     geometry_rectangle_init( &result,
     780              :                              left,
     781              :                              top,
     782              :                              right - left,
     783              :                              bottom - top
     784              :                            );
     785              : 
     786           15 :     return result;
     787              : }
     788              : 
     789            3 : static inline geometry_rectangle_t geometry_connector_get_segment_bounds ( const geometry_connector_t *this_,
     790              :                                                                            geometry_connector_segment_t segment_id )
     791              : {
     792            3 :     assert( ( segment_id == GEOMETRY_CONNECTOR_SEGMENT_SOURCE )
     793              :         ||( segment_id == GEOMETRY_CONNECTOR_SEGMENT_MAIN )||( segment_id == GEOMETRY_CONNECTOR_SEGMENT_DESTINATION ) );
     794              :     geometry_rectangle_t result;
     795              : 
     796            3 :     switch ( segment_id )
     797              :     {
     798            1 :         case GEOMETRY_CONNECTOR_SEGMENT_SOURCE:
     799              :         {
     800            1 :             const double left = fmin ( (*this_).main_line_source_x, (*this_).source_end_x );
     801            1 :             const double right = fmax ( (*this_).main_line_source_x, (*this_).source_end_x );
     802            1 :             const double top = fmin ( (*this_).main_line_source_y, (*this_).source_end_y );
     803            1 :             const double bottom = fmax ( (*this_).main_line_source_y, (*this_).source_end_y );
     804            1 :             geometry_rectangle_init( &result, left, top, right - left, bottom - top );
     805              :         }
     806            1 :         break;
     807              : 
     808            1 :         case GEOMETRY_CONNECTOR_SEGMENT_MAIN:
     809              :         default:
     810              :         {
     811            1 :             const double left = fmin ( (*this_).main_line_source_x, (*this_).main_line_destination_x );
     812            1 :             const double right = fmax ( (*this_).main_line_source_x, (*this_).main_line_destination_x );
     813            1 :             const double top = fmin ( (*this_).main_line_source_y, (*this_).main_line_destination_y );
     814            1 :             const double bottom = fmax ( (*this_).main_line_source_y, (*this_).main_line_destination_y );
     815            1 :             geometry_rectangle_init( &result, left, top, right - left, bottom - top );
     816              :         }
     817            1 :         break;
     818              : 
     819            1 :         case GEOMETRY_CONNECTOR_SEGMENT_DESTINATION:
     820              :         {
     821            1 :             const double left = fmin ( (*this_).destination_end_x, (*this_).main_line_destination_x );
     822            1 :             const double right = fmax ( (*this_).destination_end_x, (*this_).main_line_destination_x );
     823            1 :             const double top = fmin ( (*this_).destination_end_y, (*this_).main_line_destination_y );
     824            1 :             const double bottom = fmax ( (*this_).destination_end_y, (*this_).main_line_destination_y );
     825            1 :             geometry_rectangle_init( &result, left, top, right - left, bottom - top );
     826              :         }
     827            1 :         break;
     828              :     }
     829              : 
     830            3 :     return result;
     831              : }
     832              : 
     833           41 : static inline geometry_3dir_t geometry_connector_get_directions ( const geometry_connector_t *this_ )
     834              : {
     835           41 :     const double very_small = 0.000000001;
     836              : 
     837           41 :     const double src_dx = (*this_).main_line_source_x - (*this_).source_end_x;
     838           41 :     const double src_dy = (*this_).main_line_source_y - (*this_).source_end_y;
     839           41 :     const double abs_src_dx = fabs( src_dx );
     840           41 :     const double abs_src_dy = fabs( src_dy );
     841           41 :     const bool src_exists = (( abs_src_dx > very_small )||( abs_src_dy > very_small ));
     842           41 :     const bool src_is_horizontal = ( abs_src_dx > abs_src_dy );
     843              : 
     844           41 :     const geometry_direction_t src_dir
     845           41 :        = ( ! src_exists )
     846              :        ? GEOMETRY_DIRECTION_CENTER
     847           41 :        : src_is_horizontal
     848              :        ? (( src_dx > 0.0 ) ? GEOMETRY_DIRECTION_RIGHT : GEOMETRY_DIRECTION_LEFT )
     849              :        : (( src_dy > 0.0 ) ? GEOMETRY_DIRECTION_DOWN : GEOMETRY_DIRECTION_UP );
     850              : 
     851           41 :     const double main_dx = (*this_).main_line_destination_x - (*this_).main_line_source_x;
     852           41 :     const double main_dy = (*this_).main_line_destination_y - (*this_).main_line_source_y;
     853           41 :     const double abs_main_dx = fabs( main_dx );
     854           41 :     const double abs_main_dy = fabs( main_dy );
     855           41 :     const bool main_exists = (( abs_main_dx > very_small )||( abs_main_dy > very_small ));
     856           41 :     const bool main_is_horizontal = ( abs_main_dx > abs_main_dy );
     857              : 
     858           41 :     const geometry_direction_t main_dir
     859           41 :        = ( ! main_exists )
     860              :        ? GEOMETRY_DIRECTION_CENTER
     861           41 :        : main_is_horizontal
     862              :        ? (( main_dx > 0.0 ) ? GEOMETRY_DIRECTION_RIGHT : GEOMETRY_DIRECTION_LEFT )
     863              :        : (( main_dy > 0.0 ) ? GEOMETRY_DIRECTION_DOWN : GEOMETRY_DIRECTION_UP );
     864              : 
     865           41 :     const double dst_dx = (*this_).destination_end_x - (*this_).main_line_destination_x;
     866           41 :     const double dst_dy = (*this_).destination_end_y - (*this_).main_line_destination_y;
     867           41 :     const double abs_dst_dx = fabs( dst_dx );
     868           41 :     const double abs_dst_dy = fabs( dst_dy );
     869           41 :     const bool dst_exists = (( abs_dst_dx > very_small )||( abs_dst_dy > very_small ));
     870           41 :     const bool dst_is_horizontal = ( abs_dst_dx > abs_dst_dy );
     871              : 
     872           41 :     const geometry_direction_t dst_dir
     873           41 :        = ( ! dst_exists )
     874              :        ? GEOMETRY_DIRECTION_CENTER
     875           41 :        : dst_is_horizontal
     876              :        ? (( dst_dx > 0.0 ) ? GEOMETRY_DIRECTION_RIGHT : GEOMETRY_DIRECTION_LEFT )
     877              :        : (( dst_dy > 0.0 ) ? GEOMETRY_DIRECTION_DOWN : GEOMETRY_DIRECTION_UP );
     878              : 
     879           41 :     const geometry_3dir_t result = geometry_3dir_new( src_dir, main_dir, dst_dir );
     880           41 :     return result;
     881              : }
     882              : 
     883            1 : static inline void geometry_connector_trace ( const geometry_connector_t *this_ )
     884              : {
     885              :     static const char geometry_mnemomic[GEOMETRY_DIRECTION_MAX]
     886              :         = { '.', '<', 'F', '^', '7', '>', 'J', 'v', 'L' };
     887              : 
     888            1 :     const geometry_3dir_t pattern = geometry_connector_get_directions( this_ );
     889            1 :     const char pattern_as_str[6]
     890            1 :         = { [0] = geometry_mnemomic[pattern.first],
     891              :             [1] = ' ',
     892            1 :             [2] = geometry_mnemomic[pattern.second],
     893              :             [3] = ' ',
     894            1 :             [4] = geometry_mnemomic[pattern.third],
     895              :             [5] = '\0' };
     896              : 
     897            1 :     U8_TRACE_INFO( "geometry_connector_t" );
     898            1 :     U8_TRACE_INFO_INT( "- source_end_x:", (*this_).source_end_x );
     899            1 :     U8_TRACE_INFO_INT( "- source_end_y:", (*this_).source_end_y );
     900            1 :     U8_TRACE_INFO_INT( "- main_line_source_x:", (*this_).main_line_source_x );
     901            1 :     U8_TRACE_INFO_INT( "- main_line_source_y:", (*this_).main_line_source_y );
     902            1 :     U8_TRACE_INFO_INT( "- main_line_destination_x:", (*this_).main_line_destination_x );
     903            1 :     U8_TRACE_INFO_INT( "- main_line_destination_y:", (*this_).main_line_destination_y );
     904            1 :     U8_TRACE_INFO_INT( "- destination_end_x:", (*this_).destination_end_x );
     905            1 :     U8_TRACE_INFO_INT( "- destination_end_y:", (*this_).destination_end_y );
     906            1 :     U8_TRACE_INFO_STR( "- get_directions:", pattern_as_str );
     907            1 : }
     908              : 
     909              : 
     910              : /*
     911              : Copyright 2017-2025 Andreas Warnke
     912              : 
     913              : Licensed under the Apache License, Version 2.0 (the "License");
     914              : you may not use this file except in compliance with the License.
     915              : You may obtain a copy of the License at
     916              : 
     917              :     http://www.apache.org/licenses/LICENSE-2.0
     918              : 
     919              : Unless required by applicable law or agreed to in writing, software
     920              : distributed under the License is distributed on an "AS IS" BASIS,
     921              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     922              : See the License for the specific language governing permissions and
     923              : limitations under the License.
     924              : */
        

Generated by: LCOV version 2.0-1