source: branches/profile/SECEDIT/SEC_layout.cxx

Last change on this file was 11060, checked in by westram, 6 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.4 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
60void SEC_segment::calculate_segment_size() {
61    alpha = ((get_region()->get_base_count()+1) / loop->get_circumference()) * (2*M_PI);
62}
63
64void SEC_loop::compute_circumference() {      // Calculates the circumference of the loop by counting the bases of the loop
65    SEC_root *sroot = get_root();
66    double    dbs   = sroot->display_params().distance_between_strands;
67
68    Circumference = 0;
69    for (SEC_segment_iterator seg(this); seg; ++seg) {
70        SEC_region *reg = seg->get_region();
71        reg->update_base_count(sroot);
72        Circumference += reg->get_base_count() + 1 + dbs;
73    }
74}
75
76void SEC_loop::compute_radius() {
77    compute_circumference();
78    setStandardSize(Circumference / (2 * M_PI));
79}
80
81void SEC_loop::calculate_loop_size() {
82    compute_radius();
83
84    for (SEC_segment_iterator seg(this); seg; ++seg) {
85        seg->calculate_segment_size();
86        SEC_helix_strand *strand = seg->get_next_strand();
87        if (strand->isRootsideFixpoint()) { // for all strands pointing away from loop
88            strand->get_helix()->calculate_helix_size();
89        }
90    }
91}
92
93void SEC_helix::calculate_helix_size() {
94    SEC_region *reg1  = strandToRoot()->get_region();
95    SEC_region *reg2  = strandToOutside()->get_region();
96    SEC_root   *sroot = get_root();
97
98    reg1->update_base_count(sroot);
99    reg2->update_base_count(sroot);
100
101    reg1->align_helix_strands(sroot, reg2); // aligns both strands
102
103    base_length = max(reg1->get_base_count(), reg2->get_base_count());
104    if (base_length == 0) {
105#if defined(DEBUG)
106        printf("Helix w/o size faking length=1\n");
107#endif // DEBUG
108        base_length = 1;
109    }
110    setStandardSize(base_length-1);
111
112    strandToRoot()->get_origin_loop()->calculate_loop_size();
113}
114
115void SEC_root::calculate_size() {
116    SEC_loop *rootLoop = get_root_loop();
117    if (rootLoop) rootLoop->calculate_loop_size();
118}
119
120// --------------------------------------------
121//      calculate coordinates of structure
122
123void SEC_segment::calculate_segment_coordinates(const Position& start, const Position& end) {
124    // start is rightAttach of previous strand, end is leftAttach of next strand.
125    // both strands are already correct.
126
127    const Position& loopCenter = loop->get_center();
128
129    Vector start_center(start, loopCenter);
130    Vector end_center(end, loopCenter);
131
132    double radius = loop->drawnSize();
133
134    start_center.normalize() *= radius;
135    end_center.normalize()   *= radius;
136
137    center1 = start+start_center;
138    center2 = end+end_center;
139}
140
141void SEC_loop::calculate_loop_coordinates() {
142    // assumes the fixpoint helix and loop-center are correct
143    SEC_helix        *fixpoint_helix = get_fixpoint_helix();
144    SEC_helix_strand *strand_away    = fixpoint_helix->strandAwayFrom(this);
145    const Position&   loop_fixpoint  = strand_away->get_fixpoint();
146
147    Angle current(center, loop_fixpoint);
148
149    double dbs                   = get_root()->display_params().distance_between_strands;
150    double angle_between_strands = (dbs / Circumference) * (2*M_PI);  // angle between two strands
151
152    SEC_segment      *seg     = strand_away->get_next_segment();
153    SEC_helix_strand *pstrand = strand_away;
154
155#if defined(DEBUG)
156    static int avoid_deep_recursion = 0;
157    avoid_deep_recursion++;
158    sec_assert(avoid_deep_recursion<500); // structure with more than 500 loops ? Sure ?
159#endif // DEBUG
160
161    while (seg) {
162        SEC_helix_strand *strand   = seg->get_next_strand();
163        SEC_segment      *next_seg = 0;
164
165        if (strand != strand_away) {
166            current += Angle(seg->get_alpha()+angle_between_strands);
167            strand->setFixpoint(center + current.normal()*drawnSize());
168            strand->get_helix()->calculate_helix_coordinates();
169
170            next_seg = strand->get_next_segment();
171        }
172
173        seg->calculate_segment_coordinates(pstrand->rightAttachPoint(), strand->leftAttachPoint());
174
175        pstrand = strand;
176        seg     = next_seg;
177    }
178
179#if defined(DEBUG)
180    avoid_deep_recursion--;
181#endif // DEBUG
182
183}
184
185void SEC_helix::calculate_helix_coordinates() {
186    // assumes the rootside fixpoint and the rootside loop-center are correct
187    SEC_helix_strand *strand1 = strandToOutside();
188    const Position&   fix1    = strand1->get_fixpoint();
189
190    const Angle& loopAngle   = strand1->get_origin_loop()->get_abs_angle();
191    Angle        strandAngle = loopAngle+get_rel_angle();
192
193    Position          fix2    = fix1 + strandAngle.normal()*drawnSize();
194    SEC_helix_strand *strand2 = strand1->get_other_strand();
195    strand2->setFixpoint(fix2);
196
197    // calculate attachment points
198    double dbs          = get_root()->display_params().distance_between_strands;
199    Vector fix1_rAttach = strandAngle.normal() * (dbs * 0.5);
200    fix1_rAttach.rotate90deg();
201
202    strand1->setAttachPoints(fix1-fix1_rAttach, fix1+fix1_rAttach);
203    strand2->setAttachPoints(fix2+fix1_rAttach, fix2-fix1_rAttach);
204
205    // calculate loop-center of outside loop
206    SEC_loop *nextLoop    = outsideLoop();
207    Angle     fix2_center = strandAngle + nextLoop->get_rel_angle();
208    Position  loopCenter  = fix2 + fix2_center.normal()*nextLoop->drawnSize();
209
210    nextLoop->set_center(loopCenter);
211    nextLoop->calculate_loop_coordinates();
212}
213
214void SEC_root::calculate_coordinates() {
215    SEC_loop *rootLoop = get_root_loop();
216
217    if (rootLoop) {
218        rootLoop->set_center(Origin);
219        rootLoop->mark_angle_absolute(); // mark angle as absolute
220
221        SEC_helix *primary_helix = rootLoop->get_fixpoint_helix();
222
223        // calculate the coordinates of the primary helix
224        const Angle& loopAngle = rootLoop->get_abs_angle();
225        Position     rootside  = Origin + loopAngle.normal() * rootLoop->drawnSize();
226        Position     outside   = rootside + Angle(loopAngle + primary_helix->get_abs_angle()).normal() * primary_helix->drawnSize();
227
228        primary_helix->setFixpoints(rootside, outside);
229        primary_helix->calculate_helix_coordinates();
230
231        rootLoop->calculate_loop_coordinates(); // does not calculate for the primary helix
232    }
233}
234
235// ----------------------------
236//      angle invalidation
237
238void SEC_oriented::invalidate() {
239    if (abs_angle_valid) { // skip recursion if already invalidated
240        invalidate_sub_angles();
241        abs_angle_valid = false;
242    }
243}
244
245void SEC_helix::invalidate_sub_angles() {
246    SEC_loop *outLoop = outsideLoop(); // does not exist during read
247    if (outLoop) {
248        outLoop->invalidate();
249    }
250    else {
251        sec_assert(get_root()->under_construction()); // loop missing and structure
252    }
253}
254
255void SEC_loop::invalidate_sub_angles() {
256    for (SEC_strand_iterator strand(this); strand; ++strand) {
257        if (strand->isRootsideFixpoint()) { // outgoing strand
258            strand->get_helix()->invalidate();
259        }
260    }
261}
262
263// ---------------------
264//      count bases
265
266void SEC_region::invalidate_base_count() {
267    delete [] abspos_array;
268    abspos_array      = 0;
269#if defined(ASSERTION_USED)
270    abspos_array_size = 0;
271#endif // ASSERTION_USED
272
273    baseCount = -1;
274}
275
276void SEC_region::create_abspos_array(const int *static_array) {
277    sec_assert(abspos_array == 0);
278    sec_assert(baseCount >= 0);
279
280    if (baseCount>0) {
281        abspos_array = new int[baseCount];
282        memcpy(abspos_array, static_array, baseCount*sizeof(*static_array));
283    }
284#if defined(ASSERTION_USED)
285    abspos_array_size = baseCount;
286#endif // ASSERTION_USED
287}
288
289void SEC_region::count_bases(SEC_root *root) {
290    invalidate_base_count();
291
292    bool is_endings_seg = false;
293    int  max_index      = root->max_index();
294
295    sec_assert(sequence_start <= max_index);
296    sec_assert(sequence_end <= (max_index+1));
297
298    int size;
299    int last;
300
301    if (sequence_end < sequence_start) { // if this is the "endings-segment"
302        size           = (max_index - sequence_start + 1) + sequence_end;
303        last           = max_index;
304        is_endings_seg = true;
305    }
306    else {
307        size = sequence_end - sequence_start;
308        last = sequence_end-1;
309    }
310
311    sec_assert(root->get_db()->canDisplay());
312    static int *static_array        = NULL;
313    static int  sizeof_static_array = 0;
314
315    if (size > sizeof_static_array) {
316        delete [] static_array;
317        static_array = new int[size];
318        sizeof_static_array = size;
319    }
320
321    baseCount = 0;
322
323    int i;
324    for (i = sequence_start; i <= last; ++i) {
325        if (root->shallDisplayPosition(i)) {
326            sec_assert(baseCount < size);
327            static_array[baseCount++] = i;
328        }
329    }
330
331    if (is_endings_seg) {
332        for (i = 0; i < sequence_end; ++i) {
333            if (root->shallDisplayPosition(i)) {
334                sec_assert(baseCount < size);
335                static_array[baseCount++] = i;
336            }
337        }
338    }
339
340    sec_assert(baseCount <= size);
341    create_abspos_array(static_array);
342
343    sec_assert(baseCount <= size);
344}
345
346
347
Note: See TracBrowser for help on using the repository browser.