Line data Source code
1 : /* File: pencil_label_layout_helper.c; Copyright and License: see below */ 2 : 3 : #include "pencil_label_layout_helper.h" 4 : #include "u8/u8_trace.h" 5 : #include "utf8stringbuf/utf8string.h" 6 : 7 0 : void pencil_label_layout_helper_init( pencil_label_layout_helper_t *this_ ) 8 : { 9 0 : U8_TRACE_BEGIN(); 10 : 11 0 : (*this_).dummy = 0; /* prevent warnings on uninitialized usage */ 12 : 13 0 : U8_TRACE_END(); 14 0 : } 15 : 16 0 : void pencil_label_layout_helper_destroy( pencil_label_layout_helper_t *this_ ) 17 : { 18 0 : U8_TRACE_BEGIN(); 19 : 20 0 : U8_TRACE_END(); 21 0 : } 22 : 23 0 : void pencil_label_layout_helper_select_solution ( pencil_label_layout_helper_t *this_, 24 : layout_visible_set_t *layout_data, 25 : geometry_point_t target_point, 26 : uint32_t solutions_count, 27 : const geometry_rectangle_t solutions[], 28 : uint32_t *out_index_of_best ) 29 : { 30 0 : U8_TRACE_BEGIN(); 31 0 : assert( NULL != solutions ); 32 0 : assert( solutions_count >= 1 ); 33 0 : assert( NULL != out_index_of_best ); 34 : 35 : /* get draw area */ 36 : const layout_diagram_t *const diagram_layout 37 0 : = layout_visible_set_get_diagram_ptr( layout_data ); 38 : const geometry_rectangle_t *const diagram_draw_area 39 0 : = layout_diagram_get_draw_area_const( diagram_layout ); 40 : 41 : /* define potential solution and rating */ 42 0 : uint32_t index_of_best = 0; 43 0 : double debts_of_best = DBL_MAX; 44 : 45 : /* evaluate the solutions by their overlaps with classifiers */ 46 0 : for ( uint32_t solution_idx = 0; solution_idx < solutions_count; solution_idx ++ ) 47 : { 48 : /* evalute the debts of this solution */ 49 0 : double debts_of_current = 0.0; 50 0 : const geometry_rectangle_t * const current_solution = &(solutions[solution_idx]); 51 : 52 : /* avoid alternating solutions in case their debts are identical */ 53 0 : debts_of_current += 0.1 * solution_idx; 54 : 55 : /* check distance to target point */ 56 0 : const geometry_point_t solution_middle = geometry_rectangle_get_center( current_solution ); 57 0 : debts_of_current += geometry_point_calc_chess_distance ( &target_point, &solution_middle ); 58 : 59 : /* add debts for overlap to diagram boundary */ 60 0 : if ( ! geometry_rectangle_is_containing( diagram_draw_area, current_solution ) ) 61 : { 62 0 : debts_of_current += 100.0 * geometry_rectangle_get_area(diagram_draw_area); /* high debt */ 63 : } 64 : 65 : /* iterate over all classifiers */ 66 : const uint32_t count_clasfy 67 0 : = layout_visible_set_get_visible_classifier_count ( layout_data ); 68 0 : for ( uint32_t clasfy_index = 0; clasfy_index < count_clasfy; clasfy_index ++ ) 69 : { 70 : const layout_visible_classifier_t *const probe_classifier 71 0 : = layout_visible_set_get_visible_classifier_ptr( layout_data, clasfy_index ); 72 : 73 : const geometry_rectangle_t *const classifier_symbol_box 74 0 : = layout_visible_classifier_get_symbol_box_const( probe_classifier ); 75 0 : if ( geometry_rectangle_is_intersecting( current_solution, classifier_symbol_box ) ) 76 : { 77 : /* overlaps to the symbol box are bad only if not contained in space area */ 78 : const geometry_rectangle_t *const classifier_space 79 0 : = layout_visible_classifier_get_space_const( probe_classifier ); 80 0 : if ( ! geometry_rectangle_is_containing( classifier_space, current_solution ) ) 81 : { 82 0 : debts_of_current += geometry_rectangle_get_intersect_area( current_solution, classifier_symbol_box ); /* low debt */ 83 : } 84 : } 85 : 86 : const geometry_rectangle_t *const classifier_label_box 87 0 : = layout_visible_classifier_get_label_box_const( probe_classifier ); 88 0 : if ( geometry_rectangle_is_intersecting( current_solution, classifier_label_box ) ) 89 : { 90 0 : debts_of_current += 100.0 * geometry_rectangle_get_intersect_area( current_solution, classifier_label_box ); /* medium debt */ 91 : } 92 : } 93 : 94 : /* iterate over all features */ 95 : const uint32_t count_feat 96 0 : = layout_visible_set_get_feature_count ( layout_data ); 97 0 : for ( uint32_t feat_index = 0; feat_index < count_feat; feat_index ++ ) 98 : { 99 : const layout_feature_t *const probe_feature 100 0 : = layout_visible_set_get_feature_ptr( layout_data, feat_index ); 101 : const data_feature_t *const probe_f_data 102 0 : = layout_feature_get_data_const( probe_feature ); 103 : 104 : const geometry_rectangle_t *const feature_symbol_box 105 0 : = layout_feature_get_symbol_box_const( probe_feature ); 106 0 : if ( geometry_rectangle_is_intersecting( current_solution, feature_symbol_box ) ) 107 : { 108 0 : if ( DATA_FEATURE_TYPE_LIFELINE == data_feature_get_main_type( probe_f_data ) ) 109 : { 110 0 : debts_of_current += geometry_rectangle_get_intersect_area( current_solution, feature_symbol_box ); /* low debt */ 111 : } 112 : else 113 : { 114 0 : debts_of_current += 100.0 * geometry_rectangle_get_intersect_area( current_solution, feature_symbol_box ); /* medium debt */ 115 : } 116 : } 117 : 118 : const geometry_rectangle_t *const feature_label_box 119 0 : = layout_feature_get_label_box_const( probe_feature ); 120 0 : if ( geometry_rectangle_is_intersecting( current_solution, feature_label_box ) ) 121 : { 122 0 : debts_of_current += 100.0 * geometry_rectangle_get_intersect_area( current_solution, feature_label_box ); /* medium debt */ 123 : } 124 : } 125 : 126 : /* iterate over all relationships */ 127 : const uint32_t count_relations 128 0 : = layout_visible_set_get_relationship_count ( layout_data ); 129 0 : for ( uint32_t rel_index = 0; rel_index < count_relations; rel_index ++ ) 130 : { 131 : /* add debts if intersects */ 132 : const layout_relationship_t *const probe_relationship 133 0 : = layout_visible_set_get_relationship_ptr( layout_data, rel_index ); 134 0 : if (( PENCIL_VISIBILITY_SHOW == layout_relationship_get_visibility( probe_relationship ) ) 135 0 : || ( PENCIL_VISIBILITY_GRAY_OUT == layout_relationship_get_visibility( probe_relationship ) )) 136 : { 137 : const geometry_connector_t *const probe_shape 138 0 : = layout_relationship_get_shape_const( probe_relationship ); 139 0 : if ( geometry_connector_is_intersecting_rectangle( probe_shape, current_solution ) ) 140 : { 141 0 : debts_of_current += geometry_rectangle_get_area( current_solution ); /* relationship bounds intersects are not so bad ... low debt */ 142 : } 143 : 144 : const geometry_rectangle_t *const relationship_label_box 145 0 : = layout_relationship_get_label_box_const( probe_relationship ); 146 0 : if ( geometry_rectangle_is_intersecting( current_solution, relationship_label_box ) ) 147 : { 148 0 : debts_of_current += 100.0 * geometry_rectangle_get_intersect_area( current_solution, relationship_label_box ); /* medium debt */ 149 : } 150 : } 151 : } 152 : 153 : /* update best solution */ 154 0 : if ( debts_of_current < debts_of_best ) 155 : { 156 0 : index_of_best = solution_idx; 157 0 : debts_of_best = debts_of_current; 158 : } 159 : } 160 : 161 : /* 162 : static unsigned int random; 163 : random ++; 164 : index_of_best = random % solutions_count; 165 : */ 166 : 167 : /* output the best */ 168 0 : U8_TRACE_INFO_INT_INT("label layout idx, debt:", index_of_best, (int32_t)debts_of_best) 169 0 : *out_index_of_best = index_of_best; 170 : 171 0 : U8_TRACE_END(); 172 0 : } 173 : 174 : 175 : /* 176 : * Copyright 2019-2024 Andreas Warnke 177 : * 178 : * Licensed under the Apache License, Version 2.0 (the "License"); 179 : * you may not use this file except in compliance with the License. 180 : * You may obtain a copy of the License at 181 : * 182 : * http://www.apache.org/licenses/LICENSE-2.0 183 : * 184 : * Unless required by applicable law or agreed to in writing, software 185 : * distributed under the License is distributed on an "AS IS" BASIS, 186 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 187 : * See the License for the specific language governing permissions and 188 : * limitations under the License. 189 : */