ARB
SEC_layout.cxx
Go to the documentation of this file.
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 void SEC_segment::calculate_segment_size() {
61  alpha = ((get_region()->get_base_count()+1) / loop->get_circumference()) * (2*M_PI);
62 }
63 
64 void 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 
76 void SEC_loop::compute_radius() {
77  compute_circumference();
78  setStandardSize(Circumference / (2 * M_PI));
79 }
80 
81 void 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 
93 void 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 
115 void 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 
123 void 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 
141 void 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 = NULp;
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 
185 void 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 
214 void 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 
239  if (abs_angle_valid) { // skip recursion if already invalidated
240  invalidate_sub_angles();
241  abs_angle_valid = false;
242  }
243 }
244 
245 void 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 
255 void 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 
267  delete [] abspos_array;
268  abspos_array = NULp;
269 #if defined(ASSERTION_USED)
270  abspos_array_size = 0;
271 #endif // ASSERTION_USED
272 
273  baseCount = -1;
274 }
275 
276 void SEC_region::create_abspos_array(const int *static_array) {
277  sec_assert(!abspos_array);
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 
289 void 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 = NULp;
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 
int get_base_count() const
Definition: SEC_root.hxx:110
void invalidate_base_count()
Definition: SEC_layout.cxx:266
void align_helix_strands(SEC_root *root, SEC_region *other_region)
Definition: SEC_paint.cxx:1125
Vector & rotate90deg()
void update_base_count(SEC_root *root)
Definition: SEC_root.hxx:103
const SEC_db_interface * get_db() const
Definition: SEC_root.hxx:747
size_t max_index()
Definition: SEC_root.hxx:830
const SEC_displayParams & display_params() const
Definition: SEC_root.hxx:761
STL namespace.
const Vector & normal() const
#define M_PI
const Angle & get_abs_angle() const
Definition: SEC_root.hxx:222
static HelixNrInfo * start
void invalidate()
Definition: SEC_layout.cxx:238
double distance_between_strands
Definition: SEC_root.hxx:636
bool shallDisplayPosition(int abspos) const
Definition: SEC_root.hxx:821
bool canDisplay() const
Definition: SEC_db.hxx:140
#define NULp
Definition: cxxforward.h:116
const Position Origin
#define sec_assert(cond)
Definition: SEC_defs.hxx:19
#define max(a, b)
Definition: f2c.h:154