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

Generated by: LCOV version 2.0-1