| 1 | // =============================================================== // |
|---|
| 2 | // // |
|---|
| 3 | // File : SEC_layout.cxx // |
|---|
| 4 | // Purpose : layout size and positions of structure // |
|---|
| 5 | // // |
|---|
| 6 | // Coded by Ralf Westram (coder@reallysoft.de) in August 2007 // |
|---|
| 7 | // Institute of Microbiology (Technical University Munich) // |
|---|
| 8 | // http://www.arb-home.de/ // |
|---|
| 9 | // // |
|---|
| 10 | // =============================================================== // |
|---|
| 11 | |
|---|
| 12 | #include <algorithm> |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | #include "SEC_root.hxx" |
|---|
| 16 | #include "SEC_iter.hxx" |
|---|
| 17 | |
|---|
| 18 | using namespace std; |
|---|
| 19 | |
|---|
| 20 | const Angle& SEC_oriented::calc_abs_angle() const { |
|---|
| 21 | sec_assert(!abs_angle_valid); |
|---|
| 22 | |
|---|
| 23 | const SEC_base *previous = parent(); |
|---|
| 24 | if (previous) { |
|---|
| 25 | #if defined(DEBUG) |
|---|
| 26 | static int avoid_deep_recursion = 0; |
|---|
| 27 | avoid_deep_recursion++; |
|---|
| 28 | sec_assert(avoid_deep_recursion<1000); // looks like a bug |
|---|
| 29 | #endif // DEBUG |
|---|
| 30 | |
|---|
| 31 | abs_angle = previous->get_abs_angle()+rel_angle; |
|---|
| 32 | |
|---|
| 33 | #if defined(DEBUG) |
|---|
| 34 | avoid_deep_recursion--; |
|---|
| 35 | #endif // DEBUG |
|---|
| 36 | } |
|---|
| 37 | else { // no parent = root loop |
|---|
| 38 | abs_angle = rel_angle; |
|---|
| 39 | } |
|---|
| 40 | abs_angle_valid = true; |
|---|
| 41 | |
|---|
| 42 | return abs_angle; |
|---|
| 43 | } |
|---|
| 44 | const Angle& SEC_oriented::calc_rel_angle() { |
|---|
| 45 | const SEC_base *previous = parent(); |
|---|
| 46 | if (previous) { |
|---|
| 47 | rel_angle = abs_angle - previous->get_abs_angle(); |
|---|
| 48 | } |
|---|
| 49 | else { |
|---|
| 50 | rel_angle = abs_angle; |
|---|
| 51 | } |
|---|
| 52 | abs_angle_valid = true; |
|---|
| 53 | |
|---|
| 54 | return rel_angle; |
|---|
| 55 | } |
|---|
| 56 | |
|---|
| 57 | // ------------------------------------ |
|---|
| 58 | // calculate size of structure |
|---|
| 59 | // ------------------------------------ |
|---|
| 60 | |
|---|
| 61 | void SEC_segment::calculate_segment_size() { |
|---|
| 62 | alpha = ((get_region()->get_base_count()+1) / loop->get_circumferance()) * (2*M_PI); |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | void SEC_loop::compute_circumferance(void) { // Calculates the circumferance of the loop by counting the bases of the loop |
|---|
| 66 | SEC_root *sroot = get_root(); |
|---|
| 67 | double dbs = sroot->display_params().distance_between_strands; |
|---|
| 68 | |
|---|
| 69 | Circumferance = 0; |
|---|
| 70 | for (SEC_segment_iterator seg(this); seg; ++seg) { |
|---|
| 71 | SEC_region *reg = seg->get_region(); |
|---|
| 72 | reg->update_base_count(sroot); |
|---|
| 73 | Circumferance += reg->get_base_count() + 1 + dbs; |
|---|
| 74 | } |
|---|
| 75 | } |
|---|
| 76 | |
|---|
| 77 | void SEC_loop::compute_radius(void) { |
|---|
| 78 | compute_circumferance(); |
|---|
| 79 | setStandardSize(Circumferance / (2 * M_PI)); |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | void SEC_loop::calculate_loop_size() { |
|---|
| 83 | compute_radius(); |
|---|
| 84 | |
|---|
| 85 | for (SEC_segment_iterator seg(this); seg; ++seg) { |
|---|
| 86 | seg->calculate_segment_size(); |
|---|
| 87 | SEC_helix_strand *strand = seg->get_next_strand(); |
|---|
| 88 | if (strand->isRootsideFixpoint()) { // for all strands pointing away from loop |
|---|
| 89 | strand->get_helix()->calculate_helix_size(); |
|---|
| 90 | } |
|---|
| 91 | } |
|---|
| 92 | } |
|---|
| 93 | |
|---|
| 94 | void SEC_helix::calculate_helix_size() { |
|---|
| 95 | SEC_region *reg1 = strandToRoot()->get_region(); |
|---|
| 96 | SEC_region *reg2 = strandToOutside()->get_region(); |
|---|
| 97 | SEC_root *sroot = get_root(); |
|---|
| 98 | |
|---|
| 99 | reg1->update_base_count(sroot); |
|---|
| 100 | reg2->update_base_count(sroot); |
|---|
| 101 | |
|---|
| 102 | reg1->align_helix_strands(sroot, reg2); // aligns both strands |
|---|
| 103 | |
|---|
| 104 | base_length = max(reg1->get_base_count(), reg2->get_base_count()); |
|---|
| 105 | if (base_length == 0) { |
|---|
| 106 | #if defined(DEBUG) |
|---|
| 107 | printf("Helix w/o size faking length=1\n"); |
|---|
| 108 | #endif // DEBUG |
|---|
| 109 | base_length = 1; |
|---|
| 110 | } |
|---|
| 111 | setStandardSize(base_length-1); |
|---|
| 112 | |
|---|
| 113 | strandToRoot()->get_origin_loop()->calculate_loop_size(); |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | void SEC_root::calculate_size() { |
|---|
| 117 | SEC_loop *rootLoop = get_root_loop(); |
|---|
| 118 | if (rootLoop) rootLoop->calculate_loop_size(); |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | // ------------------------------------------- |
|---|
| 122 | // calculate coordinates of structure |
|---|
| 123 | // ------------------------------------------- |
|---|
| 124 | |
|---|
| 125 | void SEC_segment::calculate_segment_coordinates(const Position& start, const Position& end) { |
|---|
| 126 | // start is rightAttach of previous strand, end is leftAttach of next strand. |
|---|
| 127 | // both strands are already correct. |
|---|
| 128 | |
|---|
| 129 | const Position& loopCenter = loop->get_center(); |
|---|
| 130 | |
|---|
| 131 | Vector start_center(start, loopCenter); |
|---|
| 132 | Vector end_center(end, loopCenter); |
|---|
| 133 | |
|---|
| 134 | double radius = loop->drawnSize(); |
|---|
| 135 | |
|---|
| 136 | start_center.normalize() *= radius; |
|---|
| 137 | end_center.normalize() *= radius; |
|---|
| 138 | |
|---|
| 139 | center1 = start+start_center; |
|---|
| 140 | center2 = end+end_center; |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | void SEC_loop::calculate_loop_coordinates() { |
|---|
| 144 | // assumes the fixpoint helix and loop-center are correct |
|---|
| 145 | SEC_helix *fixpoint_helix = get_fixpoint_helix(); |
|---|
| 146 | SEC_helix_strand *strand_away = fixpoint_helix->strandAwayFrom(this); |
|---|
| 147 | const Position& loop_fixpoint = strand_away->get_fixpoint(); |
|---|
| 148 | |
|---|
| 149 | Angle current(center, loop_fixpoint); |
|---|
| 150 | |
|---|
| 151 | double dbs = get_root()->display_params().distance_between_strands; |
|---|
| 152 | double angle_between_strands = ( dbs / Circumferance) * (2*M_PI); //angle between two strands |
|---|
| 153 | |
|---|
| 154 | SEC_segment *seg = strand_away->get_next_segment(); |
|---|
| 155 | SEC_helix_strand *pstrand = strand_away; |
|---|
| 156 | |
|---|
| 157 | #if defined(DEBUG) |
|---|
| 158 | static int avoid_deep_recursion = 0; |
|---|
| 159 | avoid_deep_recursion++; |
|---|
| 160 | sec_assert(avoid_deep_recursion<500); // structure with more than 500 loops ? Sure ? |
|---|
| 161 | #endif // DEBUG |
|---|
| 162 | |
|---|
| 163 | while (seg) { |
|---|
| 164 | SEC_helix_strand *strand = seg->get_next_strand(); |
|---|
| 165 | SEC_segment *next_seg = 0; |
|---|
| 166 | |
|---|
| 167 | if (strand != strand_away) { |
|---|
| 168 | current += seg->get_alpha()+angle_between_strands; |
|---|
| 169 | strand->setFixpoint(center + current.normal()*drawnSize()); |
|---|
| 170 | strand->get_helix()->calculate_helix_coordinates(); |
|---|
| 171 | |
|---|
| 172 | next_seg = strand->get_next_segment(); |
|---|
| 173 | } |
|---|
| 174 | |
|---|
| 175 | seg->calculate_segment_coordinates(pstrand->rightAttachPoint(), strand->leftAttachPoint()); |
|---|
| 176 | |
|---|
| 177 | pstrand = strand; |
|---|
| 178 | seg = next_seg; |
|---|
| 179 | } |
|---|
| 180 | |
|---|
| 181 | #if defined(DEBUG) |
|---|
| 182 | avoid_deep_recursion--; |
|---|
| 183 | #endif // DEBUG |
|---|
| 184 | |
|---|
| 185 | } |
|---|
| 186 | |
|---|
| 187 | void SEC_helix::calculate_helix_coordinates() { |
|---|
| 188 | // assumes the rootside fixpoint and the rootside loop-center are correct |
|---|
| 189 | SEC_helix_strand *strand1 = strandToOutside(); |
|---|
| 190 | const Position& fix1 = strand1->get_fixpoint(); |
|---|
| 191 | |
|---|
| 192 | const Angle& loopAngle = strand1->get_origin_loop()->get_abs_angle(); |
|---|
| 193 | Angle strandAngle = loopAngle+get_rel_angle(); |
|---|
| 194 | |
|---|
| 195 | Position fix2 = fix1 + strandAngle.normal()*drawnSize(); |
|---|
| 196 | SEC_helix_strand *strand2 = strand1->get_other_strand(); |
|---|
| 197 | strand2->setFixpoint(fix2); |
|---|
| 198 | |
|---|
| 199 | // calculate attachment points |
|---|
| 200 | double dbs = get_root()->display_params().distance_between_strands; |
|---|
| 201 | Vector fix1_rAttach = strandAngle.normal() * (dbs * 0.5); |
|---|
| 202 | fix1_rAttach.rotate90deg(); |
|---|
| 203 | |
|---|
| 204 | strand1->setAttachPoints(fix1-fix1_rAttach, fix1+fix1_rAttach); |
|---|
| 205 | strand2->setAttachPoints(fix2+fix1_rAttach, fix2-fix1_rAttach); |
|---|
| 206 | |
|---|
| 207 | // calculate loop-center of outside loop |
|---|
| 208 | SEC_loop *nextLoop = outsideLoop(); |
|---|
| 209 | Angle fix2_center = strandAngle + nextLoop->get_rel_angle(); |
|---|
| 210 | Position loopCenter = fix2 + fix2_center.normal()*nextLoop->drawnSize(); |
|---|
| 211 | |
|---|
| 212 | nextLoop->set_center(loopCenter); |
|---|
| 213 | nextLoop->calculate_loop_coordinates(); |
|---|
| 214 | } |
|---|
| 215 | |
|---|
| 216 | void SEC_root::calculate_coordinates() { |
|---|
| 217 | SEC_loop *rootLoop = get_root_loop(); |
|---|
| 218 | |
|---|
| 219 | if (rootLoop) { |
|---|
| 220 | rootLoop->set_center(Origin); |
|---|
| 221 | rootLoop->mark_angle_absolute(); // mark angle as absolute |
|---|
| 222 | |
|---|
| 223 | SEC_helix *primary_helix = rootLoop->get_fixpoint_helix(); |
|---|
| 224 | |
|---|
| 225 | // calculate the coordinates of the primary helix |
|---|
| 226 | const Angle& loopAngle = rootLoop->get_abs_angle(); |
|---|
| 227 | Position rootside = Origin + loopAngle.normal() * rootLoop->drawnSize(); |
|---|
| 228 | Position outside = rootside + Angle(loopAngle + primary_helix->get_abs_angle()).normal() * primary_helix->drawnSize(); |
|---|
| 229 | |
|---|
| 230 | primary_helix->setFixpoints(rootside, outside); |
|---|
| 231 | primary_helix->calculate_helix_coordinates(); |
|---|
| 232 | |
|---|
| 233 | rootLoop->calculate_loop_coordinates(); // does not calculate for the primary helix |
|---|
| 234 | } |
|---|
| 235 | } |
|---|
| 236 | |
|---|
| 237 | // --------------------------- |
|---|
| 238 | // angle invalidation |
|---|
| 239 | // --------------------------- |
|---|
| 240 | |
|---|
| 241 | void SEC_oriented::invalidate() { |
|---|
| 242 | if (abs_angle_valid) { // skip recursion if already invalidated |
|---|
| 243 | invalidate_sub_angles(); |
|---|
| 244 | abs_angle_valid = false; |
|---|
| 245 | } |
|---|
| 246 | } |
|---|
| 247 | |
|---|
| 248 | void SEC_helix::invalidate_sub_angles() { |
|---|
| 249 | SEC_loop *outLoop = outsideLoop(); // does not exist during read |
|---|
| 250 | if (outLoop) { |
|---|
| 251 | outLoop->invalidate(); |
|---|
| 252 | } |
|---|
| 253 | else { |
|---|
| 254 | sec_assert(get_root()->under_construction()); // loop missing and structure |
|---|
| 255 | } |
|---|
| 256 | } |
|---|
| 257 | |
|---|
| 258 | void SEC_loop::invalidate_sub_angles() { |
|---|
| 259 | for (SEC_strand_iterator strand(this); strand; ++strand) { |
|---|
| 260 | if (strand->isRootsideFixpoint()) { // outgoing strand |
|---|
| 261 | strand->get_helix()->invalidate(); |
|---|
| 262 | } |
|---|
| 263 | } |
|---|
| 264 | } |
|---|
| 265 | |
|---|
| 266 | // -------------------- |
|---|
| 267 | // count bases |
|---|
| 268 | // -------------------- |
|---|
| 269 | |
|---|
| 270 | void SEC_region::invalidate_base_count() { |
|---|
| 271 | delete [] abspos_array; |
|---|
| 272 | abspos_array = 0; |
|---|
| 273 | #if defined(DEBUG) |
|---|
| 274 | abspos_array_size = 0; |
|---|
| 275 | #endif // DEBUG |
|---|
| 276 | |
|---|
| 277 | baseCount = -1; |
|---|
| 278 | } |
|---|
| 279 | |
|---|
| 280 | void SEC_region::create_abspos_array(const int *static_array) { |
|---|
| 281 | sec_assert(abspos_array == 0); |
|---|
| 282 | sec_assert(baseCount >= 0); |
|---|
| 283 | |
|---|
| 284 | if (baseCount>0) { |
|---|
| 285 | abspos_array = new int[baseCount]; |
|---|
| 286 | memcpy(abspos_array, static_array, baseCount*sizeof(*static_array)); |
|---|
| 287 | } |
|---|
| 288 | #if defined(DEBUG) |
|---|
| 289 | abspos_array_size = baseCount; |
|---|
| 290 | #endif // DEBUG |
|---|
| 291 | } |
|---|
| 292 | |
|---|
| 293 | void SEC_region::count_bases(SEC_root *root) { |
|---|
| 294 | invalidate_base_count(); |
|---|
| 295 | |
|---|
| 296 | bool is_endings_seg = false; |
|---|
| 297 | int max_index = root->max_index(); |
|---|
| 298 | |
|---|
| 299 | sec_assert(sequence_start <= max_index); |
|---|
| 300 | sec_assert(sequence_end <= (max_index+1)); |
|---|
| 301 | |
|---|
| 302 | int size; |
|---|
| 303 | int last; |
|---|
| 304 | |
|---|
| 305 | if (sequence_end < sequence_start) { // if this is the "endings-segment" |
|---|
| 306 | size = (max_index - sequence_start + 1) + sequence_end; |
|---|
| 307 | last = max_index; |
|---|
| 308 | is_endings_seg = true; |
|---|
| 309 | } |
|---|
| 310 | else { |
|---|
| 311 | size = sequence_end - sequence_start; |
|---|
| 312 | last = sequence_end-1; |
|---|
| 313 | } |
|---|
| 314 | |
|---|
| 315 | sec_assert(root->get_db()->canDisplay()); |
|---|
| 316 | static int *static_array = NULL; |
|---|
| 317 | static int sizeof_static_array = 0; |
|---|
| 318 | |
|---|
| 319 | if (size > sizeof_static_array) { |
|---|
| 320 | delete [] static_array; |
|---|
| 321 | static_array = new int[size]; |
|---|
| 322 | sizeof_static_array = size; |
|---|
| 323 | } |
|---|
| 324 | |
|---|
| 325 | baseCount = 0; |
|---|
| 326 | |
|---|
| 327 | int i; |
|---|
| 328 | for (i = sequence_start; i <= last; ++i) { |
|---|
| 329 | if (root->shallDisplayPosition(i)) { |
|---|
| 330 | sec_assert(baseCount < size); |
|---|
| 331 | static_array[baseCount++] = i; |
|---|
| 332 | } |
|---|
| 333 | } |
|---|
| 334 | |
|---|
| 335 | if (is_endings_seg) { |
|---|
| 336 | for (i = 0; i < sequence_end; ++i) { |
|---|
| 337 | if (root->shallDisplayPosition(i)) { |
|---|
| 338 | sec_assert(baseCount < size); |
|---|
| 339 | static_array[baseCount++] = i; |
|---|
| 340 | } |
|---|
| 341 | } |
|---|
| 342 | } |
|---|
| 343 | |
|---|
| 344 | sec_assert(baseCount <= size); |
|---|
| 345 | create_abspos_array(static_array); |
|---|
| 346 | |
|---|
| 347 | sec_assert(baseCount <= size); |
|---|
| 348 | } |
|---|
| 349 | |
|---|
| 350 | |
|---|
| 351 | |
|---|