LCOV - code coverage report
Current view: top level - pencil/source - pencil_relationship_2d_layouter.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.63.2_covts Lines: 0.0 % 829 0
Test Date: 2025-05-01 10:10:14 Functions: 0.0 % 15 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 2.0-1