source: tags/arb_5.5/SECEDIT/SEC_layout.cxx

Last change on this file was 5675, checked in by westram, 15 years ago
  • removed automatic timestamps (the best they were good for, were vc-conflicts)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.5 KB
Line 
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
18using namespace std;
19
20const 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}
44const 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
61void SEC_segment::calculate_segment_size() {
62    alpha = ((get_region()->get_base_count()+1) / loop->get_circumferance()) * (2*M_PI);
63}
64
65void 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
77void SEC_loop::compute_radius(void) {
78    compute_circumferance();
79    setStandardSize(Circumferance / (2 * M_PI));
80}
81
82void 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
94void 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
116void 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
125void 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
143void 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
187void 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
216void 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
241void 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
248void 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
258void 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
270void 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
280void 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
293void 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
Note: See TracBrowser for help on using the repository browser.