LCOV - code coverage report
Current view: top level - pencil/source - pencil_relationship_2d_layouter.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.65.6_covts Lines: 0 829 0.0 %
Date: 2025-09-25 21:07:53 Functions: 0 15 0.0 %

          Line data    Source code
       1             : /* File: pencil_relationship_2d_layouter.c; Copyright and License: see below */
       2             : 
       3             : #include "pencil_relationship_2d_layouter.h"
       4             : #include "layout/layout_relationship_iter.h"
       5             : #include "layout/layout_quality.h"
       6             : #include "u8/u8_trace.h"
       7             : #include <pango/pangocairo.h>
       8             : #include <stdio.h>
       9             : #include <stdlib.h>
      10             : #include <math.h>
      11             : #include <stdint.h>
      12             : 
      13           0 : void pencil_relationship_2d_layouter_init( pencil_relationship_2d_layouter_t *this_,
      14             :                                            layout_visible_set_t *layout_data,
      15             :                                            const data_profile_part_t *profile,
      16             :                                            const pencil_size_t *pencil_size )
      17             : {
      18           0 :     U8_TRACE_BEGIN();
      19           0 :     assert( NULL != layout_data );
      20           0 :     assert( NULL != profile );
      21           0 :     assert( NULL != pencil_size );
      22             : 
      23           0 :     (*this_).layout_data = layout_data;
      24           0 :     (*this_).profile = profile;
      25             : 
      26           0 :     universal_array_index_sorter_init( &((*this_).sorted_relationships) );
      27           0 :     layout_relationship_iter_init( &((*this_).already_processed), layout_data, &((*this_).sorted_relationships) );
      28             : 
      29           0 :     (*this_).pencil_size = pencil_size;
      30           0 :     pencil_relationship_painter_init( &((*this_).relationship_painter) );
      31             : 
      32           0 :     U8_TRACE_END();
      33           0 : }
      34             : 
      35           0 : void pencil_relationship_2d_layouter_destroy( pencil_relationship_2d_layouter_t *this_ )
      36             : {
      37           0 :     U8_TRACE_BEGIN();
      38             : 
      39           0 :     layout_relationship_iter_destroy( &((*this_).already_processed) );
      40           0 :     universal_array_index_sorter_destroy( &((*this_).sorted_relationships) );
      41             : 
      42           0 :     pencil_relationship_painter_destroy( &((*this_).relationship_painter) );
      43             : 
      44           0 :     U8_TRACE_END();
      45           0 : }
      46             : 
      47           0 : void pencil_relationship_2d_layouter_private_do_layout ( pencil_relationship_2d_layouter_t *this_ )
      48             : {
      49           0 :     U8_TRACE_BEGIN();
      50             :     assert ( (unsigned int) UNIVERSAL_ARRAY_INDEX_SORTER_MAX_ARRAY_SIZE >= (unsigned int) LAYOUT_VISIBLE_SET_MAX_RELATIONSHIPS );
      51             : 
      52           0 :     universal_array_index_sorter_reinit( &((*this_).sorted_relationships) );
      53             : 
      54             :     /* sort the relationships by their movement-needs, drop invisible relations */
      55           0 :     pencil_relationship_2d_layouter_private_propose_processing_order ( this_ );
      56             : 
      57             :     /* shape the relationships */
      58             :     layout_relationship_iter_t relationship_iterator;
      59           0 :     layout_relationship_iter_init( &relationship_iterator, (*this_).layout_data, &((*this_).sorted_relationships) );
      60           0 :     while ( layout_relationship_iter_has_next( &relationship_iterator ) )
      61             :     {
      62             :         /* initialize the already processed relationship iterator - it is needed by called methods */
      63           0 :         layout_relationship_iter_destroy( &((*this_).already_processed) );
      64           0 :         layout_relationship_iter_init_from_processed( &((*this_).already_processed), &relationship_iterator );
      65             : 
      66             :         /* determine pointer to relationship */
      67           0 :         layout_relationship_t *const current_relationship = layout_relationship_iter_next_ptr( &relationship_iterator );
      68             : 
      69             :         /* declaration of list of options */
      70           0 :         uint32_t solutions_count = 0;
      71             :         static const uint32_t SOLUTIONS_MAX = 18;
      72             :         geometry_connector_t solution[18];
      73             : 
      74             :         /* propose options */
      75           0 :         pencil_relationship_2d_layouter_private_propose_solutions( this_,
      76             :                                                                    current_relationship,
      77             :                                                                    SOLUTIONS_MAX,
      78             :                                                                    solution,
      79             :                                                                    &solutions_count
      80             :                                                                  );
      81             : 
      82             :         /* select best option */
      83             :         uint32_t index_of_best;
      84           0 :         if ( 1 == solutions_count )
      85             :         {
      86           0 :             index_of_best = 0;
      87             :         }
      88             :         else
      89             :         {
      90           0 :             pencil_relationship_2d_layouter_private_select_solution( this_,
      91             :                                                                      current_relationship,
      92             :                                                                      solutions_count,
      93             :                                                                      solution,
      94             :                                                                      &index_of_best
      95             :                                                                    );
      96             :         }
      97             : 
      98             :         /* store best option to (*this_).layout_data */
      99           0 :         layout_relationship_set_shape( current_relationship, &(solution[index_of_best]) );
     100             : 
     101             :         /* initialize also the label (to empty), this is updated later */
     102             :         {
     103             :             geometry_rectangle_t void_rect;
     104           0 :             geometry_rectangle_init_empty( &void_rect );
     105           0 :             layout_relationship_set_label_box( current_relationship, &void_rect );
     106           0 :             geometry_rectangle_destroy( &void_rect );
     107             :         }
     108             : 
     109             :     }
     110           0 :     layout_relationship_iter_destroy( &relationship_iterator );
     111             : 
     112             :     /* clear the array and iterator of processed relationships */
     113           0 :     universal_array_index_sorter_reinit( &((*this_).sorted_relationships) );
     114           0 :     layout_relationship_iter_destroy( &((*this_).already_processed) );
     115           0 :     layout_relationship_iter_init( &((*this_).already_processed), (*this_).layout_data, &((*this_).sorted_relationships) );
     116             : 
     117           0 :     U8_TRACE_END();
     118           0 : }
     119             : 
     120           0 : void pencil_relationship_2d_layouter_private_propose_processing_order ( pencil_relationship_2d_layouter_t *this_ )
     121             : {
     122           0 :     U8_TRACE_BEGIN();
     123             :     assert ( (unsigned int) UNIVERSAL_ARRAY_INDEX_SORTER_MAX_ARRAY_SIZE >= (unsigned int) DATA_VISIBLE_SET_MAX_RELATIONSHIPS );
     124             : 
     125             :     /* get draw area */
     126             :     const layout_diagram_t *const diagram_layout
     127           0 :         = layout_visible_set_get_diagram_ptr( (*this_).layout_data );
     128             :     const geometry_rectangle_t *const diagram_draw_area
     129           0 :         = layout_diagram_get_draw_area_const( diagram_layout );
     130             : 
     131             :     /* sort the relationships by their shaping-needs: the less simple, the earlier it shall be processed */
     132             :     const uint32_t count_relations
     133           0 :         = layout_visible_set_get_relationship_count ( (*this_).layout_data );
     134           0 :     for ( uint32_t index = 0; index < count_relations; index ++ )
     135             :     {
     136             :         layout_relationship_t *const current_relation
     137           0 :             = layout_visible_set_get_relationship_ptr ( (*this_).layout_data, index );
     138             : 
     139           0 :         int64_t simpleness = 0;
     140             : 
     141             :         /* determine simpleness by relationship type */
     142             :         {
     143             :             data_relationship_type_t reltype;
     144           0 :             reltype = data_relationship_get_main_type( layout_relationship_get_data_const ( current_relation ));
     145           0 :             if (( DATA_RELATIONSHIP_TYPE_UML_DEPENDENCY == reltype )
     146           0 :                 ||( DATA_RELATIONSHIP_TYPE_UML_CONTAINMENT == reltype ))
     147             :             {
     148             :                 /* containment may be solved by embracing, mere dependencies are unimportant */
     149           0 :                 simpleness += geometry_rectangle_get_width ( diagram_draw_area );
     150             :             }
     151             :         }
     152             : 
     153             :         /* whatever is not visible is simple */
     154             :         {
     155           0 :             if (( PENCIL_VISIBILITY_SHOW != layout_relationship_get_visibility ( current_relation ) )
     156           0 :                 && ( PENCIL_VISIBILITY_GRAY_OUT != layout_relationship_get_visibility ( current_relation ) ))
     157             :             {
     158           0 :                 simpleness += 2 * geometry_rectangle_get_width ( diagram_draw_area );
     159             :             }
     160             :         }
     161             : 
     162             :         /* determine simpleness by distance between source and destination */
     163             :         {
     164             :             const geometry_rectangle_t *const source_rect
     165           0 :                 = layout_relationship_get_from_box_const ( current_relation );
     166             :             const geometry_rectangle_t *const dest_rect
     167           0 :                 = layout_relationship_get_to_box_const ( current_relation );
     168             : 
     169           0 :             simpleness -= fabs ( geometry_rectangle_get_center_x(source_rect) - geometry_rectangle_get_center_x(dest_rect) );
     170           0 :             simpleness -= fabs ( geometry_rectangle_get_center_y(source_rect) - geometry_rectangle_get_center_y(dest_rect) );
     171             :         }
     172             : 
     173             :         /* insert relation to sorted array, the simpler the more to the back */
     174             :         {
     175             :             int insert_error;
     176           0 :             insert_error = universal_array_index_sorter_insert( &((*this_).sorted_relationships), index, simpleness );
     177           0 :             if ( 0 != insert_error )
     178             :             {
     179           0 :                 U8_LOG_WARNING( "not all relationships are shaped" );
     180             :             }
     181             :         }
     182             :     }
     183             : 
     184           0 :     U8_TRACE_END();
     185           0 : }
     186             : 
     187           0 : void pencil_relationship_2d_layouter_private_propose_solutions ( pencil_relationship_2d_layouter_t *this_,
     188             :                                                                  const layout_relationship_t *current_relation,
     189             :                                                                  uint32_t solutions_max,
     190             :                                                                  geometry_connector_t out_solutions[],
     191             :                                                                  uint32_t *out_solutions_count )
     192             : {
     193           0 :     U8_TRACE_BEGIN();
     194           0 :     assert ( NULL != current_relation );
     195           0 :     assert ( NULL != out_solutions );
     196           0 :     assert ( NULL != out_solutions_count );
     197           0 :     assert ( 1 <= solutions_max );  /* general requirement to report at least one option */
     198           0 :     assert ( 18 <= solutions_max );  /* current implementation requires at least 18 options */
     199             : 
     200             :     /* propose connections between source and destination */
     201             :     {
     202             :         const geometry_rectangle_t *const source_rect
     203           0 :             = layout_relationship_get_from_box_const ( current_relation );
     204             :         const geometry_rectangle_t *const dest_rect
     205           0 :             = layout_relationship_get_to_box_const ( current_relation );
     206             : 
     207             :         uint32_t solutions_by_I;
     208           0 :         pencil_relationship_2d_layouter_private_connect_rectangles_by_I ( this_,
     209             :                                                                           source_rect,
     210             :                                                                           dest_rect,
     211             :                                                                           solutions_max,
     212             :                                                                           &(out_solutions[0]),
     213             :                                                                           &solutions_by_I
     214             :                                                                         );
     215             : 
     216             :         uint32_t solutions_by_ZN;
     217           0 :         pencil_relationship_2d_layouter_private_connect_rectangles_by_ZN ( this_,
     218             :                                                                            source_rect,
     219             :                                                                            dest_rect,
     220             :                                                                            solutions_max - solutions_by_I,
     221           0 :                                                                            &(out_solutions[solutions_by_I]),
     222             :                                                                            &solutions_by_ZN
     223             :                                                                          );
     224             : 
     225             :         uint32_t solutions_by_L7;
     226           0 :         const uint32_t solutions_by_I_ZN = solutions_by_I + solutions_by_ZN;
     227           0 :         pencil_relationship_2d_layouter_private_connect_rectangles_by_L7 ( this_,
     228             :                                                                            source_rect,
     229             :                                                                            dest_rect,
     230             :                                                                            solutions_max - solutions_by_I_ZN,
     231           0 :                                                                            &(out_solutions[solutions_by_I_ZN]),
     232             :                                                                            &solutions_by_L7
     233             :                                                                          );
     234             : 
     235             :         uint32_t solutions_by_UC;
     236           0 :         const uint32_t solutions_by_I_ZN_L7 = solutions_by_I_ZN + solutions_by_L7;
     237           0 :         pencil_relationship_2d_layouter_private_connect_rectangles_by_UC ( this_,
     238             :                                                                            source_rect,
     239             :                                                                            dest_rect,
     240             :                                                                            solutions_max - solutions_by_I_ZN_L7,
     241           0 :                                                                            &(out_solutions[solutions_by_I_ZN_L7]),
     242             :                                                                            &solutions_by_UC
     243             :                                                                          );
     244             : 
     245           0 :         *out_solutions_count = solutions_by_I_ZN_L7 + solutions_by_UC;
     246           0 :         assert ( 1 <= *out_solutions_count );
     247           0 :         assert ( *out_solutions_count <= solutions_max );
     248             :     }
     249             : 
     250           0 :     U8_TRACE_END();
     251           0 : }
     252             : 
     253           0 : void pencil_relationship_2d_layouter_private_select_solution ( pencil_relationship_2d_layouter_t *this_,
     254             :                                                                const layout_relationship_t *current_relation,
     255             :                                                                uint32_t solutions_count,
     256             :                                                                const geometry_connector_t solutions[],
     257             :                                                                uint32_t *out_index_of_best )
     258             : {
     259           0 :     U8_TRACE_BEGIN();
     260           0 :     assert ( NULL != current_relation );
     261           0 :     assert ( NULL != solutions );
     262           0 :     assert ( NULL != out_index_of_best );
     263           0 :     assert ( 1 <= solutions_count );
     264             : 
     265             :     /* get current relationship data */
     266             :     const geometry_rectangle_t *const source_rect
     267           0 :         = layout_relationship_get_from_box_const ( current_relation );
     268             :     const geometry_rectangle_t *const dest_rect
     269           0 :         = layout_relationship_get_to_box_const ( current_relation );
     270             : 
     271             :     /* get draw area */
     272             :     const layout_diagram_t *const diagram_layout
     273           0 :         = layout_visible_set_get_diagram_ptr( (*this_).layout_data );
     274             : 
     275             :     /* define potential solution and rating */
     276           0 :     uint32_t index_of_best = 0;
     277           0 :     double debts_of_best = DBL_MAX;
     278             : 
     279             :     /* evaluate the solutions by their overlaps with classifiers */
     280           0 :     for ( uint32_t solution_idx = 0; solution_idx < solutions_count; solution_idx ++ )
     281             :     {
     282           0 :         const geometry_connector_t *const current_solution = &(solutions[solution_idx]);
     283             : 
     284             :         /* avoid alternating solutions in case their debts are identical */
     285           0 :         double debts_of_current = 0.0;
     286           0 :         debts_of_current += 0.1 * solution_idx;
     287             : 
     288             :         /* evalute the debts of this solution */
     289           0 :         const layout_quality_t quality = layout_quality_new( (*this_).pencil_size );
     290           0 :         debts_of_current += layout_quality_debts_conn_diag( &quality, current_solution, source_rect, dest_rect, diagram_layout );
     291             : 
     292             :         /* iterate over all classifiers */
     293             :         const uint32_t count_clasfy
     294           0 :             = layout_visible_set_get_visible_classifier_count ( (*this_).layout_data );
     295           0 :         for ( uint32_t clasfy_index = 0; clasfy_index < count_clasfy; clasfy_index ++ )
     296             :         {
     297             :             const layout_visible_classifier_t *const probe_classifier
     298           0 :                 = layout_visible_set_get_visible_classifier_ptr( (*this_).layout_data, clasfy_index );
     299           0 :             const layout_visible_classifier_t *const from = layout_relationship_get_from_classifier_ptr( current_relation );
     300           0 :             const layout_visible_classifier_t *const to = layout_relationship_get_to_classifier_ptr( current_relation );
     301           0 :             const bool is_ancestor_of_from = layout_visible_set_is_ancestor( (*this_).layout_data, probe_classifier, from );
     302           0 :             const bool is_ancestor_of_to = layout_visible_set_is_ancestor( (*this_).layout_data, probe_classifier, to );
     303           0 :             debts_of_current += layout_quality_debts_conn_class( &quality,
     304             :                                                                  current_solution,
     305             :                                                                  probe_classifier,
     306             :                                                                  is_ancestor_of_from,
     307             :                                                                  is_ancestor_of_to
     308             :                                                                );
     309             :         }
     310             : 
     311             :         /* iterate over all features, check symbol boxes only, label boxes are not yet initialized */
     312             :         const uint32_t count_features
     313           0 :             = layout_visible_set_get_feature_count ( (*this_).layout_data );
     314           0 :         for ( uint32_t f_idx = 0; f_idx < count_features; f_idx ++ )
     315             :         {
     316             :             const layout_feature_t *const feature_layout
     317           0 :                 = layout_visible_set_get_feature_ptr ( (*this_).layout_data, f_idx );
     318             : 
     319             :             const geometry_rectangle_t *const feature_symbol_box
     320           0 :                 = layout_feature_get_symbol_box_const( feature_layout );
     321             : 
     322           0 :             debts_of_current += layout_quality_debts_conn_sym( &quality, current_solution, feature_symbol_box );
     323             :         }
     324             : 
     325             :         /* iterate over the already created connectors */
     326             :         layout_relationship_iter_t relationship_iterator;
     327           0 :         layout_relationship_iter_copy( &relationship_iterator, &((*this_).already_processed) );
     328           0 :         while ( layout_relationship_iter_has_next( &relationship_iterator ) )
     329             :         {
     330             :             /* get pointer to relationship */
     331           0 :             const layout_relationship_t *const probe_relationship = layout_relationship_iter_next_ptr( &relationship_iterator );
     332             : 
     333             :             /* add debts if intersects */
     334             : #if 0
     335             :             const data_relationship_t *const probe_relation_data
     336             :                 = layout_relationship_get_data_const ( probe_relationship );
     337             :             const bool same_type = ( data_relationship_get_main_type( probe_relation_data )
     338             :                                      == data_relationship_get_main_type( current_relation_data ) );
     339             :             const bool same_from = ( data_relationship_get_from_classifier_row_id( probe_relation_data )
     340             :                                      == data_relationship_get_from_classifier_row_id( current_relation_data ) );
     341             :             const bool same_to = ( data_relationship_get_to_classifier_row_id( probe_relation_data )
     342             :                                      == data_relationship_get_to_classifier_row_id( current_relation_data ) );
     343             :             const bool one_same_end = ( same_from != same_to );
     344             :             /* if probe and current have same type and (same source classifier xor same destination classifier), overlaps are ok */
     345             :             if ( ! ( same_type && one_same_end ) )
     346             : #endif
     347             :             {
     348             :                 const geometry_connector_t *const probe_shape
     349           0 :                     = layout_relationship_get_shape_const( probe_relationship );
     350             : 
     351           0 :                 debts_of_current += layout_quality_debts_conn_conn( &quality, current_solution, probe_shape );
     352             :                 /* U8_TRACE_INFO_INT_INT( "solution[idx] vs probe[idx]", solution_idx, probe_index ); */
     353             :             }
     354             :         }
     355           0 :         layout_relationship_iter_destroy( &relationship_iterator );
     356             : 
     357             :         /* update best solution */
     358           0 :         if ( debts_of_current < debts_of_best )
     359             :         {
     360           0 :             index_of_best = solution_idx;
     361           0 :             debts_of_best = debts_of_current;
     362             :         }
     363             :     }
     364             : 
     365             : #if 0
     366             :     static unsigned int counter = 0;
     367             :     counter ++;
     368             :     index_of_best = counter % solutions_count;
     369             : #endif
     370             : 
     371             :     /* the best */
     372           0 :     *out_index_of_best = index_of_best;
     373           0 :     geometry_connector_trace( &(solutions[index_of_best]) );
     374             : 
     375           0 :     U8_TRACE_END();
     376           0 : }
     377             : 
     378           0 : void pencil_relationship_2d_layouter_private_connect_rectangles_by_I ( pencil_relationship_2d_layouter_t *this_,
     379             :                                                                        const geometry_rectangle_t *source_rect,
     380             :                                                                        const geometry_rectangle_t *dest_rect,
     381             :                                                                        uint32_t solutions_max,
     382             :                                                                        geometry_connector_t out_solutions[],
     383             :                                                                        uint32_t *out_solutions_count )
     384             : {
     385           0 :     U8_TRACE_BEGIN();
     386           0 :     assert( NULL != source_rect );
     387           0 :     assert( NULL != dest_rect );
     388           0 :     assert ( NULL != out_solutions );
     389           0 :     assert ( NULL != out_solutions_count );
     390           0 :     assert ( 4 <= solutions_max );  /* current implementation requires at least 4 options */
     391             : 
     392           0 :     uint32_t solutions_count = 0;
     393             : 
     394           0 :     const double src_left = geometry_rectangle_get_left(source_rect);
     395           0 :     const double src_right = geometry_rectangle_get_right(source_rect);
     396           0 :     const double src_top = geometry_rectangle_get_top(source_rect);
     397           0 :     const double src_bottom = geometry_rectangle_get_bottom(source_rect);
     398             : 
     399           0 :     const double dst_left = geometry_rectangle_get_left(dest_rect);
     400           0 :     const double dst_right = geometry_rectangle_get_right(dest_rect);
     401           0 :     const double dst_top = geometry_rectangle_get_top(dest_rect);
     402           0 :     const double dst_bottom = geometry_rectangle_get_bottom(dest_rect);
     403             : 
     404           0 :     const double object_dist = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
     405           0 :     const double gap_dist = 0.499 * object_dist;  /* half the object distance allows a line to pass between two objects */
     406             : 
     407             :     /* if applicable, add a solution where line is vertical */
     408           0 :     if (( src_right >= dst_left )&&( src_left <= dst_right ))
     409             :     {
     410           0 :         const double min_left = fmax( src_left, dst_left );
     411           0 :         const double max_right = fmin( src_right, dst_right );
     412             : 
     413           0 :         if ( dst_bottom + object_dist < src_top )
     414             :         {
     415             :             /* define defaults */
     416           0 :             double x_value = ( min_left + max_right ) / 2.0;
     417             : 
     418             :             /* optimize coordinates */
     419             :             geometry_rectangle_t search_rect;
     420           0 :             geometry_rectangle_init_by_corners( &search_rect, min_left, dst_bottom, max_right, src_top );
     421           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &search_rect, gap_dist, &x_value );
     422           0 :             geometry_rectangle_destroy( &search_rect );
     423             : 
     424             :             /* add solution */
     425           0 :             geometry_connector_reinit_vertical ( &(out_solutions[solutions_count]),
     426             :                                                  x_value,
     427             :                                                  src_top,
     428             :                                                  x_value,
     429             :                                                  dst_bottom,
     430             :                                                  x_value
     431             :                                                );
     432           0 :             solutions_count ++;
     433             :         }
     434           0 :         else if ( dst_top - object_dist > src_bottom )
     435             :         {
     436             :             /* define defaults */
     437           0 :             double x_value = ( min_left + max_right ) / 2.0;
     438             : 
     439             :             /* optimize coordinates */
     440             :             geometry_rectangle_t search_rect;
     441           0 :             geometry_rectangle_init_by_corners( &search_rect, min_left, dst_top, max_right, src_bottom );
     442           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &search_rect, gap_dist, &x_value );
     443           0 :             geometry_rectangle_destroy( &search_rect );
     444             : 
     445             :             /* add solution */
     446           0 :             geometry_connector_reinit_vertical ( &(out_solutions[solutions_count]),
     447             :                                                  x_value,
     448             :                                                  src_bottom,
     449             :                                                  x_value,
     450             :                                                  dst_top,
     451             :                                                  x_value
     452             :                                                );
     453           0 :             solutions_count ++;
     454             :         }
     455             :         else
     456             :         {
     457           0 :             if ( fabs( src_top - dst_top ) > object_dist )
     458             :             {
     459             :                 /* define defaults */
     460           0 :                 double x_value = ( min_left + max_right ) / 2.0;
     461             : 
     462             :                 /* optimize coordinates */
     463             :                 geometry_rectangle_t search_rect;
     464           0 :                 geometry_rectangle_init_by_corners( &search_rect, min_left, dst_top, max_right, src_top );
     465           0 :                 pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &search_rect, gap_dist, &x_value );
     466           0 :                 geometry_rectangle_destroy( &search_rect );
     467             : 
     468             :                 /* add solution */
     469           0 :                 geometry_connector_reinit_vertical ( &(out_solutions[solutions_count]),
     470             :                                                     x_value,
     471             :                                                     src_top,
     472             :                                                     x_value,
     473             :                                                     dst_top,
     474             :                                                     x_value
     475             :                                                   );
     476           0 :                 solutions_count ++;
     477             :             }
     478             : 
     479           0 :             if ( fabs( src_bottom - dst_bottom ) > object_dist )
     480             :             {
     481             :                 /* define defaults */
     482           0 :                 double x_value = ( min_left + max_right ) / 2.0;
     483             : 
     484             :                 /* optimize coordinates */
     485             :                 geometry_rectangle_t search_rect;
     486           0 :                 geometry_rectangle_init_by_corners( &search_rect, min_left, src_bottom, max_right, dst_bottom );
     487           0 :                 pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &search_rect, gap_dist, &x_value );
     488           0 :                 geometry_rectangle_destroy( &search_rect );
     489             : 
     490             :                 /* add solution */
     491           0 :                 geometry_connector_reinit_vertical ( &(out_solutions[solutions_count]),
     492             :                                                     x_value,
     493             :                                                     src_bottom,
     494             :                                                     x_value,
     495             :                                                     dst_bottom,
     496             :                                                     x_value
     497             :                                                   );
     498           0 :                 solutions_count ++;
     499             :             }
     500             :         }
     501             :     }
     502             : 
     503             :     /* if applicable, add a solution where line is horizontal */
     504           0 :     if (( src_bottom >= dst_top )&&( src_top <= dst_bottom ))
     505             :     {
     506           0 :         const double min_top = fmax( src_top, dst_top );
     507           0 :         const double max_bottom = fmin( src_bottom, dst_bottom );
     508             : 
     509           0 :         if ( dst_right + object_dist < src_left )
     510             :         {
     511             :             /* define defaults */
     512           0 :             double y_value = ( min_top + max_bottom ) / 2.0;
     513             : 
     514             :             /* optimize coordinates */
     515             :             geometry_rectangle_t search_rect;
     516           0 :             geometry_rectangle_init_by_corners( &search_rect, dst_right, min_top, src_left, max_bottom );
     517           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &search_rect, gap_dist, &y_value );
     518           0 :             geometry_rectangle_destroy( &search_rect );
     519             : 
     520             :             /* add solution */
     521           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
     522             :                                                    src_left,
     523             :                                                    y_value,
     524             :                                                    dst_right,
     525             :                                                    y_value,
     526             :                                                    y_value
     527             :                                                  );
     528           0 :             solutions_count ++;
     529             :         }
     530           0 :         else if ( dst_left - object_dist > src_right )
     531             :         {
     532             :             /* define defaults */
     533           0 :             double y_value = ( min_top + max_bottom ) / 2.0;
     534             : 
     535             :             /* optimize coordinates */
     536             :             geometry_rectangle_t search_rect;
     537           0 :             geometry_rectangle_init_by_corners( &search_rect, dst_left, min_top, src_right, max_bottom );
     538           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &search_rect, gap_dist, &y_value );
     539           0 :             geometry_rectangle_destroy( &search_rect );
     540             : 
     541             :             /* add solution */
     542           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
     543             :                                                    src_right,
     544             :                                                    y_value,
     545             :                                                    dst_left,
     546             :                                                    y_value,
     547             :                                                    y_value
     548             :                                                  );
     549           0 :             solutions_count ++;
     550             :         }
     551             :         else
     552             :         {
     553           0 :             if ( fabs( src_left - dst_left ) > object_dist )
     554             :             {
     555             :                 /* define defaults */
     556           0 :                 double y_value = ( min_top + max_bottom ) / 2.0;
     557             : 
     558             :                 /* optimize coordinates */
     559             :                 geometry_rectangle_t search_rect;
     560           0 :                 geometry_rectangle_init_by_corners( &search_rect, src_left, min_top, dst_left, max_bottom );
     561           0 :                 pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &search_rect, gap_dist, &y_value );
     562           0 :                 geometry_rectangle_destroy( &search_rect );
     563             : 
     564             :                 /* add solution */
     565           0 :                 geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
     566             :                                                        src_left,
     567             :                                                        y_value,
     568             :                                                        dst_left,
     569             :                                                        y_value,
     570             :                                                        y_value
     571             :                                                      );
     572           0 :                 solutions_count ++;
     573             :             }
     574             : 
     575           0 :             if ( fabs( src_right - dst_right ) > object_dist )
     576             :             {
     577             :                 /* define defaults */
     578           0 :                 double y_value = ( min_top + max_bottom ) / 2.0;
     579             : 
     580             :                 /* optimize coordinates */
     581             :                 geometry_rectangle_t search_rect;
     582           0 :                 geometry_rectangle_init_by_corners( &search_rect, src_right, min_top, dst_right, max_bottom );
     583           0 :                 pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &search_rect, gap_dist, &y_value );
     584           0 :                 geometry_rectangle_destroy( &search_rect );
     585             : 
     586             :                 /* add solution */
     587           0 :                 geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
     588             :                                                        src_right,
     589             :                                                        y_value,
     590             :                                                        dst_right,
     591             :                                                        y_value,
     592             :                                                        y_value
     593             :                                                      );
     594           0 :                 solutions_count ++;
     595             :             }
     596             :         }
     597             :     }
     598             : 
     599           0 :     *out_solutions_count = solutions_count;
     600             : 
     601           0 :     U8_TRACE_END();
     602           0 : }
     603             : 
     604           0 : void pencil_relationship_2d_layouter_private_connect_rectangles_by_ZN ( pencil_relationship_2d_layouter_t *this_,
     605             :                                                                         const geometry_rectangle_t *source_rect,
     606             :                                                                         const geometry_rectangle_t *dest_rect,
     607             :                                                                         uint32_t solutions_max,
     608             :                                                                         geometry_connector_t out_solutions[],
     609             :                                                                         uint32_t *out_solutions_count )
     610             : {
     611           0 :     U8_TRACE_BEGIN();
     612           0 :     assert( NULL != source_rect );
     613           0 :     assert( NULL != dest_rect );
     614           0 :     assert ( NULL != out_solutions );
     615           0 :     assert ( NULL != out_solutions_count );
     616           0 :     assert ( 2 <= solutions_max );  /* current implementation requires at least 2 options */
     617             : 
     618           0 :     uint32_t solutions_count = 0;
     619             : 
     620           0 :     const double src_left = geometry_rectangle_get_left(source_rect);
     621           0 :     const double src_center_x = geometry_rectangle_get_center_x(source_rect);
     622           0 :     const double src_right = geometry_rectangle_get_right(source_rect);
     623           0 :     const double src_top = geometry_rectangle_get_top(source_rect);
     624           0 :     const double src_center_y = geometry_rectangle_get_center_y(source_rect);
     625           0 :     const double src_bottom = geometry_rectangle_get_bottom(source_rect);
     626           0 :     const double src_width = geometry_rectangle_get_width(source_rect);
     627           0 :     const double src_height = geometry_rectangle_get_height(source_rect);
     628             : 
     629           0 :     const double dst_left = geometry_rectangle_get_left(dest_rect);
     630           0 :     const double dst_center_x = geometry_rectangle_get_center_x(dest_rect);
     631           0 :     const double dst_right = geometry_rectangle_get_right(dest_rect);
     632           0 :     const double dst_top = geometry_rectangle_get_top(dest_rect);
     633           0 :     const double dst_center_y = geometry_rectangle_get_center_y(dest_rect);
     634           0 :     const double dst_bottom = geometry_rectangle_get_bottom(dest_rect);
     635           0 :     const double dst_width = geometry_rectangle_get_width(dest_rect);
     636           0 :     const double dst_height = geometry_rectangle_get_height(dest_rect);
     637             : 
     638           0 :     const double object_dist = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
     639           0 :     const double good_dist = 2.0 * object_dist;  /* duplicate distance: once for each side of the line */
     640           0 :     const double gap_dist = 0.499 * object_dist;  /* half the object distance allows a line to pass between two objects */
     641             : 
     642             :     /* if applicable, add a solution where main line is vertical */
     643             :     {
     644           0 :         if ( dst_right + good_dist < src_left )
     645             :         {
     646             :             /* define defaults */
     647           0 :             double x_value = ( src_left + dst_right ) / 2.0;
     648           0 :             double src_y = src_center_y;
     649           0 :             double dst_y = dst_center_y;
     650             : 
     651             :             /* optimize coordinates */
     652             :             geometry_rectangle_t search_rect;
     653           0 :             geometry_rectangle_init_by_corners( &search_rect, src_left, src_y, dst_right, dst_y );
     654           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &search_rect, gap_dist, &x_value );
     655           0 :             geometry_rectangle_destroy( &search_rect );
     656             : 
     657           0 :             const geometry_rectangle_t depart_area
     658           0 :                 = { .left=x_value, .top=src_top, .width=(src_left-x_value), .height=src_height};
     659           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &depart_area, gap_dist, &src_y );
     660             : 
     661           0 :             const geometry_rectangle_t arrive_area
     662           0 :                 = { .left=dst_right, .top=dst_top, .width=(x_value-dst_right), .height=dst_height};
     663           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &arrive_area, gap_dist, &dst_y );
     664             : 
     665             :             /* add solution */
     666           0 :             geometry_connector_reinit_vertical ( &(out_solutions[solutions_count]),
     667             :                                                  src_left,
     668             :                                                  src_y,
     669             :                                                  dst_right,
     670             :                                                  dst_y,
     671             :                                                  x_value
     672             :                                                );
     673           0 :             solutions_count ++;
     674             :         }
     675           0 :         else if ( dst_left - good_dist > src_right )
     676             :         {
     677             :             /* define defaults */
     678           0 :             double x_value = ( src_right + dst_left ) / 2.0;
     679           0 :             double src_y = src_center_y;
     680           0 :             double dst_y = dst_center_y;
     681             : 
     682             :             /* optimize coordinates */
     683             :             geometry_rectangle_t search_rect;
     684           0 :             geometry_rectangle_init_by_corners( &search_rect, src_right, src_y, dst_left, dst_y );
     685           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &search_rect, gap_dist, &x_value );
     686           0 :             geometry_rectangle_destroy( &search_rect );
     687             : 
     688           0 :             const geometry_rectangle_t depart_area
     689           0 :                 = { .left=src_right, .top=src_top, .width=(x_value-src_right), .height=src_height};
     690           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &depart_area, gap_dist, &src_y );
     691             : 
     692           0 :             const geometry_rectangle_t arrive_area
     693           0 :                 = { .left=x_value, .top=dst_top, .width=(dst_left-x_value), .height=dst_height};
     694           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &arrive_area, gap_dist, &dst_y );
     695             : 
     696             :             /* add solution */
     697           0 :             geometry_connector_reinit_vertical ( &(out_solutions[solutions_count]),
     698             :                                                  src_right,
     699             :                                                  src_y,
     700             :                                                  dst_left,
     701             :                                                  dst_y,
     702             :                                                  x_value
     703             :                                                );
     704           0 :             solutions_count ++;
     705             :         }
     706             :     }
     707             : 
     708             :     /* if applicable, add a solution where main line is horizontal */
     709             :     {
     710           0 :         if ( dst_bottom + good_dist < src_top )
     711             :         {
     712             :             /* define defaults */
     713           0 :             double y_value = ( src_top + dst_bottom ) / 2.0;
     714           0 :             double src_x = src_center_x;
     715           0 :             double dst_x = dst_center_x;
     716             : 
     717             :             /* optimize coordinates */
     718             :             geometry_rectangle_t search_rect;
     719           0 :             geometry_rectangle_init_by_corners( &search_rect, src_x, src_top, dst_x, dst_bottom );
     720           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &search_rect, gap_dist, &y_value );
     721           0 :             geometry_rectangle_destroy( &search_rect );
     722             : 
     723           0 :             const geometry_rectangle_t depart_area
     724           0 :                 = { .left=src_left, .top=y_value, .width=src_width, .height=(src_top-y_value)};
     725           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &depart_area, gap_dist, &src_x );
     726             : 
     727           0 :             const geometry_rectangle_t arrive_area
     728           0 :                 = { .left=dst_left, .top=dst_bottom, .width=dst_width, .height=(y_value-dst_bottom)};
     729           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &arrive_area, gap_dist, &dst_x );
     730             : 
     731             :             /* add solution */
     732           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
     733             :                                                    src_x,
     734             :                                                    src_top,
     735             :                                                    dst_x,
     736             :                                                    dst_bottom,
     737             :                                                    y_value
     738             :                                                  );
     739           0 :             solutions_count ++;
     740             :         }
     741           0 :         else if ( dst_top - good_dist > src_bottom )
     742             :         {
     743             :             /* define defaults */
     744           0 :             double y_value = ( src_bottom + dst_top ) / 2.0;
     745           0 :             double src_x = src_center_x;
     746           0 :             double dst_x = dst_center_x;
     747             : 
     748             :             /* optimize coordinates */
     749             :             geometry_rectangle_t search_rect;
     750           0 :             geometry_rectangle_init_by_corners( &search_rect, src_x, src_bottom, dst_x, dst_top );
     751           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &search_rect, gap_dist, &y_value );
     752           0 :             geometry_rectangle_destroy( &search_rect );
     753             : 
     754           0 :             const geometry_rectangle_t depart_area
     755           0 :                 = { .left=src_left, .top=src_bottom, .width=src_width, .height=(y_value-src_bottom)};
     756           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &depart_area, gap_dist, &src_x );
     757             : 
     758           0 :             const geometry_rectangle_t arrive_area
     759           0 :                 = { .left=dst_left, .top=y_value, .width=dst_width, .height=(dst_top-y_value)};
     760           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &arrive_area, gap_dist, &dst_x );
     761             : 
     762             :             /* add solution */
     763           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
     764             :                                                    src_x,
     765             :                                                    src_bottom,
     766             :                                                    dst_x,
     767             :                                                    dst_top,
     768             :                                                    y_value
     769             :                                                  );
     770           0 :             solutions_count ++;
     771             :         }
     772             :     }
     773             : 
     774           0 :     *out_solutions_count = solutions_count;
     775             : 
     776           0 :     U8_TRACE_END();
     777           0 : }
     778             : 
     779           0 : void pencil_relationship_2d_layouter_private_connect_rectangles_by_UC ( pencil_relationship_2d_layouter_t *this_,
     780             :                                                                         const geometry_rectangle_t *source_rect,
     781             :                                                                         const geometry_rectangle_t *dest_rect,
     782             :                                                                         uint32_t solutions_max,
     783             :                                                                         geometry_connector_t out_solutions[],
     784             :                                                                         uint32_t *out_solutions_count )
     785             : {
     786           0 :     U8_TRACE_BEGIN();
     787           0 :     assert( NULL != source_rect );
     788           0 :     assert( NULL != dest_rect );
     789           0 :     assert ( NULL != out_solutions );
     790           0 :     assert ( NULL != out_solutions_count );
     791           0 :     assert ( 4 <= solutions_max );  /* current implementation calculates exactly 4 options */
     792             : 
     793           0 :     uint32_t solutions_count = 0;
     794             : 
     795             :     /* get draw area */
     796             :     const layout_diagram_t *const diagram_layout
     797           0 :         = layout_visible_set_get_diagram_ptr( (*this_).layout_data );
     798             :     const geometry_rectangle_t *const diagram_draw_area
     799           0 :         = layout_diagram_get_draw_area_const( diagram_layout );
     800           0 :     const double draw_left = geometry_rectangle_get_left( diagram_draw_area );
     801           0 :     const double draw_right = geometry_rectangle_get_right( diagram_draw_area );
     802           0 :     const double draw_top = geometry_rectangle_get_top( diagram_draw_area );
     803           0 :     const double draw_bottom = geometry_rectangle_get_bottom( diagram_draw_area );
     804             : 
     805           0 :     const double src_left = geometry_rectangle_get_left(source_rect);
     806           0 :     const double src_center_x = geometry_rectangle_get_center_x(source_rect);
     807           0 :     const double src_right = geometry_rectangle_get_right(source_rect);
     808           0 :     const double src_top = geometry_rectangle_get_top(source_rect);
     809           0 :     const double src_center_y = geometry_rectangle_get_center_y(source_rect);
     810           0 :     const double src_bottom = geometry_rectangle_get_bottom(source_rect);
     811           0 :     const double src_width = geometry_rectangle_get_width(source_rect);
     812           0 :     const double src_height = geometry_rectangle_get_height(source_rect);
     813             : 
     814           0 :     const double dst_left = geometry_rectangle_get_left(dest_rect);
     815           0 :     const double dst_center_x = geometry_rectangle_get_center_x(dest_rect);
     816           0 :     const double dst_right = geometry_rectangle_get_right(dest_rect);
     817           0 :     const double dst_top = geometry_rectangle_get_top(dest_rect);
     818           0 :     const double dst_center_y = geometry_rectangle_get_center_y(dest_rect);
     819           0 :     const double dst_bottom = geometry_rectangle_get_bottom(dest_rect);
     820           0 :     const double dst_width = geometry_rectangle_get_width(dest_rect);
     821           0 :     const double dst_height = geometry_rectangle_get_height(dest_rect);
     822             : 
     823           0 :     const double object_dist = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
     824           0 :     const double gap_dist = 0.499 * object_dist;  /* half the object distance allows a line to pass between two objects */
     825             :     static const double NO_TOUCH = 0.0001;
     826             : 
     827             :     /* connect via left side */
     828             :     {
     829             :         /* define defaults */
     830           0 :         double x_value = fmin( src_left, dst_left ) - object_dist;
     831           0 :         double src_y = src_center_y;
     832           0 :         double dst_y = dst_center_y;
     833           0 :         if ( fabs( src_center_y - dst_center_y ) < NO_TOUCH )
     834             :         {
     835             :             /* forward way is identical to retour - may be a relation to self */
     836           0 :             src_y = fmin( src_center_y + gap_dist, src_bottom );
     837           0 :             dst_y = fmax( dst_center_y - gap_dist, dst_top );
     838             :         }
     839             : 
     840             :         /* optimize coordinates */
     841             :         geometry_rectangle_t search_rect;
     842           0 :         geometry_rectangle_init_by_corners( &search_rect, draw_left, src_y, x_value, dst_y );
     843           0 :         pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &search_rect, gap_dist, &x_value );
     844           0 :         geometry_rectangle_destroy( &search_rect );
     845             : 
     846           0 :         const geometry_rectangle_t depart_area
     847           0 :             = { .left=x_value, .top=src_top, .width=(src_left-x_value), .height=src_height};
     848           0 :         pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &depart_area, gap_dist, &src_y );
     849             : 
     850           0 :         const geometry_rectangle_t arrive_area
     851           0 :             = { .left=x_value, .top=dst_top, .width=(dst_left-x_value), .height=dst_height};
     852           0 :         pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &arrive_area, gap_dist, &dst_y );
     853             : 
     854             :         /* add solution */
     855           0 :         geometry_connector_reinit_vertical( &(out_solutions[solutions_count]),
     856             :                                             src_left,
     857             :                                             src_y,
     858             :                                             dst_left,
     859             :                                             dst_y,
     860             :                                             x_value
     861             :                                           );
     862           0 :         solutions_count ++;
     863             :     }
     864             : 
     865             :     /* connect via right side */
     866             :     {
     867             :         /* define defaults */
     868           0 :         double x_value = fmax( src_right, dst_right ) + object_dist;
     869           0 :         double src_y = src_center_y;
     870           0 :         double dst_y = dst_center_y;
     871           0 :         if ( fabs( src_center_y - dst_center_y ) < NO_TOUCH )
     872             :         {
     873             :             /* forward way is identical to retour - may be a relation to self */
     874           0 :             src_y = fmin( src_center_y + gap_dist, src_bottom );
     875           0 :             dst_y = fmax( dst_center_y - gap_dist, dst_top );
     876             :         }
     877             : 
     878             :         /* optimize coordinates */
     879             :         geometry_rectangle_t search_rect;
     880           0 :         geometry_rectangle_init_by_corners( &search_rect, x_value, src_y, draw_right, dst_y );
     881           0 :         pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &search_rect, gap_dist, &x_value );
     882           0 :         geometry_rectangle_destroy( &search_rect );
     883             : 
     884           0 :         const geometry_rectangle_t depart_area
     885           0 :             = { .left=src_right, .top=src_top, .width=(x_value-src_right), .height=src_height};
     886           0 :         pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &depart_area, gap_dist, &src_y );
     887             : 
     888           0 :         const geometry_rectangle_t arrive_area
     889           0 :             = { .left=dst_right, .top=dst_top, .width=(x_value-dst_right), .height=dst_height};
     890           0 :         pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &arrive_area, gap_dist, &dst_y );
     891             : 
     892             :         /* add solution */
     893           0 :         geometry_connector_reinit_vertical( &(out_solutions[solutions_count]),
     894             :                                             src_right,
     895             :                                             src_y,
     896             :                                             dst_right,
     897             :                                             dst_y,
     898             :                                             x_value
     899             :                                           );
     900           0 :         solutions_count ++;
     901             :     }
     902             : 
     903             :     /* connect via top side */
     904             :     {
     905             :         /* define defaults */
     906           0 :         double y_value = fmin( src_top, dst_top ) - object_dist;
     907           0 :         double src_x = src_center_x;
     908           0 :         double dst_x = dst_center_x;
     909           0 :         if ( fabs( src_center_x - dst_center_x ) < NO_TOUCH )
     910             :         {
     911             :             /* forward way is identical to retour - may be a relation to self */
     912           0 :             src_x = fmax( src_center_x - gap_dist, src_left );
     913           0 :             dst_x = fmin( dst_center_x + gap_dist, dst_right );
     914             :         }
     915             : 
     916             :         /* optimize coordinates */
     917             :         geometry_rectangle_t search_rect;
     918           0 :         geometry_rectangle_init_by_corners( &search_rect, src_x, draw_top, dst_x, y_value );
     919           0 :         pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &search_rect, gap_dist, &y_value );
     920           0 :         geometry_rectangle_destroy( &search_rect );
     921             : 
     922           0 :         const geometry_rectangle_t depart_area
     923           0 :             = { .left=src_left, .top=y_value, .width=src_width, .height=(src_top-y_value)};
     924           0 :         pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &depart_area, gap_dist, &src_x );
     925             : 
     926           0 :         const geometry_rectangle_t arrive_area
     927           0 :             = { .left=dst_left, .top=y_value, .width=dst_width, .height=(dst_top-y_value)};
     928           0 :         pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &arrive_area, gap_dist, &dst_x );
     929             : 
     930             :         /* add solution */
     931           0 :         geometry_connector_reinit_horizontal( &(out_solutions[solutions_count]),
     932             :                                               src_x,
     933             :                                               src_top,
     934             :                                               dst_x,
     935             :                                               dst_top,
     936             :                                               y_value
     937             :                                             );
     938           0 :         solutions_count ++;
     939             :     }
     940             : 
     941             :     /* connect via bottom side */
     942             :     {
     943             :         /* define defaults */
     944           0 :         double y_value = fmax( src_bottom, dst_bottom ) + object_dist;
     945           0 :         double src_x = src_center_x;
     946           0 :         double dst_x = dst_center_x;
     947           0 :         if ( fabs( src_center_x - dst_center_x ) < NO_TOUCH )
     948             :         {
     949             :             /* forward way is identical to retour - may be a relation to self */
     950           0 :             src_x = fmax( src_center_x - gap_dist, src_left );
     951           0 :             dst_x = fmin( dst_center_x + gap_dist, dst_right );
     952             :         }
     953             : 
     954             :         /* optimize coordinates */
     955             :         geometry_rectangle_t search_rect;
     956           0 :         geometry_rectangle_init_by_corners( &search_rect, src_x, y_value, dst_x, draw_bottom );
     957           0 :         pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &search_rect, gap_dist, &y_value );
     958           0 :         geometry_rectangle_destroy( &search_rect );
     959             : 
     960           0 :         const geometry_rectangle_t depart_area
     961           0 :             = { .left=src_left, .top=src_bottom, .width=src_width, .height=(y_value-src_bottom)};
     962           0 :         pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &depart_area, gap_dist, &src_x );
     963             : 
     964           0 :         const geometry_rectangle_t arrive_area
     965           0 :             = { .left=dst_left, .top=dst_bottom, .width=dst_width, .height=(y_value-dst_bottom)};
     966           0 :         pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &arrive_area, gap_dist, &dst_x );
     967             : 
     968             :         /* add solution */
     969           0 :         geometry_connector_reinit_horizontal( &(out_solutions[solutions_count]),
     970             :                                               src_x,
     971             :                                               src_bottom,
     972             :                                               dst_x,
     973             :                                               dst_bottom,
     974             :                                               y_value
     975             :                                             );
     976           0 :         solutions_count ++;
     977             :     }
     978             : 
     979           0 :     *out_solutions_count = solutions_count;
     980             : 
     981           0 :     U8_TRACE_END();
     982           0 : }
     983             : 
     984           0 : void pencil_relationship_2d_layouter_private_connect_rectangles_by_L7 ( pencil_relationship_2d_layouter_t *this_,
     985             :                                                                         const geometry_rectangle_t *source_rect,
     986             :                                                                         const geometry_rectangle_t *dest_rect,
     987             :                                                                         uint32_t solutions_max,
     988             :                                                                         geometry_connector_t out_solutions[],
     989             :                                                                         uint32_t *out_solutions_count )
     990             : {
     991           0 :     U8_TRACE_BEGIN();
     992           0 :     assert( NULL != source_rect );
     993           0 :     assert( NULL != dest_rect );
     994           0 :     assert ( NULL != out_solutions );
     995           0 :     assert ( NULL != out_solutions_count );
     996           0 :     assert ( 8 <= solutions_max );  /* current implementation requires at least 2 options */
     997             : 
     998           0 :     uint32_t solutions_count = 0;
     999             : 
    1000           0 :     const double src_left = geometry_rectangle_get_left(source_rect);
    1001           0 :     const double src_right = geometry_rectangle_get_right(source_rect);
    1002           0 :     const double src_top = geometry_rectangle_get_top(source_rect);
    1003           0 :     const double src_bottom = geometry_rectangle_get_bottom(source_rect);
    1004             : 
    1005           0 :     const double dst_left = geometry_rectangle_get_left(dest_rect);
    1006           0 :     const double dst_right = geometry_rectangle_get_right(dest_rect);
    1007           0 :     const double dst_top = geometry_rectangle_get_top(dest_rect);
    1008           0 :     const double dst_bottom = geometry_rectangle_get_bottom(dest_rect);
    1009             : 
    1010           0 :     const double object_dist = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
    1011           0 :     const double gap_dist = 0.499 * object_dist;  /* half the object distance allows a line to pass between two objects */
    1012             : 
    1013             :     /* pre-calculate some intermediate values on source rect */
    1014           0 :     const bool src_left_to_outside = dst_left < src_left;  /* connector starts towards outside of source rect */
    1015           0 :     const bool src_right_to_outside = dst_right > src_right;  /* connector starts towards outside of source rect */
    1016           0 :     const bool src_top_to_outside = src_top > dst_top;  /* connector arrives from outside at dest rect */
    1017           0 :     const bool src_bottom_to_outside = src_bottom < dst_bottom;  /* connector arrives from outside at dest rect */
    1018             :     /* pre-calculate some intermediate values on destination rect */
    1019           0 :     const bool dst_left_from_outside = src_left < dst_left;  /* connector starts towards outside of source rect */
    1020           0 :     const bool dst_right_from_outside = src_right > dst_right;  /* connector starts towards outside of source rect */
    1021           0 :     const bool dst_top_from_outside = dst_top > src_top;  /* connector arrives from outside at dest rect */
    1022           0 :     const bool dst_bottom_from_outside = dst_bottom < src_bottom;  /* connector arrives from outside at dest rect */
    1023             : 
    1024             :     /* add two solutions from source-left */
    1025             :     {
    1026           0 :         const double search_left = dst_left;
    1027           0 :         const double search_right = src_left_to_outside ? fmin( src_left, dst_right ) : dst_right;
    1028             :         /* add a solution from source-left to destination-bottom */
    1029             :         {
    1030           0 :             const double search_top = dst_bottom_from_outside ? fmax( src_top, dst_bottom ) : src_top;
    1031           0 :             const double search_bottom = src_bottom;
    1032             : 
    1033             :             /* define defaults */
    1034           0 :             double dst_x = ( search_left + search_right ) / 2.0;
    1035           0 :             double src_y = ( search_top + search_bottom ) / 2.0;
    1036             : 
    1037             :             /* optimize coordinates */
    1038             :             geometry_rectangle_t depart_area;
    1039           0 :             geometry_rectangle_init_by_corners( &depart_area, dst_x, src_top, src_left, src_bottom );
    1040           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &depart_area, gap_dist, &src_y );
    1041           0 :             geometry_rectangle_destroy( &depart_area );
    1042             : 
    1043             :             geometry_rectangle_t arrive_area;
    1044           0 :             geometry_rectangle_init_by_corners( &arrive_area, dst_left, src_y, dst_right, dst_bottom );
    1045           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &arrive_area, gap_dist, &dst_x );
    1046           0 :             geometry_rectangle_destroy( &arrive_area );
    1047             : 
    1048             :             /* add solution */
    1049           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
    1050             :                                                    src_left,
    1051             :                                                    src_y,
    1052             :                                                    dst_x,
    1053             :                                                    dst_bottom,
    1054             :                                                    src_y
    1055             :                                                  );
    1056           0 :             solutions_count ++;
    1057             :         }
    1058             :         /* add a solution from source-left to destination-top */
    1059             :         {
    1060           0 :             const double search_top = src_top;
    1061           0 :             const double search_bottom = dst_top_from_outside ? fmin( src_bottom, dst_top ) : src_bottom;
    1062             : 
    1063             :             /* define defaults */
    1064           0 :             double dst_x = ( search_left + search_right ) / 2.0;
    1065           0 :             double src_y = ( search_top + search_bottom ) / 2.0;
    1066             : 
    1067             :             /* optimize coordinates */
    1068             :             geometry_rectangle_t depart_area;
    1069           0 :             geometry_rectangle_init_by_corners( &depart_area, dst_x, src_top, src_left, src_bottom );
    1070           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &depart_area, gap_dist, &src_y );
    1071           0 :             geometry_rectangle_destroy( &depart_area );
    1072             : 
    1073             :             geometry_rectangle_t arrive_area;
    1074           0 :             geometry_rectangle_init_by_corners( &arrive_area, dst_left, src_y, dst_right, dst_top );
    1075           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &arrive_area, gap_dist, &dst_x );
    1076           0 :             geometry_rectangle_destroy( &arrive_area );
    1077             : 
    1078             :             /* add solution */
    1079           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
    1080             :                                                    src_left,
    1081             :                                                    src_y,
    1082             :                                                    dst_x,
    1083             :                                                    dst_top,
    1084             :                                                    src_y
    1085             :                                                  );
    1086           0 :             solutions_count ++;
    1087             :         }
    1088             :     }
    1089             : 
    1090             :     /* add two solutions from source-right */
    1091             :     {
    1092           0 :         const double search_left = src_right_to_outside ? fmax( src_right, dst_left ) : dst_left;
    1093           0 :         const double search_right = dst_right;
    1094             :         /* add a solution from source-right to destination-bottom */
    1095             :         {
    1096           0 :             const double search_top = dst_bottom_from_outside ? fmax( src_top, dst_bottom ) : src_top;
    1097           0 :             const double search_bottom = src_bottom;
    1098             : 
    1099             :             /* define defaults */
    1100           0 :             double dst_x = ( search_left + search_right ) / 2.0;
    1101           0 :             double src_y = ( search_top + search_bottom ) / 2.0;
    1102             : 
    1103             :             /* optimize coordinates */
    1104             :             geometry_rectangle_t depart_area;
    1105           0 :             geometry_rectangle_init_by_corners( &depart_area, dst_x, src_top, src_right, src_bottom );
    1106           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &depart_area, gap_dist, &src_y );
    1107           0 :             geometry_rectangle_destroy( &depart_area );
    1108             : 
    1109             :             geometry_rectangle_t arrive_area;
    1110           0 :             geometry_rectangle_init_by_corners( &arrive_area, dst_left, src_y, dst_right, dst_bottom );
    1111           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &arrive_area, gap_dist, &dst_x );
    1112           0 :             geometry_rectangle_destroy( &arrive_area );
    1113             : 
    1114             :             /* add solution */
    1115           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
    1116             :                                                    src_right,
    1117             :                                                    src_y,
    1118             :                                                    dst_x,
    1119             :                                                    dst_bottom,
    1120             :                                                    src_y
    1121             :                                                  );
    1122           0 :             solutions_count ++;
    1123             :         }
    1124             :         /* add a solution from source-right to destination-top */
    1125             :         {
    1126           0 :             const double search_top = src_top;
    1127           0 :             const double search_bottom = dst_top_from_outside ? fmin( src_bottom, dst_top ) : src_bottom;
    1128             : 
    1129             :             /* define defaults */
    1130           0 :             double dst_x = ( search_left + search_right ) / 2.0;
    1131           0 :             double src_y = ( search_top + search_bottom ) / 2.0;
    1132             : 
    1133             :             /* optimize coordinates */
    1134             :             geometry_rectangle_t depart_area;
    1135           0 :             geometry_rectangle_init_by_corners( &depart_area, dst_x, src_top, src_right, src_bottom );
    1136           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &depart_area, gap_dist, &src_y );
    1137           0 :             geometry_rectangle_destroy( &depart_area );
    1138             : 
    1139             :             geometry_rectangle_t arrive_area;
    1140           0 :             geometry_rectangle_init_by_corners( &arrive_area, dst_left, src_y, dst_right, dst_top );
    1141           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &arrive_area, gap_dist, &dst_x );
    1142           0 :             geometry_rectangle_destroy( &arrive_area );
    1143             : 
    1144             :             /* add solution */
    1145           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
    1146             :                                                    src_right,
    1147             :                                                    src_y,
    1148             :                                                    dst_x,
    1149             :                                                    dst_top,
    1150             :                                                    src_y
    1151             :                                                  );
    1152           0 :             solutions_count ++;
    1153             :         }
    1154             :     }
    1155             : 
    1156             :     /* add two solutions from source-top */
    1157             :     {
    1158           0 :         const double search_top = dst_top;
    1159           0 :         const double search_bottom = src_top_to_outside ? fmin( src_top, dst_bottom ) : dst_bottom;
    1160             :         /* add a solution from source-top to destination-right */
    1161             :         {
    1162           0 :             const double search_left = dst_right_from_outside ? fmax( dst_right, src_left ) : src_left;
    1163           0 :             const double search_right = src_right;
    1164             : 
    1165             :             /* define defaults */
    1166           0 :             double src_x = ( search_left + search_right ) / 2.0;
    1167           0 :             double dst_y = ( search_top + search_bottom ) / 2.0;
    1168             : 
    1169             :             /* optimize coordinates */
    1170             :             geometry_rectangle_t depart_area;
    1171           0 :             geometry_rectangle_init_by_corners( &depart_area, src_left, src_top, src_right, dst_y );
    1172           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &depart_area, gap_dist, &src_x );
    1173           0 :             geometry_rectangle_destroy( &depart_area );
    1174             : 
    1175             :             geometry_rectangle_t arrive_area;
    1176           0 :             geometry_rectangle_init_by_corners( &arrive_area, src_x, dst_top, dst_right, dst_bottom );
    1177           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &arrive_area, gap_dist, &dst_y );
    1178           0 :             geometry_rectangle_destroy( &arrive_area );
    1179             : 
    1180             :             /* add solution */
    1181           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
    1182             :                                                    src_x,
    1183             :                                                    src_top,
    1184             :                                                    dst_right,
    1185             :                                                    dst_y,
    1186             :                                                    dst_y
    1187             :                                                  );
    1188           0 :             solutions_count ++;
    1189             :         }
    1190             :         /* add a solution from source-top to destination-left */
    1191             :         {
    1192           0 :             const double search_left = src_left;
    1193           0 :             const double search_right = dst_left_from_outside ? fmin( dst_left, src_right ) : src_right;
    1194             : 
    1195             :             /* define defaults */
    1196           0 :             double src_x = ( search_left + search_right ) / 2.0;
    1197           0 :             double dst_y = ( search_top + search_bottom ) / 2.0;
    1198             : 
    1199             :             /* optimize coordinates */
    1200             :             geometry_rectangle_t depart_area;
    1201           0 :             geometry_rectangle_init_by_corners( &depart_area, src_left, src_top, src_right, dst_y );
    1202           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &depart_area, gap_dist, &src_x );
    1203           0 :             geometry_rectangle_destroy( &depart_area );
    1204             : 
    1205             :             geometry_rectangle_t arrive_area;
    1206           0 :             geometry_rectangle_init_by_corners( &arrive_area, src_x, dst_top, dst_left, dst_bottom );
    1207           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &arrive_area, gap_dist, &dst_y );
    1208           0 :             geometry_rectangle_destroy( &arrive_area );
    1209             : 
    1210             :             /* add solution */
    1211           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
    1212             :                                                    src_x,
    1213             :                                                    src_top,
    1214             :                                                    dst_left,
    1215             :                                                    dst_y,
    1216             :                                                    dst_y
    1217             :                                                  );
    1218           0 :             solutions_count ++;
    1219             :         }
    1220             :     }
    1221             : 
    1222             :     /* add two solutions from source-bottom */
    1223             :     {
    1224           0 :         const double search_top = src_bottom_to_outside ? fmax( src_bottom, dst_top ) : dst_top;
    1225           0 :         const double search_bottom = dst_bottom;
    1226             :         /* add a solution from source-bottom to destination-right */
    1227             :         {
    1228           0 :             const double search_left = dst_right_from_outside ? fmax( dst_right, src_left ) : src_left;
    1229           0 :             const double search_right = src_right;
    1230             : 
    1231             :             /* define defaults */
    1232           0 :             double src_x = ( search_left + search_right ) / 2.0;
    1233           0 :             double dst_y = ( search_top + search_bottom ) / 2.0;
    1234             : 
    1235             :             /* optimize coordinates */
    1236             :             geometry_rectangle_t depart_area;
    1237           0 :             geometry_rectangle_init_by_corners( &depart_area, src_left, src_bottom, src_right, dst_y );
    1238           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &depart_area, gap_dist, &src_x );
    1239           0 :             geometry_rectangle_destroy( &depart_area );
    1240             : 
    1241             :             geometry_rectangle_t arrive_area;
    1242           0 :             geometry_rectangle_init_by_corners( &arrive_area, src_x, dst_top, dst_right, dst_bottom );
    1243           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &arrive_area, gap_dist, &dst_y );
    1244           0 :             geometry_rectangle_destroy( &arrive_area );
    1245             : 
    1246             :             /* add solution */
    1247           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
    1248             :                                                    src_x,
    1249             :                                                    src_bottom,
    1250             :                                                    dst_right,
    1251             :                                                    dst_y,
    1252             :                                                    dst_y
    1253             :                                                  );
    1254           0 :             solutions_count ++;
    1255             :         }
    1256             :         /* add a solution from source-bottom to destination-left */
    1257             :         {
    1258           0 :             const double search_left = src_left;
    1259           0 :             const double search_right = dst_left_from_outside ? fmin( dst_left, src_right ) : src_right;
    1260             : 
    1261             :             /* define defaults */
    1262           0 :             double src_x = ( search_left + search_right ) / 2.0;
    1263           0 :             double dst_y = ( search_top + search_bottom ) / 2.0;
    1264             : 
    1265             :             /* optimize coordinates */
    1266             :             geometry_rectangle_t depart_area;
    1267           0 :             geometry_rectangle_init_by_corners( &depart_area, src_left, src_bottom, src_right, dst_y );
    1268           0 :             pencil_relationship_2d_layouter_private_find_space_for_v_line ( this_, &depart_area, gap_dist, &src_x );
    1269           0 :             geometry_rectangle_destroy( &depart_area );
    1270             : 
    1271             :             geometry_rectangle_t arrive_area;
    1272           0 :             geometry_rectangle_init_by_corners( &arrive_area, src_x, dst_top, dst_left, dst_bottom );
    1273           0 :             pencil_relationship_2d_layouter_private_find_space_for_h_line ( this_, &arrive_area, gap_dist, &dst_y );
    1274           0 :             geometry_rectangle_destroy( &arrive_area );
    1275             : 
    1276             :             /* add solution */
    1277           0 :             geometry_connector_reinit_horizontal ( &(out_solutions[solutions_count]),
    1278             :                                                    src_x,
    1279             :                                                    src_bottom,
    1280             :                                                    dst_left,
    1281             :                                                    dst_y,
    1282             :                                                    dst_y
    1283             :                                                  );
    1284           0 :             solutions_count ++;
    1285             :         }
    1286             :     }
    1287             : 
    1288           0 :     *out_solutions_count = solutions_count;
    1289             : 
    1290           0 :     U8_TRACE_END();
    1291           0 : }
    1292             : 
    1293           0 : u8_error_t pencil_relationship_2d_layouter_private_find_space_for_line ( pencil_relationship_2d_layouter_t *this_,
    1294             :                                                                          const geometry_rectangle_t *search_rect,
    1295             :                                                                          bool horizontal_line,
    1296             :                                                                          double min_gap,
    1297             :                                                                          double *io_coordinate )
    1298             : {
    1299           0 :     U8_TRACE_BEGIN();
    1300           0 :     assert ( NULL != search_rect );
    1301           0 :     assert ( NULL != io_coordinate );
    1302           0 :     u8_error_t err = U8_ERROR_NONE;
    1303             : 
    1304             :     /* start two probes at the center and move these to the boundaries when discovering overlaps */
    1305           0 :     const double center = *io_coordinate;
    1306           0 :     if ( horizontal_line )
    1307             :     {
    1308           0 :         assert( center > geometry_rectangle_get_top( search_rect ) - 0.000000001 );
    1309           0 :         assert( center < geometry_rectangle_get_bottom( search_rect ) + 0.000000001 );
    1310             :     }
    1311             :     else
    1312             :     {
    1313           0 :         assert( center > geometry_rectangle_get_left( search_rect ) - 0.000000001 );
    1314           0 :         assert( center < geometry_rectangle_get_right( search_rect ) + 0.000000001 );
    1315             :     }
    1316           0 :     double good_smaller = center;  /* a coordinate top/left of major obstacles */
    1317           0 :     double good_greater = center;  /* a coordinate bottom/right of major obstacles */
    1318           0 :     double best_smaller = center;  /* a coordinate top/left of any obstacle */
    1319           0 :     double best_greater = center;  /* a coordinate bottom/right of any obstacle */
    1320             : 
    1321             :     /* the rectangle where each classifier within is checked for intersections: */
    1322             :     geometry_rectangle_t consider_rect;
    1323           0 :     geometry_rectangle_copy( &consider_rect, search_rect );
    1324           0 :     if ( horizontal_line )
    1325             :     {
    1326           0 :         geometry_rectangle_set_top( &consider_rect, geometry_rectangle_get_top( search_rect ) - min_gap );
    1327           0 :         geometry_rectangle_set_height( &consider_rect, geometry_rectangle_get_height( search_rect ) + 2.0 * min_gap );
    1328             : 
    1329             :     }
    1330             :     else
    1331             :     {
    1332           0 :         geometry_rectangle_set_left( &consider_rect, geometry_rectangle_get_left( search_rect ) - min_gap );
    1333           0 :         geometry_rectangle_set_width( &consider_rect, geometry_rectangle_get_width( search_rect ) + 2.0 * min_gap );
    1334             :     }
    1335           0 :     const double minimum_result
    1336             :         = horizontal_line
    1337           0 :         ? geometry_rectangle_get_top( search_rect )
    1338           0 :         : geometry_rectangle_get_left( search_rect );
    1339           0 :     const double maximum_result
    1340             :         = horizontal_line
    1341           0 :         ? geometry_rectangle_get_bottom( search_rect )
    1342           0 :         : geometry_rectangle_get_right( search_rect );
    1343             : 
    1344             :     /* iterate till no hit anymore */
    1345           0 :     const uint32_t max_list_iteration = 8;  /* in any case, do not iterate ofer the list more than 8 times */
    1346           0 :     bool hit = true;  /* whenever the probes hit a rectangle, hit is set to true */
    1347           0 :     for ( uint32_t list_iteration = 0; (list_iteration < max_list_iteration) && hit; list_iteration ++ )
    1348             :     {
    1349           0 :         hit = false;
    1350             : 
    1351             :         /* move away from classifiers */
    1352           0 :         const uint32_t count_classifiers = layout_visible_set_get_visible_classifier_count ( (*this_).layout_data );
    1353           0 :         for ( uint32_t classifier_index = 0; classifier_index < count_classifiers; classifier_index ++ )
    1354             :         {
    1355             :             const layout_visible_classifier_t *const the_classifier
    1356           0 :                 = layout_visible_set_get_visible_classifier_ptr( (*this_).layout_data, classifier_index );
    1357             : 
    1358             :             const geometry_rectangle_t *const classifier_symbol_box
    1359           0 :                 = layout_visible_classifier_get_symbol_box_const( the_classifier );
    1360             :             const geometry_rectangle_t *const classifier_space
    1361           0 :                 = layout_visible_classifier_get_space_const( the_classifier );
    1362             :             /* Note: This algorithm ignores if the current classifier is parent container of source or destination */
    1363           0 :             if ( geometry_rectangle_is_intersecting( &consider_rect, classifier_symbol_box ) )
    1364             :             {
    1365           0 :                 const double clas_symbol_box_smaller
    1366             :                     = horizontal_line /* do vertical search if line is horizontal */
    1367           0 :                     ? ( geometry_rectangle_get_top(classifier_symbol_box) - min_gap )
    1368           0 :                     : ( geometry_rectangle_get_left(classifier_symbol_box) - min_gap );
    1369           0 :                 const double clas_symbol_box_greater
    1370             :                     = horizontal_line /* do vertical search if line is horizontal */
    1371           0 :                     ? ( geometry_rectangle_get_bottom(classifier_symbol_box) + min_gap )
    1372           0 :                     : ( geometry_rectangle_get_right(classifier_symbol_box) + min_gap );
    1373             : 
    1374           0 :                 const double undo_good_smaller = good_smaller;
    1375           0 :                 const double undo_good_greater = good_greater;
    1376           0 :                 const bool undo_hit = hit;
    1377           0 :                 const geometry_rectangle_t good_smaller_rect
    1378           0 :                     = { .left = horizontal_line ? geometry_rectangle_get_left( search_rect ) : good_smaller,
    1379           0 :                         .top = horizontal_line ? good_smaller : geometry_rectangle_get_top( search_rect ),
    1380           0 :                         .width = horizontal_line ? geometry_rectangle_get_width( search_rect ) : 0.0,
    1381           0 :                         .height = horizontal_line ? 0.0 : geometry_rectangle_get_height( search_rect )
    1382             :                     };
    1383           0 :                 if ( ( ! geometry_rectangle_is_containing( classifier_space, &good_smaller_rect ) )
    1384           0 :                     && ( clas_symbol_box_smaller < good_smaller ) && ( good_smaller < clas_symbol_box_greater ) )
    1385             :                 {
    1386           0 :                     good_smaller = clas_symbol_box_smaller;
    1387           0 :                     hit = true;
    1388             :                 }
    1389           0 :                 const geometry_rectangle_t good_greater_rect
    1390           0 :                     = { .left = horizontal_line ? geometry_rectangle_get_left( search_rect ) : good_greater,
    1391           0 :                         .top = horizontal_line ? good_greater : geometry_rectangle_get_top( search_rect ),
    1392           0 :                         .width = horizontal_line ? geometry_rectangle_get_width( search_rect ) : 0.0,
    1393           0 :                         .height = horizontal_line ? 0.0 : geometry_rectangle_get_height( search_rect )
    1394             :                     };
    1395           0 :                 if ( ( ! geometry_rectangle_is_containing( classifier_space, &good_greater_rect ) )
    1396           0 :                     && ( clas_symbol_box_smaller < good_greater ) && ( good_greater < clas_symbol_box_greater ) )
    1397             :                 {
    1398           0 :                     good_greater = clas_symbol_box_greater;
    1399           0 :                     hit = true;
    1400             :                 }
    1401           0 :                 const bool no_solution_remaining
    1402           0 :                     = ( good_smaller < minimum_result )&&( good_greater > maximum_result );
    1403           0 :                 if ( no_solution_remaining )
    1404             :                 {
    1405             :                     /* restore old values */
    1406           0 :                     good_smaller = undo_good_smaller;
    1407           0 :                     good_greater = undo_good_greater;
    1408           0 :                     hit = undo_hit;
    1409             :                 }
    1410           0 :                 const geometry_rectangle_t best_smaller_rect
    1411           0 :                     = { .left = horizontal_line ? geometry_rectangle_get_left( search_rect ) : best_smaller,
    1412           0 :                         .top = horizontal_line ? best_smaller : geometry_rectangle_get_top( search_rect ),
    1413           0 :                         .width = horizontal_line ? geometry_rectangle_get_width( search_rect ) : 0.0,
    1414           0 :                         .height = horizontal_line ? 0.0 : geometry_rectangle_get_height( search_rect )
    1415             :                     };
    1416           0 :                 if ( ( ! geometry_rectangle_is_containing( classifier_space, &best_smaller_rect ) )
    1417           0 :                     && ( clas_symbol_box_smaller < best_smaller ) && ( best_smaller < clas_symbol_box_greater ) )
    1418             :                 {
    1419           0 :                     best_smaller = clas_symbol_box_smaller;
    1420           0 :                     hit = true;
    1421             :                 }
    1422           0 :                 const geometry_rectangle_t best_greater_rect
    1423           0 :                     = { .left = horizontal_line ? geometry_rectangle_get_left( search_rect ) : best_greater,
    1424           0 :                         .top = horizontal_line ? best_greater : geometry_rectangle_get_top( search_rect ),
    1425           0 :                         .width = horizontal_line ? geometry_rectangle_get_width( search_rect ) : 0.0,
    1426           0 :                         .height = horizontal_line ? 0.0 : geometry_rectangle_get_height( search_rect )
    1427             :                     };
    1428           0 :                 if ( ( ! geometry_rectangle_is_containing( classifier_space, &best_greater_rect ) )
    1429           0 :                     && ( clas_symbol_box_smaller < best_greater ) && ( best_greater < clas_symbol_box_greater ) )
    1430             :                 {
    1431           0 :                     best_greater = clas_symbol_box_greater;
    1432           0 :                     hit = true;
    1433             :                 }
    1434             :             }
    1435             : 
    1436             :             const geometry_rectangle_t *const classifier_label_box
    1437           0 :                 = layout_visible_classifier_get_label_box_const( the_classifier );
    1438           0 :             if ( geometry_rectangle_is_intersecting( &consider_rect, classifier_label_box ) )
    1439             :             {
    1440           0 :                 const double clas_label_smaller
    1441             :                     = horizontal_line /* do vertical search if line is horizontal */
    1442           0 :                     ? ( geometry_rectangle_get_top(classifier_label_box) - min_gap )
    1443           0 :                     : ( geometry_rectangle_get_left(classifier_label_box) - min_gap );
    1444           0 :                 const double clas_label_greater
    1445             :                     = horizontal_line /* do vertical search if line is horizontal */
    1446           0 :                     ? ( geometry_rectangle_get_bottom(classifier_label_box) + min_gap )
    1447           0 :                     : ( geometry_rectangle_get_right(classifier_label_box) + min_gap );
    1448             : 
    1449           0 :                 if ( ( clas_label_smaller < good_smaller ) && ( good_smaller < clas_label_greater ) )
    1450             :                 {
    1451           0 :                     good_smaller = clas_label_smaller;
    1452           0 :                     hit = true;
    1453             :                 }
    1454           0 :                 if ( ( clas_label_smaller < good_greater ) && ( good_greater < clas_label_greater ) )
    1455             :                 {
    1456           0 :                     good_greater = clas_label_greater;
    1457           0 :                     hit = true;
    1458             :                 }
    1459           0 :                 if ( ( clas_label_smaller < best_smaller ) && ( best_smaller < clas_label_greater ) )
    1460             :                 {
    1461           0 :                     best_smaller = clas_label_smaller;
    1462           0 :                     hit = true;
    1463             :                 }
    1464           0 :                 if ( ( clas_label_smaller < best_greater ) && ( best_greater < clas_label_greater ) )
    1465             :                 {
    1466           0 :                     best_greater = clas_label_greater;
    1467           0 :                     hit = true;
    1468             :                 }
    1469             :             }
    1470             :         }
    1471             : 
    1472             :         /* move away from features, check symbol boxes only, label boxes are not yet initialized */
    1473           0 :         const uint32_t count_features = layout_visible_set_get_feature_count ( (*this_).layout_data );
    1474           0 :         for ( uint32_t f_idx = 0; f_idx < count_features; f_idx ++ )
    1475             :         {
    1476             :             const layout_feature_t *const feature_layout
    1477           0 :                 = layout_visible_set_get_feature_ptr ( (*this_).layout_data, f_idx );
    1478             : 
    1479             :             const geometry_rectangle_t *const feature_symbol_box
    1480           0 :                 = layout_feature_get_symbol_box_const( feature_layout );
    1481           0 :             if ( geometry_rectangle_is_intersecting( &consider_rect, feature_symbol_box ) )
    1482             :             {
    1483           0 :                 const double feature_smaller
    1484             :                     = horizontal_line /* do vertical search if line is horizontal */
    1485           0 :                     ? ( geometry_rectangle_get_top(feature_symbol_box) - min_gap )
    1486           0 :                     : ( geometry_rectangle_get_left(feature_symbol_box) - min_gap );
    1487           0 :                 const double feature_greater
    1488             :                     = horizontal_line /* do vertical search if line is horizontal */
    1489           0 :                     ? ( geometry_rectangle_get_bottom(feature_symbol_box) + min_gap )
    1490           0 :                     : ( geometry_rectangle_get_right(feature_symbol_box) + min_gap );
    1491             : 
    1492           0 :                 if ( ( feature_smaller < good_smaller ) && ( good_smaller < feature_greater ) )
    1493             :                 {
    1494           0 :                     good_smaller = feature_smaller;
    1495           0 :                     hit = true;
    1496             :                 }
    1497           0 :                 if ( ( feature_smaller < good_greater ) && ( good_greater < feature_greater ) )
    1498             :                 {
    1499           0 :                     good_greater = feature_greater;
    1500           0 :                     hit = true;
    1501             :                 }
    1502           0 :                 if ( ( feature_smaller < best_smaller ) && ( best_smaller < feature_greater ) )
    1503             :                 {
    1504           0 :                     best_smaller = feature_smaller;
    1505           0 :                     hit = true;
    1506             :                 }
    1507           0 :                 if ( ( feature_smaller < best_greater ) && ( best_greater < feature_greater ) )
    1508             :                 {
    1509           0 :                     best_greater = feature_greater;
    1510           0 :                     hit = true;
    1511             :                 }
    1512             :             }
    1513             :         }
    1514             : 
    1515             :         /* move away from already layed-out parallel relationship-segments; */
    1516             :         /* iterate over the already created connectors */
    1517             :         layout_relationship_iter_t relationship_iterator;
    1518           0 :         layout_relationship_iter_copy( &relationship_iterator, &((*this_).already_processed) );
    1519           0 :         while ( layout_relationship_iter_has_next( &relationship_iterator ) )
    1520             :         {
    1521             :             /* get pointer to relationship */
    1522           0 :             const layout_relationship_t *const exist_relationship = layout_relationship_iter_next_ptr( &relationship_iterator );
    1523             : 
    1524             :             /* Note: This algorithm ignores the relationship types (same_type), sources and destinations (one_same_end) */
    1525           0 :             const geometry_connector_t *const exist_shape = layout_relationship_get_shape_const( exist_relationship );
    1526           0 :             if ( geometry_connector_is_intersecting_rectangle( exist_shape, &consider_rect ) )
    1527             :             {
    1528             :                 const geometry_rectangle_t seg_1
    1529           0 :                     = geometry_connector_get_segment_bounds( exist_shape, GEOMETRY_CONNECTOR_SEGMENT_SOURCE );
    1530             :                 const bool seg_1_is_intersecting
    1531           0 :                     = geometry_rectangle_is_intersecting( &seg_1, &consider_rect );
    1532           0 :                 const double seg_1_smaller
    1533             :                     = horizontal_line /* do vertical search if line is horizontal */
    1534           0 :                     ? ( geometry_rectangle_get_top( &seg_1 ) - min_gap )
    1535           0 :                     : ( geometry_rectangle_get_left( &seg_1 ) - min_gap );
    1536           0 :                 const double seg_1_greater
    1537             :                     = horizontal_line /* do vertical search if line is horizontal */
    1538           0 :                     ? ( geometry_rectangle_get_bottom( &seg_1 ) + min_gap )
    1539           0 :                     : ( geometry_rectangle_get_right( &seg_1 ) + min_gap );
    1540           0 :                 if ( seg_1_is_intersecting
    1541           0 :                     && ( seg_1_smaller < best_smaller ) && ( best_smaller < seg_1_greater ) )
    1542             :                 {
    1543           0 :                     best_smaller = seg_1_smaller;
    1544           0 :                     hit = true;
    1545             :                 }
    1546           0 :                 if ( seg_1_is_intersecting
    1547           0 :                     && ( seg_1_smaller < best_greater ) && ( best_greater < seg_1_greater ) )
    1548             :                 {
    1549           0 :                     best_greater = seg_1_greater;
    1550           0 :                     hit = true;
    1551             :                 }
    1552             :                 const geometry_rectangle_t seg_2
    1553           0 :                     = geometry_connector_get_segment_bounds( exist_shape, GEOMETRY_CONNECTOR_SEGMENT_MAIN );
    1554             :                 const bool seg_2_is_intersecting
    1555           0 :                     = geometry_rectangle_is_intersecting( &seg_2, &consider_rect );
    1556           0 :                 const double seg_2_smaller
    1557             :                     = horizontal_line /* do vertical search if line is horizontal */
    1558           0 :                     ? ( geometry_rectangle_get_top( &seg_2 ) - min_gap )
    1559           0 :                     : ( geometry_rectangle_get_left( &seg_2 ) - min_gap );
    1560           0 :                 const double seg_2_greater
    1561             :                     = horizontal_line /* do vertical search if line is horizontal */
    1562           0 :                     ? ( geometry_rectangle_get_bottom( &seg_2 ) + min_gap )
    1563           0 :                     : ( geometry_rectangle_get_right( &seg_2 ) + min_gap );
    1564           0 :                 if ( seg_2_is_intersecting
    1565           0 :                     && ( seg_2_smaller < best_smaller ) && ( best_smaller < seg_2_greater ) )
    1566             :                 {
    1567           0 :                     best_smaller = seg_2_smaller;
    1568           0 :                     hit = true;
    1569             :                 }
    1570           0 :                 if ( seg_2_is_intersecting
    1571           0 :                     && ( seg_2_smaller < best_greater ) && ( best_greater < seg_2_greater ) )
    1572             :                 {
    1573           0 :                     best_greater = seg_2_greater;
    1574           0 :                     hit = true;
    1575             :                 }
    1576             :                 const geometry_rectangle_t seg_3
    1577           0 :                     = geometry_connector_get_segment_bounds( exist_shape, GEOMETRY_CONNECTOR_SEGMENT_DESTINATION );
    1578             :                 const bool seg_3_is_intersecting
    1579           0 :                     = geometry_rectangle_is_intersecting( &seg_3, &consider_rect );
    1580           0 :                 const double seg_3_smaller
    1581             :                     = horizontal_line /* do vertical search if line is horizontal */
    1582           0 :                     ? ( geometry_rectangle_get_top( &seg_3 ) - min_gap )
    1583           0 :                     : ( geometry_rectangle_get_left( &seg_3 ) - min_gap );
    1584           0 :                 const double seg_3_greater
    1585             :                     = horizontal_line /* do vertical search if line is horizontal */
    1586           0 :                     ? ( geometry_rectangle_get_bottom( &seg_3 ) + min_gap )
    1587           0 :                     : ( geometry_rectangle_get_right( &seg_3 ) + min_gap );
    1588           0 :                 if ( seg_3_is_intersecting
    1589           0 :                     && ( seg_3_smaller < best_smaller ) && ( best_smaller < seg_3_greater ) )
    1590             :                 {
    1591           0 :                     best_smaller = seg_3_smaller;
    1592           0 :                     hit = true;
    1593             :                 }
    1594           0 :                 if ( seg_3_is_intersecting
    1595           0 :                     && ( seg_3_smaller < best_greater ) && ( best_greater < seg_3_greater ) )
    1596             :                 {
    1597           0 :                     best_greater = seg_3_greater;
    1598           0 :                     hit = true;
    1599             :                 }
    1600             : 
    1601           0 :                 const geometry_3dir_t exist_dirs = geometry_connector_get_directions( exist_shape );
    1602           0 :                 if ( horizontal_line )
    1603             :                 {
    1604           0 :                     const double exist_source_y = geometry_connector_get_main_line_source_y ( exist_shape );
    1605           0 :                     const double exist_destination_y = geometry_connector_get_main_line_destination_y ( exist_shape );
    1606           0 :                     if ( geometry_3dir_is_first_h( &exist_dirs ) || geometry_3dir_is_second_h( &exist_dirs ) )
    1607             :                     {
    1608           0 :                         if (( exist_source_y - min_gap < good_smaller )&&( good_smaller < exist_source_y + min_gap ))
    1609             :                         {
    1610           0 :                             good_smaller = exist_source_y - min_gap;
    1611           0 :                             hit = true;
    1612             :                         }
    1613           0 :                         if (( exist_source_y - min_gap < good_greater )&&( good_greater < exist_source_y + min_gap ))
    1614             :                         {
    1615           0 :                             good_greater = exist_source_y + min_gap;
    1616           0 :                             hit = true;
    1617             :                         }
    1618             :                     }
    1619           0 :                     if ( geometry_3dir_is_third_h( &exist_dirs ) ) /* third segment only, second is already evaluated above */
    1620             :                     {
    1621           0 :                         if (( exist_destination_y - min_gap < good_smaller )&&( good_smaller < exist_destination_y + min_gap ))
    1622             :                         {
    1623           0 :                             good_smaller = exist_destination_y - min_gap;
    1624           0 :                             hit = true;
    1625             :                         }
    1626           0 :                         if (( exist_destination_y - min_gap < good_greater )&&( good_greater < exist_destination_y + min_gap ))
    1627             :                         {
    1628           0 :                             good_greater = exist_destination_y + min_gap;
    1629           0 :                             hit = true;
    1630             :                         }
    1631             :                     }
    1632             :                 }
    1633             :                 else
    1634             :                 {
    1635           0 :                     const double exist_source_x = geometry_connector_get_main_line_source_x ( exist_shape );
    1636           0 :                     const double exist_destination_x = geometry_connector_get_main_line_destination_x ( exist_shape );
    1637           0 :                     if ( geometry_3dir_is_first_v( &exist_dirs ) || geometry_3dir_is_second_v( &exist_dirs ) )
    1638             :                     {
    1639           0 :                         if (( exist_source_x - min_gap < good_smaller )&&( good_smaller < exist_source_x + min_gap ))
    1640             :                         {
    1641           0 :                             good_smaller = exist_source_x - min_gap;
    1642           0 :                             hit = true;
    1643             :                         }
    1644           0 :                         if (( exist_source_x - min_gap < good_greater )&&( good_greater < exist_source_x + min_gap ))
    1645             :                         {
    1646           0 :                             good_greater = exist_source_x + min_gap;
    1647           0 :                             hit = true;
    1648             :                         }
    1649             :                     }
    1650           0 :                     if ( geometry_3dir_is_third_v( &exist_dirs ) ) /* third segment only, second is already evaluated above */
    1651             :                     {
    1652           0 :                         if (( exist_destination_x - min_gap < good_smaller )&&( good_smaller < exist_destination_x + min_gap ))
    1653             :                         {
    1654           0 :                             good_smaller = exist_destination_x - min_gap;
    1655           0 :                             hit = true;
    1656             :                         }
    1657           0 :                         if (( exist_destination_x - min_gap < good_greater )&&( good_greater < exist_destination_x + min_gap ))
    1658             :                         {
    1659           0 :                             good_greater = exist_destination_x + min_gap;
    1660           0 :                             hit = true;
    1661             :                         }
    1662             :                     }
    1663             :                 }
    1664             :             }
    1665             :         }
    1666           0 :         layout_relationship_iter_destroy( &relationship_iterator );
    1667             :     }
    1668             : 
    1669             :     /* check success */
    1670           0 :     if ( best_greater < maximum_result )
    1671             :     {
    1672           0 :         if ( best_smaller > minimum_result )
    1673             :         {
    1674             :             /* best_greater and best_smaller are both in range; */
    1675             :             /* select the one with smaller distance to the center: */
    1676           0 :             if ( best_greater - center > center - best_smaller )
    1677             :             {
    1678           0 :                 *io_coordinate = best_smaller;
    1679             :             }
    1680             :             else
    1681             :             {
    1682           0 :                 *io_coordinate = best_greater;
    1683             :             }
    1684             :         }
    1685             :         else  /* best_greater is in range */
    1686             :         {
    1687           0 :             *io_coordinate = best_greater;
    1688             :         }
    1689             :     }
    1690             :     else
    1691             :     {
    1692           0 :         if ( best_smaller > minimum_result )
    1693             :         {
    1694             :             /* best_smaller is in range */
    1695           0 :             *io_coordinate = best_smaller;
    1696             :         }
    1697             :         else
    1698             :         {
    1699             :             /* BOTH BEST VALUES ARE OUT OF RANGE */
    1700             :             /* CHECK GOOD VALUES: */
    1701           0 :             if ( good_greater > maximum_result )
    1702             :             {
    1703           0 :                 if ( good_smaller < minimum_result )
    1704             :                 {
    1705           0 :                     err = U8_ERROR_NOT_FOUND;
    1706             :                 }
    1707             :                 else  /* good_smaller is in range */
    1708             :                 {
    1709           0 :                     *io_coordinate = good_smaller;
    1710             :                 }
    1711             :             }
    1712             :             else  /* good_greater is in range */
    1713             :             {
    1714           0 :                 if ( good_smaller < minimum_result )
    1715             :                 {
    1716           0 :                     *io_coordinate = good_greater;
    1717             :                 }
    1718             :                 else
    1719             :                 {
    1720             :                     /* good_smaller and good_greater are both in range; */
    1721             :                     /* select the one with smaller distance to the center: */
    1722           0 :                     if ( good_greater - center > center - good_smaller )
    1723             :                     {
    1724           0 :                         *io_coordinate = good_smaller;
    1725             :                     }
    1726             :                     else
    1727             :                     {
    1728           0 :                         *io_coordinate = good_greater;
    1729             :                     }
    1730             :                 }
    1731             :             }
    1732             :         }
    1733             :     }
    1734             : 
    1735           0 :     geometry_rectangle_destroy( &consider_rect );
    1736             : 
    1737           0 :     U8_TRACE_END_ERR(err);
    1738           0 :     return err;
    1739             : }
    1740             : 
    1741           0 : void pencil_relationship_2d_layouter_private_make_all_visible ( pencil_relationship_2d_layouter_t *this_ )
    1742             : {
    1743           0 :     U8_TRACE_BEGIN();
    1744             : 
    1745             :     /* determine visibility */
    1746           0 :     const uint32_t count_relations = layout_visible_set_get_relationship_count ( (*this_).layout_data );
    1747           0 :     for ( uint32_t index = 0; index < count_relations; index ++ )
    1748             :     {
    1749           0 :         layout_relationship_t *const the_relation = layout_visible_set_get_relationship_ptr ( (*this_).layout_data, index );
    1750           0 :         const layout_visible_classifier_t *const from_layout = layout_relationship_get_from_classifier_ptr ( the_relation );
    1751           0 :         const layout_visible_classifier_t *const to_layout = layout_relationship_get_to_classifier_ptr ( the_relation );
    1752           0 :         assert( from_layout != NULL );
    1753           0 :         assert( to_layout != NULL );
    1754           0 :         const data_visible_classifier_t *const from_data = layout_visible_classifier_get_data_const( from_layout );
    1755           0 :         const data_visible_classifier_t *const to_data = layout_visible_classifier_get_data_const( to_layout );
    1756           0 :         const data_diagramelement_t *const from_diagele = data_visible_classifier_get_diagramelement_const( from_data );
    1757           0 :         const data_diagramelement_t *const to_diagele = data_visible_classifier_get_diagramelement_const( to_data );
    1758           0 :         const data_diagramelement_flag_t from_flags = data_diagramelement_get_display_flags ( from_diagele );
    1759           0 :         const data_diagramelement_flag_t to_flags = data_diagramelement_get_display_flags ( to_diagele );
    1760           0 :         if (( 0 != ( DATA_DIAGRAMELEMENT_FLAG_GRAY_OUT & from_flags ))
    1761           0 :             || ( 0 != ( DATA_DIAGRAMELEMENT_FLAG_GRAY_OUT & to_flags )))
    1762             :         {
    1763           0 :             layout_relationship_set_visibility ( the_relation, PENCIL_VISIBILITY_GRAY_OUT );
    1764             :         }
    1765             :         else
    1766             :         {
    1767           0 :             layout_relationship_set_visibility ( the_relation, PENCIL_VISIBILITY_SHOW );
    1768             :         }
    1769             :     }
    1770             : 
    1771           0 :     U8_TRACE_END();
    1772           0 : }
    1773             : 
    1774           0 : void pencil_relationship_2d_layouter_layout_standard( pencil_relationship_2d_layouter_t *this_ )
    1775             : {
    1776           0 :     U8_TRACE_BEGIN();
    1777             : 
    1778           0 :     pencil_relationship_2d_layouter_private_make_all_visible( this_ );
    1779             : 
    1780           0 :     pencil_relationship_2d_layouter_private_do_layout ( this_ );
    1781             : 
    1782           0 :     U8_TRACE_END();
    1783           0 : }
    1784             : 
    1785           0 : void pencil_relationship_2d_layouter_layout_void( pencil_relationship_2d_layouter_t *this_ )
    1786             : {
    1787           0 :     U8_TRACE_BEGIN();
    1788             : 
    1789             :     /* hide all relationships */
    1790             :     const uint32_t count_relations
    1791           0 :         = layout_visible_set_get_relationship_count ( (*this_).layout_data );
    1792           0 :     for ( uint32_t index = 0; index < count_relations; index ++ )
    1793             :     {
    1794             :         /*
    1795             :         layout_visible_set_set_relationship_visibility ( (*this_).layout_data, index, PENCIL_VISIBILITY_HIDE );
    1796             :         */
    1797           0 :         layout_visible_set_set_relationship_visibility ( (*this_).layout_data, index, PENCIL_VISIBILITY_IMPLICIT );
    1798             :     }
    1799             : 
    1800             :     /* layout the relationships (needed for PENCIL_VISIBILITY_IMPLICIT) */
    1801           0 :     pencil_relationship_2d_layouter_private_do_layout ( this_ );
    1802             : 
    1803           0 :     U8_TRACE_END();
    1804           0 : }
    1805             : 
    1806           0 : void pencil_relationship_2d_layouter_layout_for_communication( pencil_relationship_2d_layouter_t *this_ )
    1807             : {
    1808           0 :     U8_TRACE_BEGIN();
    1809             : 
    1810           0 :     pencil_relationship_2d_layouter_private_make_all_visible( this_ );
    1811             : 
    1812             :     /* hide some relationships */
    1813             :     const uint32_t count_relations
    1814           0 :         = layout_visible_set_get_relationship_count ( (*this_).layout_data );
    1815           0 :     for ( uint32_t index = 0; index < count_relations; index ++ )
    1816             :     {
    1817             :         layout_relationship_t *const the_relationship
    1818           0 :             = layout_visible_set_get_relationship_ptr ( (*this_).layout_data, index );
    1819             : 
    1820             :         /* adjust visibility */
    1821           0 :         if ( ( NULL == layout_relationship_get_from_feature_ptr ( the_relationship ) )
    1822           0 :             && ( NULL == layout_relationship_get_to_feature_ptr ( the_relationship ) ) )
    1823             :         {
    1824             :             /* this is a globally visible relation, not local/scenario-based */
    1825           0 :             layout_visible_set_set_relationship_visibility ( (*this_).layout_data, index, PENCIL_VISIBILITY_IMPLICIT );
    1826             :         }
    1827             :     }
    1828             : 
    1829             :     /* layout the visible relationships */
    1830           0 :     pencil_relationship_2d_layouter_private_do_layout ( this_ );
    1831             : 
    1832           0 :     U8_TRACE_END();
    1833           0 : }
    1834             : 
    1835             : 
    1836             : /*
    1837             : Copyright 2017-2025 Andreas Warnke
    1838             : 
    1839             : Licensed under the Apache License, Version 2.0 (the "License");
    1840             : you may not use this file except in compliance with the License.
    1841             : You may obtain a copy of the License at
    1842             : 
    1843             :     http://www.apache.org/licenses/LICENSE-2.0
    1844             : 
    1845             : Unless required by applicable law or agreed to in writing, software
    1846             : distributed under the License is distributed on an "AS IS" BASIS,
    1847             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    1848             : See the License for the specific language governing permissions and
    1849             : limitations under the License.
    1850             : */

Generated by: LCOV version 1.16