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

Generated by: LCOV version 2.0-1