LCOV - code coverage report
Current view: top level - pencil/include/geometry - geometry_connector.inl (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.65.6_covts Lines: 524 524 100.0 %
Date: 2025-09-25 21:07:53 Functions: 30 30 100.0 %

          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 1.16