ARB
SEC_paint.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : SEC_paint.cxx //
4 // Purpose : //
5 // //
6 // Institute of Microbiology (Technical University Munich) //
7 // http://www.arb-home.de/ //
8 // //
9 // =============================================================== //
10 
11 #include "SEC_root.hxx"
12 #include "SEC_graphic.hxx"
13 #include "SEC_iter.hxx"
14 #include "SEC_drawn_pos.hxx"
15 #include "SEC_bonddef.hxx"
16 #include "SEC_toggle.hxx"
17 
18 #include <aw_msg.hxx>
19 #include <iupac.h>
20 
21 #include <ed4_extern.hxx>
22 
23 #include <arb_defs.h>
24 
25 #include <iostream>
26 #include <sstream>
27 
28 using namespace std;
29 
30 // -------------------
31 // Debugging
32 
33 #if defined(ASSERTION_USED)
34 
35 inline bool valid_cb_params(AW_CL cd1, AW_CL cd2) {
36  return cd1 == 0 || cd2 != -1;
37 }
38 inline bool valid_cb_params(AW_device *device) {
39  const AW_click_cd *cd = device->get_click_cd();
40  return valid_cb_params(cd->get_cd1(), cd->get_cd2());
41 }
42 
43 #endif
44 
45 #if defined(DEBUG)
46 // #define PAINT_REGION_INDEX // // paint region-internal index next to base
47 
48 static void paintDebugInfo(AW_device *device, int color, const Position& pos, const char *txt) {
49  sec_assert(valid_cb_params(device));
50  device->circle(color, AW::FillStyle::SOLID, pos.xpos(), pos.ypos(), 0.06, 0.06);
51  device->text(SEC_GC_DEFAULT, txt, pos.xpos(), pos.ypos(), 0, AW_SCREEN);
52 }
53 static void paintStrandDebugInfo(AW_device *device, int color, SEC_helix_strand *strand) {
54  AW_click_cd cd(device, strand->self(), strand->rightAttachAbspos()); paintDebugInfo(device, color, strand->rightAttachPoint(), "RAP");
55  cd.set_cd2(strand->leftAttachAbspos()); paintDebugInfo(device, color, strand->leftAttachPoint(), "LAP");
56  cd.set_cd2(strand->startAttachAbspos()); paintDebugInfo(device, color, strand->get_fixpoint(), strand->isRootsideFixpoint() ? "RFP" : "FP");
57 }
58 
59 #endif // DEBUG
60 
61 // -------------------
62 // PaintData
63 
64 class PaintData {
65  int gc_edit4_to_secedit[ED4_G_DRAG+1]; // GC translation table (EDIT4 -> SECEDIT)
66  int line_property_gc[SEC_GC_LAST_DATA+1][SEC_GC_LAST_DATA+1]; // of two GCs, which is responsible for line properties
67 
68 public:
70  int gc;
71 
72  // GC translation (EDIT4->SECEDIT)
73  for (gc = 0; gc <= ED4_G_DRAG; gc++) {
74  gc_edit4_to_secedit[gc] = -1; // invalid
75  }
76  for (gc = ED4_G_SBACK_0; gc <= ED4_G_SBACK_8; gc++) { // IRRELEVANT_LOOP
77  gc_edit4_to_secedit[gc] = gc-ED4_G_SBACK_0+SEC_GC_SBACK_0;
78  }
79  for (gc = ED4_G_CBACK_0; gc <= ED4_G_CBACK_9; gc++) { // IRRELEVANT_LOOP
80  gc_edit4_to_secedit[gc] = gc-ED4_G_CBACK_0+SEC_GC_CBACK_0;
81  }
82 
83  // calc line property GCs
84  for (gc = SEC_GC_FIRST_DATA; gc <= SEC_GC_LAST_DATA; gc++) {
85  for (int gc2 = SEC_GC_FIRST_DATA; gc <= SEC_GC_LAST_DATA; gc++) {
86  int prop_gc;
87  if (gc == gc2) {
88  prop_gc = gc;
89  }
90  else {
91  if (gc == SEC_GC_LOOP || gc2 == SEC_GC_LOOP) {
92  prop_gc = SEC_GC_LOOP; // use loop-properties in loop and at loop-helix-transition
93  }
94  else if (gc == SEC_GC_NHELIX || gc2 == SEC_GC_NHELIX) {
95  prop_gc = SEC_GC_NHELIX; // use nhelix-properties in nhelix and at helix-nhelix-transition
96  }
97  else {
98  prop_gc = SEC_GC_HELIX; // use helix-properties in helix
99  }
100  }
101  line_property_gc[gc][gc2] = prop_gc;
102  }
103  }
104  }
105 
106  int convert_BackgroundGC(int edit4_gc) const {
107  // returns -1 if edit4_gc is invalid
108  sec_assert(edit4_gc >= 0 && edit4_gc <= ED4_G_DRAG);
109  return gc_edit4_to_secedit[edit4_gc];
110  }
111 
112  int get_linePropertyGC(int gc1, int gc2) {
113  // of the GCs of two positions, it returns the GC which is
114  // defining the properties for the background painted in-between the two positions
117  return line_property_gc[gc1][gc2];
118  }
119 };
120 
122 
123 // ---------------------
124 // Annotations
125 
127  const Position& pos, const Position& left, const Position& right,
128  double noteDistance, const char *text,
129  bool lineToPos, bool linesToLeftRight, bool boxText)
130 {
131  // draw annotation to explicit position 'pos' (annotation is drawn "above" the line left->right)
132  // The distance between pos and note is determined by
133  // * textsize (minimal half textsize/boxsize) and
134  // * the given 'noteDistance'
135  // lineToPos == true -> draw a line from text to 'pos'
136  // linesToLeftRight == true -> draw lines from text to 'left' and 'right'
137  // boxText == true -> draw a box around text
138 
139  sec_assert(valid_cb_params(device));
140 
141  Vector strand(left, right);
142  Angle pos2note(strand);
143  pos2note.rotate270deg();
144 
145  int fontgc = gc <= SEC_GC_LAST_FONT ? gc : SEC_GC_DEFAULT;
146  double half_charSize = center_char[fontgc].length();
147 
148  SizedCstr stext(text);
149 
150  // calculate textsize
151  AW_pos half_width = 0.5 * device->rtransform_size(device->get_string_size(gc, stext));
152  AW_pos half_height = center_char[fontgc].y();
153 
154  double note_distance = max(half_height, half_width) * (boxText ? 1.3 : 1.0);
155  note_distance = max(note_distance, noteDistance);
156 
157  Position note_center = pos + pos2note.normal()*note_distance;
158 
159  if (device->get_filter() & AW_PRINTER) {
160  boxText = false; // don't print/xfig-export boxes
161  }
162 
163  if (lineToPos || linesToLeftRight) {
164  device->set_line_attributes(gc, 1, AW_SOLID);
165 
166  if (lineToPos) {
167  Vector dist = pos2note.normal()*half_charSize;
168  device->line(gc, boxText ? note_center : note_center-dist, pos+dist);
169  }
170  if (linesToLeftRight) {
171  Vector out(pos, note_center);
172 
173  if (out.length()*2 >= strand.length()) { // short strands -> draw simple bracket
174  Vector toLeft(note_center, left);
175  Vector toRight(note_center, right);
176 
177  device->line(gc, boxText ? note_center : note_center+toLeft*(half_width/toLeft.length()),
178  left-toLeft*(half_charSize/toLeft.length()), AW_ALL_DEVICES_SCALED);
179  device->line(gc, boxText ? note_center : note_center+toRight*(half_width/toRight.length()),
180  right-toRight*(half_charSize/toRight.length()), AW_ALL_DEVICES_SCALED);
181  }
182  else {
183  Vector rightIndent = out;
184  rightIndent.rotate270deg();
185 
186  Position rightOut = right+out+rightIndent;
187  Position leftOut = left+out-rightIndent;
188 
189  Vector posPad = Vector(right, rightOut).set_length(half_charSize);
190  device->line(gc, right+posPad, rightOut);
191  posPad.rotate90deg();
192  device->line(gc, left+posPad, leftOut);
193 
194  if (boxText) {
195  device->line(gc, leftOut, rightOut);
196  }
197  else {
198  Vector rightTextPad(note_center, rightOut);
199  rightTextPad.set_length(half_width);
200 
201  device->line(gc, note_center+rightTextPad, rightOut);
202  device->line(gc, note_center-rightTextPad, leftOut);
203  }
204  }
205  }
206  }
207 
208  Vector center_textcorner(-half_width, half_height); // from center to lower left corner
209  Position textcorner = note_center+center_textcorner;
210 
211  if (boxText) {
212  Vector center_corner(-half_width-half_height*0.3, half_height*1.3); // box is 25% bigger than text
213  Rectangle box(note_center+center_corner, -2*center_corner);
214 
215  device->clear_part(box, -1);
216  device->box(gc, AW::FillStyle::EMPTY, box);
217  }
218 
219  device->text(gc, text, textcorner);
220 }
221 
222 void SEC_root::paintPosAnnotation(AW_device *device, int gc, size_t absPos, const char *text, bool lineToBase, bool boxText) {
223  // draw a annotation next to a base (only works after paint()).
224  // if nothing was drawn at absPos, annotate a position between previous and next drawn position.
225  // text == NULp -> draw absPos as number
226  // lineToBase == true -> draw a line to the base itself
227  // boxText == true -> draw a box around text
228 
229  size_t abs1, abs2;
230  const Position& pos1 = drawnPositions->drawn_before(absPos, &abs1);
231  const Position& pos2 = drawnPositions->drawn_after (absPos, &abs2);
232 
233  LineVector vec12(pos1, pos2);
234  Position mid12 = vec12.centroid();
235  Position pos;
236  {
237  const Position *posDrawn = drawnPositions->drawn_at(absPos);
238  if (posDrawn) { // absPos was drawn
239  pos = *posDrawn;
240  }
241  else { // absPos was not drawn -> use position in-between
242  pos = mid12;
243  }
244  }
245 
246  if (!text) text = GBS_global_string("%zu", absPos);
247 
248  AW_click_cd cd(device, 0, absPos);
249  paintAnnotation(device, gc, pos, pos1, pos2, vec12.length(), text, lineToBase, false, boxText);
250 }
251 
252 void SEC_root::paintEcoliPositions(AW_device *device) {
253  long abspos = db->ecoli()->rel_2_abs(0);
254  paintPosAnnotation(device, SEC_GC_ECOLI, size_t(abspos), "1", true, true);
255 
256  const BI_ecoli_ref *ecoli = db->ecoli();
257  for (size_t ep = bio2info(100); ep < (size_t)ecoli->base_count(); ep += 100) {
258  abspos = ecoli->rel_2_abs(ep);
259  paintPosAnnotation(device, SEC_GC_ECOLI, size_t(abspos), GBS_global_string("%i", info2bio(ep)), true, true);
260  }
261 }
262 
263 void SEC_root::paintHelixNumbers(AW_device *device) {
264  for (SEC_base_iterator elem(this); elem; ++elem) {
265  if (elem->getType() == SEC_HELIX) {
266  SEC_helix& helix = static_cast<SEC_helix&>(*elem);
267 
268  // paint helix number of right (3') helix strand
269  SEC_helix_strand *strand = helix.strandToRoot()->is3end() ? helix.strandToRoot() : helix.strandToOutside();
270 
271  int absPos = strand->startAttachAbspos();
272  const char *helixNr = helixNrAt(absPos);
273 
274  if (helixNr) {
275  if (helix.standardSize() == 0) { // helix with zero length (just one position on each strand)
276  paintPosAnnotation(device, SEC_GC_HELIX_NO,
277  strand->startAttachAbspos(), helixNr, true, true);
278  }
279  else {
280  const Position& start = strand->startAttachPoint();
281  const Position& end = strand->endAttachPoint();
282  Position helixCenter = centroid(start, end);
283 
284  AW_click_cd cd(device, strand->self(), absPos);
285  paintAnnotation(device, SEC_GC_HELIX_NO,
286  helixCenter, start, end,
287  // displayParams.distance_between_strands*2,
288  displayParams.distance_between_strands,
289  helixNr, false, true, true);
290  }
291  }
292  }
293  }
294 }
295 
296 
297 #if defined(PAINT_ABSOLUTE_POSITION)
298 void SEC_root::showSomeAbsolutePositions(AW_device *device) {
299  if (device->get_filter() != AW_SIZE) { // ignore for size calculation (@@@)
300  Rectangle screen = device->rtransform(Rectangle(device->get_area_size(), INCLUSIVE_OUTLINE));
301  Vector diag3 = screen.diagonal()/3;
302  Rectangle showInside(screen.upper_left_corner()+diag3*1.85, diag3);
303 
304  AW_click_cd cd(device, 0, -1);
305  device->box(SEC_GC_DEFAULT, AW::FillStyle::EMPTY, showInside);
306 
307  PosMap::const_iterator end = drawnPositions->end();
308  for (PosMap::const_iterator pos = drawnPositions->begin(); pos != end; ++pos) {
309  if (showInside.contains(pos->second)) {
310  paintPosAnnotation(device, SEC_GC_DEFAULT, pos->first, NULp, true, true);
311  }
312  }
313  }
314 }
315 #endif // PAINT_ABSOLUTE_POSITION
316 
317 void SEC_root::announce_base_position(int base_pos, const Position& draw_pos) {
318  drawnPositions->announce(base_pos, draw_pos);
319 }
321  if (!drawnPositions) drawnPositions = new SEC_drawn_positions;
322  drawnPositions->clear();
323 }
324 
325 void SEC_root::delete_announced_positions() {
326  delete drawnPositions;
327  drawnPositions = NULp;
328 }
329 
330 
331 // ----------------------------
332 // Paints CONSTRAINTS
333 
334 void SEC_helix_strand::paint_constraints(AW_device *device) {
335  double minS = helix_info->minSize();
336  double maxS = helix_info->maxSize();
337 
338  if (minS>0 || maxS>0) {
339  const Position& startP = startAttachPoint();
340  const Position& endP = endAttachPoint();
341 
342  bool drawMidLine = minS>0 && maxS>0;
343  Position minP = startP + Vector(startP, endP) * (drawMidLine ? minS/maxS : 0.5);
344 
345  AW_click_cd cd(device, self(), startAttachAbspos());
346  get_root()->paintAnnotation(device, SEC_GC_DEFAULT,
347  minP, startP, endP,
348  get_root()->display_params().distance_between_strands*2,
349  GBS_global_string("%.1f-%.1f", minS, maxS),
350  drawMidLine, true, true);
351  }
352 }
353 
354 void SEC_loop::paint_constraints(AW_device *device) {
355  int abspos = get_fixpoint_strand()->startAttachAbspos();
356 
357  double minS = minSize();
358  double maxS = maxSize();
359 
360  if (minS>0 || maxS>0) {
361  AW_click_cd cd(device, self(), abspos);
362 
363  if (minS>0) device->circle(SEC_GC_DEFAULT, AW::FillStyle::EMPTY, center, Vector(minS, minS));
364  if (maxS>0) device->circle(SEC_GC_DEFAULT, AW::FillStyle::EMPTY, center, Vector(maxS, maxS));
365 
366  device->text(SEC_GC_DEFAULT, GBS_global_string("%.1f-%.1f", minS, maxS), center+Vector(0, max(minS, maxS)/2), 0.5, AW_ALL_DEVICES_UNSCALED);
367  }
368 }
369 
370 // ---------------------------
371 // Background colors
372 
373 #if defined(WARN_TODO)
374 #warning move to SEC_db_interface
375 #endif
376 void SEC_root::cacheBackgroundColor() {
377  freenull(bg_color);
378 
379  int start = 0;
380  int len = db->length();
381  int end = len-1;
382 
383  ARB_alloc(bg_color, len);
384 
385  const char *bg_sai = displayParams.display_sai ? host().get_SAI_background(start, end) : NULp;
386  const char *bg_search = displayParams.display_search ? host().get_search_background(start, end) : NULp;
387 
388  if (bg_sai) {
389  if (bg_search) {
390  for (int i = start; i <= end; ++i) {
391  bg_color[i] = bg_search[i] ? bg_search[i] : bg_sai[i];
392  }
393  }
394  else memcpy(bg_color, bg_sai, len);
395  }
396  else {
397  if (bg_search) memcpy(bg_color, bg_search, len);
398  else memset(bg_color, 0, len);
399  }
400 }
401 
402 void SEC_root::paintBackgroundColor(AW_device *device, SEC_bgpaint_mode mode, const Position& p1, int color1, int gc1, const Position& p2, int color2, int gc2, int skel_gc) {
403  // paints background colors for p2 and connection between p1 and p2.
404  // gc1/gc2 are foreground gc used to detect size of background regions
405  //
406  // Also paints skeleton
407 
408  sec_assert(valid_cb_params(device));
409 
410  color1 = paintData.convert_BackgroundGC(color1); // convert EDIT4-GCs into SECEDIT-GCs
411  color2 = paintData.convert_BackgroundGC(color2);
412 
413  if (color1 >= 0 || color2 >= 0 || displayParams.show_strSkeleton) {
414  const double& radius1 = get_char_radius(gc1);
415  const double& radius2 = get_char_radius(gc2);
416 
417  if (mode & BG_PAINT_FIRST && color1 >= 0) { // paint first circle ?
418  device->circle(color1, AW::FillStyle::SOLID, p1, Vector(radius1, radius1));
419  }
420 
421  if (mode & BG_PAINT_SECOND && color2 >= 0) { // paint second circle ?
422  device->circle(color2, AW::FillStyle::SOLID, p2, Vector(radius1, radius1));
423  }
424 
425  if (color1 == color2 && color1 >= 0) { // colors are equal -> paint background between points
426  device->set_line_attributes(color1, bg_linewidth[paintData.get_linePropertyGC(gc1, gc2)], AW_SOLID);
427  device->line(color1, p1, p2);
428  }
429 
430  if (displayParams.show_strSkeleton) { // paint skeleton?
431  Position s1 = p1;
432  Position s2 = p2;
433  bool space = false;
434 
435  if (displayParams.hide_bases) {
436  space = true; // no base chars -> enough space to paint
437  }
438  else {
439  Vector v12(p1, p2);
440  double vlen = v12.length();
441 
442  // Note: LINE_THICKNESS
443  // Lines drawn with thickness != 1 differ between motif-version and gtk-version:
444  // in motif thicker lines are also drawn longer than specified (half thickness on each side)
445  const double CORR = skelThickWorld;
446 
447  if ((radius1+radius2+CORR) < vlen) { // test if there is enough space between characters
448  s1 = p1 + v12*((radius1+CORR/2)/vlen); // skeleton<->base attach-points
449  s2 = p2 - v12*((radius2+CORR/2)/vlen);
450  space = true;
451  }
452  }
453 
454  if (space) {
455  device->set_line_attributes(skel_gc, displayParams.skeleton_thickness, AW_SOLID);
456 #if defined(DEBUG)
457  if (displayParams.show_debug) { s1 = p1; s2 = p2; } // in debug mode always show full skeleton
458 #endif // DEBUG
459  device->line(skel_gc, s1, s2);
460  }
461  }
462  }
463 }
464 
465 void SEC_root::paintSearchPatternStrings(AW_device *device, int clickedPos, AW_pos xPos, AW_pos yPos) {
466  int searchColor = getBackgroundColor(clickedPos);
467 
468  if (searchColor >= SEC_GC_SBACK_0 && searchColor <= SEC_GC_SBACK_8) {
469  static const char *text[SEC_GC_SBACK_8-SEC_GC_SBACK_0+1] = {
470  "User 1",
471  "User 2",
472  "Probe",
473  "Primer (local)",
474  "Primer (region)",
475  "Primer (global)",
476  "Signature (local)",
477  "Signature (region)",
478  "Signature (global)",
479  };
480 
481  AW_click_cd cd(device, 0, clickedPos);
482  device->text(searchColor, text[searchColor-SEC_GC_SBACK_0], xPos, yPos, 0, AW_SCREEN);
483  }
484  else {
485  aw_message("Please click on a search result");
486  }
487 }
488 
489 // ---------------
490 // Bonds
491 
492 void SEC_bond_def::paint(AW_device *device, char base1, char base2, const Position& p1, const Position& p2, const Vector& toNextBase, const double& char_radius) const {
493  if (base1 && base2) {
494  char Bond = get_bond(base1, base2);
495  if (Bond == ' ') {
496  // check IUPACs
497  const char *iupac1 = iupac::decode(base1, ali_type, 0);
498  const char *iupac2 = iupac::decode(base2, ali_type, 0);
499 
500  bool useBond[SEC_BOND_PAIR_CHARS];
501  for (int i = 0; i<SEC_BOND_PAIR_CHARS; i++) useBond[i] = false;
502 
503  int maxIdx = -1;
504  for (int i1 = 0; iupac1[i1]; ++i1) {
505  for (int i2 = 0; iupac2[i2]; ++i2) {
506  char b = get_bond(iupac1[i1], iupac2[i2]);
507 
508  if (b != ' ') {
509  const char *found = strchr(SEC_BOND_PAIR_CHAR, b);
510  int idx = found-SEC_BOND_PAIR_CHAR;
511 
512  useBond[idx] = true;
513  if (idx>maxIdx) maxIdx = idx;
514  }
515  }
516  }
517 
518  if (maxIdx >= 0) {
519  for (int i = 0; i<SEC_BOND_PAIR_CHARS; i++) {
520  if (useBond[i]) {
521  paint(device, i == maxIdx ? SEC_GC_BONDS : SEC_GC_ERROR, SEC_BOND_PAIR_CHAR[i], p1, p2, toNextBase, char_radius);
522  }
523  }
524  }
525  }
526  else {
527  paint(device, SEC_GC_BONDS, Bond, p1, p2, toNextBase, char_radius);
528  }
529  }
530 }
531 
532 void SEC_bond_def::paint(AW_device *device, int GC, char bondChar, const Position& p1, const Position& p2, const Vector& toNextBase, const double& char_radius) const {
533  Vector v12(p1, p2);
534  double oppoDist = v12.length();
535  double bondLen = oppoDist-2*char_radius;
536 
537  if (bondLen <= 0.0) return; // not enough space to draw bond
538 
539  Vector pb = v12*(char_radius/oppoDist);
540 
541  Position b1 = p1+pb; // start/end pos of bond
542  Position b2 = p2-pb;
543 
544  Position center = centroid(b1, b2);
545 
546  Vector aside = toNextBase;
547  {
548  // limit aside-size by strand-distance
549  double aside_len = aside.length();
550  double max_aside_len = min(aside_len, Vector(b1, b2).length());
551  if (max_aside_len<aside_len) {
552  aside *= max_aside_len/aside_len;
553  }
554  }
555  aside *= 0.22; // max. 22% towards next base position (has to be less than 25%, because 'aside' is added twice for some bondtypes)
556 
557  switch (bondChar) {
558  case '-': // single line
559  device->line(GC, b1, b2);
560  break;
561 
562  case '#': // double cross
563  case '=': // double line
564  device->line(GC, b1+aside, b2+aside);
565  device->line(GC, b1-aside, b2-aside);
566 
567  if (bondChar == '#') {
568  Vector outside = v12*(bondLen/oppoDist/4);
569  Position c1 = center+outside;
570  Position c2 = center-outside;
571 
572  aside *= 2;
573 
574  device->line(GC, c1-aside, c1+aside);
575  device->line(GC, c2-aside, c2+aside);
576  }
577  break;
578 
579  case '~': {
580  double radius = aside.length();
581  {
582  double maxRadius = bondLen/4;
583  if (maxRadius<radius) radius = maxRadius;
584  }
585 
586  Vector outside = v12*(radius/oppoDist);
587 
588  Position c1 = center+outside;
589  Position c2 = center-outside;
590 
591  aside *= 2;
592 
593  Angle angle(outside);
594  int deg = AW_INT(angle.degrees());
595 
596  const int INSIDE = 2;
597  const int OUTSIDE = 15;
598 
599  Vector vRadius(radius, radius);
600  device->arc(GC, AW::FillStyle::EMPTY, c1, vRadius, deg+180+INSIDE, -(180+INSIDE+OUTSIDE));
601  device->arc(GC, AW::FillStyle::EMPTY, c2, vRadius, deg+INSIDE, -(180+INSIDE+OUTSIDE));
602  break;
603  }
604 
605  case '+': // cross
606  aside *= 2;
607  device->line(GC, center-aside, center+aside);
608  if (2*aside.length() < bondLen) {
609  aside.rotate90deg();
610  device->line(GC, center-aside, center+aside);
611  }
612  else {
613  device->line(GC, b1, b2);
614  }
615  break;
616 
617  case 'o':
618  case '.': { // circles
619  double radius = aside.length();
620  if (bondChar == 'o') radius *= 2;
621  device->circle(GC, AW::FillStyle::EMPTY, center, Vector(radius, radius));
622  break;
623  }
624 
625  case '@': // error in bonddef
626  device->text(GC, "Err", center+Vector(0, char_radius), 0.5, AW_ALL_DEVICES_UNSCALED);
627  break;
628 
629  default:
630  sec_assert(0); // // illegal bond char
631  break;
632  }
633 }
634 
635 // -----------------------
636 // Paint helices
637 
639  int abs[2]; // absolute sequence position
640  int previous[2]; // previous drawn index
641  bool drawn[2]; // draw position ?
642  bool isPair; // true if position is pairing
643  Position realpos[2]; // real position
644 };
645 
646 void SEC_helix_strand::paint_strands(AW_device *device, const Vector& strand_vec, const double& strand_len) {
647  static StrandPositionData *data = NULp;
648  static int allocated = 0;
649 
650  const SEC_region* Region[2] = { get_region(), other_strand->get_region() };
651  int base_count = Region[0]->get_base_count();
652 
653  sec_assert(Region[1]->get_base_count() == base_count); // not aligned ?
654 
655  if (base_count<1) {
656  return; // completely skip painting on strands w/o any base
657  }
658 
659  if (allocated<base_count) {
660  delete [] data;
661  data = new StrandPositionData[base_count];
662  allocated = base_count;
663  }
664 
665  SEC_root *root = get_root();
666  const BI_helix *helix = root->get_helixDef();
667 
668  double base_dist = base_count>1 ? strand_len / (base_count-1) : 1;
669  Vector vnext = strand_vec * base_dist; // vector from base to next base (in strand)
670 
671  // first calculate positions
672  {
673  StrandPositionData *curr = &data[0];
674 
675  int idx[2] = { 0, base_count-1 };
676  Position pos[2] = { leftAttach, rightAttach };
677  Vector toNonBind[2]; // vectors from normal to non-binding positions
678  toNonBind[1] = (strand_vec*0.5).rotate90deg();
679  toNonBind[0] = -toNonBind[1];
680 
681  for (int strand = 0; strand<2; ++strand) {
682  curr->abs[strand] = Region[strand]->getBasePos(idx[strand]);
683  curr->previous[strand] = 0;
684  curr->drawn[strand] = (curr->abs[strand] >= 0);
685  }
686 
687  for (int dIdx = 1; ; ++dIdx) {
688  sec_assert(pos[0].valid());
689  sec_assert(pos[1].valid());
690 
691  int oneAbs = curr->drawn[0] ? curr->abs[0] : curr->abs[1];
692  sec_assert(oneAbs >= 0); // otherwise current position should have been eliminated by align_helix_strands
693  curr->isPair = (helix->pairtype(oneAbs) != HELIX_NONE);
694 
695  for (int strand = 0; strand<2; ++strand) {
696  if (curr->isPair) {
697  curr->realpos[strand] = pos[strand];
698  curr->drawn[strand] = true;
699  }
700  else {
701  curr->realpos[strand] = pos[strand]+toNonBind[strand];
702  }
703 
704  sec_assert(curr->realpos[strand].valid());
705  }
706 
707  if (dIdx >= base_count) break;
708 
709  ++idx[0];
710  --idx[1];
711 
712  StrandPositionData *prev = curr;
713  curr = &data[dIdx];
714 
715  for (int strand = 0; strand<2; ++strand) {
716  pos[strand] += vnext;
717  curr->abs[strand] = Region[strand]->getBasePos(idx[strand]);
718  curr->previous[strand] = prev->drawn[strand] ? dIdx-1 : prev->previous[strand];
719  curr->drawn[strand] = (curr->abs[strand] >= 0);
720  }
721  }
722  }
723 
724  const int pair2helixGC[2] = { SEC_GC_NHELIX, SEC_GC_HELIX };
725  const int pair2skelGC[2] = { SEC_SKELE_NHELIX, SEC_SKELE_HELIX };
726 
727  const SEC_db_interface *db = root->get_db();
728  const SEC_displayParams& disp = root->display_params();
729 
730  // draw background and skeleton
731  for (int pos = 1; pos<base_count; ++pos) {
732  StrandPositionData *curr = &data[pos];
733  for (int strand = 0; strand<2; ++strand) {
734  if (curr->drawn[strand]) {
735  StrandPositionData *prev = &data[curr->previous[strand]];
736 
737  int backAbs = disp.edit_rightward
738  ? max(prev->abs[strand], curr->abs[strand])
739  : min(prev->abs[strand], curr->abs[strand]);
740 
741  AW_click_cd cd(device, self(), backAbs);
742  root->paintBackgroundColor(device,
743  pos == base_count-1 ? BG_PAINT_NONE : BG_PAINT_SECOND,
744  prev->realpos[strand], root->getBackgroundColor(prev->abs[strand]), pair2helixGC[prev->isPair],
745  curr->realpos[strand], root->getBackgroundColor(curr->abs[strand]), pair2helixGC[curr->isPair],
746  pair2skelGC[curr->isPair && prev->isPair]);
747  }
748  }
749  }
750 
751  // draw base characters and bonds
752  char baseBuf[20] = "x";
753  for (int pos = 0; pos<base_count; ++pos) {
754  StrandPositionData *curr = &data[pos];
755  char base[2] = { 0, 0 };
756 
757  int gc = pair2helixGC[curr->isPair];
758  Vector center_char = root->get_center_char_vector(gc);
759 
760  for (int strand = 0; strand<2; ++strand) {
761  if (curr->drawn[strand]) {
762  int abs = curr->abs[strand];
763  const Position& realPos = curr->realpos[strand];
764 
765  sec_assert(abs >= 0);
766 
767  base[strand] = db->baseAt(abs);
768  root->announce_base_position(abs, realPos);
769 
770  if (!disp.hide_bases) {
771  baseBuf[0] = base[strand];
772  Position base_pos = realPos + center_char; // center base at realpos
773  AW_click_cd cd(device, self(), abs);
774 #if defined(DEBUG)
775  if (disp.show_debug) device->line(gc, realPos, base_pos);
776 #endif // DEBUG
777 
778  device->text(gc, baseBuf, base_pos, 0.0, AW_ALL_DEVICES_SCALED);
779  }
780  }
781  }
782 
783  if (disp.show_bonds == SHOW_NHELIX_BONDS || (disp.show_bonds == SHOW_HELIX_BONDS && curr->isPair)) {
784  AW_click_cd cd(device, self(), curr->abs[0]);
785  db->bonds()->paint(device, base[0], base[1], curr->realpos[0], curr->realpos[1], vnext,
786  root->get_char_radius(pair2helixGC[curr->isPair])
787  +root->get_bondThickWorld()/2 // see .@LINE_THICKNESS
788  );
789  }
790  }
791 }
792 
793 void SEC_helix_strand::paint(AW_device *device) {
794  sec_assert(isRootsideFixpoint());
795 
796  Vector strand_vec(rightAttach, other_strand->leftAttach);
797  double strand_len = strand_vec.length(); // length of strand
798 
799  if (strand_len>0) {
800  strand_vec.normalize(); // normalize
801  }
802  else { // strand with zero length (contains only one base-pair)
803  strand_vec = Vector(rightAttach, leftAttach).rotate90deg();
804  }
805 
806  other_strand->origin_loop->paint(device); // first paint next loop
807  paint_strands(device, strand_vec, strand_len); // then paint strand
808 
809  SEC_root *root = get_root();
810  const SEC_displayParams& disp = root->display_params();
811 
812  if (disp.show_strSkeleton && !disp.show_bonds && disp.hide_bases) {
813  // display strand direction
814  LineVector strandArrow;
815  if (strand_len>0) {
816  strandArrow = LineVector(get_fixpoint(), strand_vec);
817  }
818  else {
819  Vector fix2arrowStart(get_fixpoint(), leftAttachPoint());
820  fix2arrowStart.rotate90deg();
821  strandArrow = LineVector(get_fixpoint()-fix2arrowStart, 2*fix2arrowStart);
822  }
823 
824  AW_click_cd cd(device, get_helix()->self(), startAttachAbspos());
825  device->line(SEC_GC_HELIX, strandArrow);
826 
827  Vector right = strandArrow.line_vector(); // left arrowhead vector
828  right = (right * (disp.distance_between_strands*0.35/right.length())).rotate135deg();
829 
830  Vector left = Vector(right).rotate90deg();
831 
832  Position head = strandArrow.head();
833  device->line(SEC_GC_HELIX, LineVector(head, left));
834  device->line(SEC_GC_HELIX, LineVector(head, right));
835  }
836 
837 #if defined(DEBUG)
838  if (disp.show_debug) paintStrandDebugInfo(device, SEC_GC_HELIX, other_strand);
839 #endif // DEBUG
840 
841  if (root->get_show_constraints() & SEC_HELIX) paint_constraints(device);
842 }
843 
844 
845 // ---------------------
846 // Paint loops
847 
848 void SEC_segment::paint(AW_device *device, SEC_helix_strand *previous_strand_pointer) {
849  int base_count = get_region()->get_base_count(); // bases in segment
850 
851  const Position& startP = previous_strand_pointer->rightAttachPoint();
852  const Position& endP = next_helix_strand->leftAttachPoint();
853 
854  Angle current; // start/current angle
855  Angle end; // end angle
856  double radius1; // start and..
857  double radius2; // end radius of segment
858 
859  {
860  Vector seg_start_radius(center1, startP);
861  radius1 = seg_start_radius.length();
862  current = seg_start_radius;
863 
864  Vector seg_end_radius(center2, endP);
865  radius2 = seg_end_radius.length();
866  end = seg_end_radius;
867  }
868 
869  int steps = base_count+1;
870 
871  double step = ((end-current)/steps).radian();
872 
873  // correct if we have to paint more than a full loop
874  if ((alpha - (step*steps)) > M_PI) {
875  step += (2*M_PI)/steps;
876  }
877 
878  double radStep = (radius2-radius1)/steps;
879 
880  Vector cstep(center1, center2);
881  cstep /= steps;
882 
883  SEC_root *root = get_root();
884  const SEC_db_interface *db = root->get_db();
885  const SEC_displayParams& disp = root->display_params();
886 #if defined(DEBUG)
887  if (disp.show_debug) {
888  paintStrandDebugInfo(device, SEC_GC_LOOP, previous_strand_pointer);
889 
890  int startAbsPos = previous_strand_pointer->rightAttachAbspos();
891  int endAbsPos = next_helix_strand->leftAttachAbspos();
892 
893  AW_click_cd cd(device, self(), startAbsPos);
894  paintDebugInfo(device, SEC_GC_LOOP, center1, GBS_global_string("SC1 (step=%5.3f)", step));
895  device->line(SEC_GC_LOOP, center1, startP);
896  device->line(SEC_GC_LOOP, center1, center2);
897 
898  cd.set_cd2(endAbsPos);
899  paintDebugInfo(device, SEC_GC_LOOP, center2, "SC2");
900  device->line(SEC_GC_LOOP, center2, endP);
901  }
902 #endif // DEBUG
903 
904  char baseBuf[5] = "?"; // contains base char during print
905  Position pos = startP;
906  int abs = previous_strand_pointer->rightAttachAbspos();
907  int back = root->getBackgroundColor(abs);
908  int gc = root->getBondtype(abs) == HELIX_NONE ? SEC_GC_NHELIX : SEC_GC_HELIX;
909  int nextGc = SEC_GC_LOOP;
910 
911  Position currCenter = center1;
912  double currRadius = radius1;
913 
914  Angle step_angle(step);
915 
916  for (int i = -1; i<base_count; i++) { // for each segment position (plus one pre-loop)
917  current += step_angle; // iterate over angles
918  currCenter += cstep;
919  currRadius += radStep;
920 
921  Position nextPos = currCenter + current.normal()*currRadius;
922  int nextAbs;
923 
924  if (i == (base_count-1)) { // last position (belongs to strand)
925  nextAbs = next_helix_strand->leftAttachAbspos();
926  if (nextAbs<0) { // helix doesn't start with pair
927  nextAbs = next_helix_strand->getNextAbspos();
928  }
929  nextGc = root->getBondtype(nextAbs) == HELIX_NONE ? SEC_GC_NHELIX : SEC_GC_HELIX;
930  }
931  else {
932  nextAbs = get_region()->getBasePos(i+1);
933  }
934 
935  int nextBack = root->getBackgroundColor(nextAbs);
936 
937  // paint background (from pos to nextPos)
938  AW_click_cd cd(device, self(), disp.edit_rightward ? nextAbs : abs);
939  root->paintBackgroundColor(device, i == -1 ? BG_PAINT_BOTH : BG_PAINT_SECOND,
940  pos, back, gc, nextPos, nextBack, nextGc, SEC_SKELE_LOOP);
941 
942  if (i >= 0) {
943  // paint base char at pos
944  baseBuf[0] = abs>0 ? db->baseAt(abs) : '?';
945  Vector center_char = root->get_center_char_vector(gc);
946  Position base_pos = pos + center_char; // center base character at pos
947 
948  cd.set_cd2(abs);
949  if (!disp.hide_bases) {
950 #if defined(DEBUG)
951  // show line from base paint pos to calculated center of char
952  // (which is currently calculated wrong!)
953  if (disp.show_debug) device->line(SEC_GC_LOOP, pos, base_pos);
954 #endif // DEBUG
955  device->text(SEC_GC_LOOP, baseBuf, base_pos, 0.0, AW_ALL_DEVICES_SCALED);
956  }
957  root->announce_base_position(abs, pos);
958  }
959 
960  // prepare next loop
961  pos = nextPos;
962  abs = nextAbs;
963  back = nextBack;
964  gc = nextGc;
965  }
966 }
967 
968 void SEC_loop::paint(AW_device *device) {
969  for (SEC_segment_iterator seg(this); seg; ++seg) { // first paint all segments
970  seg->paint(device, seg->get_previous_strand());
971  }
972  for (SEC_strand_iterator strand(this); strand; ++strand) { // then paint all outgoing strands
973  if (strand->isRootsideFixpoint()) strand->paint(device);
974  }
975 
976  SEC_root *sroot = get_root();
977 #if defined(DEBUG)
978  if (sroot->display_params().show_debug) {
979  SEC_helix_strand *fixpoint_strand = get_fixpoint_strand();
980  int abspos = fixpoint_strand->startAttachAbspos();
981  AW_click_cd cd(device, self(), abspos);
982 
984  device->line(SEC_GC_CURSOR, get_center(), fixpoint_strand->get_fixpoint());
985 
986  paintStrandDebugInfo(device, SEC_GC_CURSOR, fixpoint_strand);
987  paintDebugInfo(device, SEC_GC_CURSOR, get_center(), "LC");
988  }
989 #endif // DEBUG
990  if (sroot->get_show_constraints() & SEC_LOOP) paint_constraints(device);
991 }
992 
993 // ------------------------------------------------------------
994 // Paint the whole structure (starting with SEC_root)
995 
997  SEC_loop *rootLoop = get_root_loop();
998  sec_assert(rootLoop);
999  clear_announced_positions(); // reset positions next to cursor
1000 
1001  const BI_helix *helix = get_helixDef();
1002  sec_assert(helix);
1003 
1004  GB_ERROR error = helix->get_error();
1005 
1006  if (!error) {
1008  // @@@ font group should be built at startup and after each font change (no need to do on every paint!)
1009  font_group.unregisterAll();
1010  for (int gc = SEC_GC_FIRST_FONT; gc <= SEC_GC_LAST_FONT; ++gc) {
1011  font_group.registerFont(device, gc, "ACGTU-.");
1012  center_char[gc] = device->rtransform(Vector(-0.5*font_group.get_width(gc), 0.5*font_group.get_ascent(gc)));
1013  }
1014 
1015  // calculate size for background painting
1017  for (int gc = SEC_GC_FIRST_DATA; gc <= SEC_GC_LAST_DATA; ++gc) {
1018  int maxSize = hypotenuse(font_group.get_width(gc), font_group.get_ascent(gc));
1019  bg_linewidth[gc] = maxSize*0.75;
1020 
1021  maxSize += 2; // add 2 extra pixels
1022  charRadius[gc] = device->rtransform_size(maxSize) * 0.5; // was 0.75
1023  }
1024 
1025  skelThickWorld = device->rtransform_size(displayParams.skeleton_thickness);
1026  bondThickWorld = device->rtransform_size(displayParams.bond_thickness);
1027 
1028  cacheBackgroundColor();
1029 
1030  device->set_line_attributes(SEC_SKELE_HELIX, displayParams.skeleton_thickness, AW_SOLID);
1031  device->set_line_attributes(SEC_SKELE_NHELIX, displayParams.skeleton_thickness, AW_SOLID);
1032  device->set_line_attributes(SEC_SKELE_LOOP, displayParams.skeleton_thickness, AW_SOLID);
1033  device->set_line_attributes(SEC_GC_BONDS, displayParams.bond_thickness, AW_SOLID);
1034 
1035  // mark the rootLoop with a box and print structure number
1036  {
1037  const Position& loop_center = rootLoop->get_center();
1038  const char *structId = db->structure()->name();
1039 
1040  AW_click_cd cd(device, rootLoop->self(), -1);
1041 
1042  Vector center2corner(-1, -1);
1043  center2corner.set_length(rootLoop->drawnSize()*0.33);
1044 
1045  Position upperleft_corner = loop_center+center2corner;
1046  Vector diagonal = -2*center2corner;
1047 
1048  Position textPos(loop_center.xpos(), upperleft_corner.ypos());
1049 
1050  device->box(SEC_GC_DEFAULT, AW::FillStyle::EMPTY, upperleft_corner, diagonal, AW_ALL_DEVICES_UNSCALED);
1051  device->text(SEC_GC_DEFAULT, structId, textPos, 0.5);
1052  }
1053 
1054 #if defined(CHECK_INTEGRITY)
1055  check_integrity(CHECK_ALL);
1056 #endif // CHECK_INTEGRITY
1057 
1058  rootLoop->paint(device);
1059 
1060  // paint ecoli positions:
1061  if (displayParams.show_ecoli_pos) paintEcoliPositions(device);
1062 
1063  if (displayParams.show_helixNrs) {
1064  paintHelixNumbers(device);
1065  }
1066 
1067 #if defined(PAINT_ABSOLUTE_POSITION)
1068  if (displayParams.show_debug) showSomeAbsolutePositions(device);
1069 #endif // PAINT_ABSOLUTE_POSITION
1070 
1071  // paint cursor:
1072  if (!drawnPositions->empty() &&
1073  (device->get_filter()&(AW_PRINTER|AW_PRINTER_EXT)) == 0) // don't print/xfig-export cursor
1074  {
1075  size_t abs1, abs2;
1076  Position pos1, pos2;
1077  size_t curAbs;
1078 
1079  if (displayParams.edit_rightward) {
1080  pos1 = drawnPositions->drawn_before(cursorAbsPos, &abs1);
1081  pos2 = drawnPositions->drawn_after(cursorAbsPos-1, &abs2);
1082  curAbs = abs2;
1083  }
1084  else {
1085  pos1 = drawnPositions->drawn_before(cursorAbsPos+1, &abs1);
1086  pos2 = drawnPositions->drawn_after(cursorAbsPos, &abs2);
1087  curAbs = abs1;
1088  }
1089 
1090  AW_click_cd cd(device, 0, curAbs);
1091 #if defined(DEBUG) && 1
1092  // draw a testline to see the baseline on that the cursor is positioned
1094  device->line(SEC_GC_CURSOR, pos1, pos2);
1095 #endif
1096 
1097  Position mid = centroid(pos1, pos2);
1098  Vector v(pos1, pos2);
1099  {
1100  Vector v_drawn = device->transform(v);
1101  double drawn_length = v_drawn.length();
1102 
1103  sec_assert(drawn_length>0.0);
1104 
1105  double cursor_size = 1.3 * max(font_group.get_max_width(), font_group.get_max_ascent()); // 30% bigger than max font size
1106  double stretch = cursor_size*0.5/drawn_length; // stretch cursor (half fontsize in each direction)
1107 
1108  v.rotate90deg() *= stretch;
1109  }
1110 
1111  LineVector cursor(mid+v, mid-v);
1113  device->line(SEC_GC_CURSOR, cursor);
1114  set_last_drawed_cursor_position(cursor);
1115 
1116  LineVector cursor_dir(cursor.head(), displayParams.edit_rightward ? v.rotate270deg() : v.rotate90deg());
1117  device->line(SEC_GC_CURSOR, cursor_dir);
1118 
1119 
1120  int cursor_gc = -1;
1121  int disp_pos = -1;
1122 
1123  switch (displayParams.show_curpos) {
1124  case SHOW_ABS_CURPOS:
1125  cursor_gc = SEC_GC_CURSOR;
1126  disp_pos = info2bio(curAbs);
1127  break;
1128  case SHOW_BASE_CURPOS:
1129  cursor_gc = SEC_GC_DEFAULT;
1130  disp_pos = host().get_base_position(curAbs+1); // show bases up to cursorpos (inclusive)
1131  break;
1132  case SHOW_ECOLI_CURPOS: {
1133  cursor_gc = SEC_GC_ECOLI;
1134  disp_pos = db->ecoli()->abs_2_rel(curAbs+1); // show ecoli base position (inclusive cursorpos)
1135  break;
1136  }
1137  case SHOW_NO_CURPOS:
1138  cursor_gc = -1;
1139  break;
1140  }
1141 
1142  if (cursor_gc >= 0) {
1143  paintPosAnnotation(device, cursor_gc, curAbs, GBS_global_string("%u", disp_pos), true, true);
1144  }
1145  }
1146  }
1147  return error;
1148 }
1149 
1151  if (abspos_array) {
1152  const BI_helix *helix = root->get_helixDef();
1153  if (helix && !helix->get_error()) {
1154  SEC_region *reg[2] = { this, other_region };
1155  int incr[2] = { 1, -1 }; // this is iterated forward, other_region backward
1156  int *absarr[2];
1157  int *new_absarr[2] = { NULp, NULp };
1158 
1159 
1160  for (int r = 0; r<2; ++r) {
1161  absarr[r] = reg[r]->abspos_array;
1162  }
1163 
1164  for (int write = 0; write < 2; ++write) {
1165  int curr[2] = { 0, reg[1]->baseCount-1 };
1166  int last[2] = { reg[0]->baseCount-1, 0 };
1167  int newp[2] = { 0, 0 };
1168 
1169  while (curr[0] <= last[0] && curr[1] >= last[1]) {
1170  int abs[2];
1171  bool ispair[2];
1172 
1173  for (int r = 0; r<2; ++r) {
1174  abs[r] = absarr[r][curr[r]];
1175  ispair[r] = abs[r] >= 0 && (helix->pairtype(abs[r]) != HELIX_NONE);
1176  }
1177 
1178  if (ispair[0] && ispair[1]) {
1179  if (helix->opposite_position(abs[0]) != size_t(abs[1]) ||
1180  helix->opposite_position(abs[1]) != size_t(abs[0]))
1181  {
1182  GB_ERROR error = GBS_global_string("Helix '%s/%s' folded at wrong position. Please refold.",
1183  helix->helixNr(abs[0]), helix->helixNr(abs[1]));
1184  aw_message(error);
1185  }
1186 
1187  for (int r = 0; r<2; ++r) { // fill up to align binding positions
1188  while (newp[r]<newp[1-r]) {
1189  if (write) {
1190  new_absarr[r][newp[r]] = -1;
1191  }
1192  newp[r]++;
1193  }
1194  }
1195 
1196  sec_assert(newp[0] == newp[1]);
1197 
1198  for (int r = 0; r<2; ++r) { // copy binding positions
1199  if (write) new_absarr[r][newp[r]] = abs[r];
1200  newp[r]++; curr[r] += incr[r];
1201  }
1202  }
1203  else {
1204  bool collected = false;
1205  for (int r = 0; r<2; ++r) {
1206  if (abs[r] >= 0 && !ispair[r]) { // collect non-pairing bases
1207  if (write) {
1208  new_absarr[r][newp[r]] = abs[r];
1209  }
1210  newp[r]++; curr[r] += incr[r];
1211  collected = true;
1212  }
1213  }
1214  if (!collected) {
1215  for (int r = 0; r<2; ++r) {
1216  if (abs[r]<0) curr[r] += incr[r];
1217  }
1218  }
1219  }
1220  }
1221 
1222  sec_assert(newp[0] == newp[1]); // alignment failed
1223 
1224  for (int r = 0; r<2; ++r) {
1225  if (write) {
1226  if (r == 1) { // reverse positions
1227  int p2 = newp[1]-1;
1228  int *arr = new_absarr[1];
1229  for (int p = 0; p<p2; ++p, --p2) { // LOOP_VECTORIZED[!<810]
1230  swap(arr[p], arr[p2]);
1231  }
1232  }
1233 
1234  delete [] reg[r]->abspos_array;
1235  reg[r]->abspos_array = new_absarr[r];
1236 #if defined(ASSERTION_USED)
1237  reg[r]->abspos_array_size = newp[r];
1238 #endif // ASSERTION_USED
1239  reg[r]->set_base_count(newp[r]);
1240  }
1241  else {
1242  // allocate buffers for second pass
1243  new_absarr[r] = new int[newp[r]];
1244  }
1245  }
1246  }
1247  }
1248  }
1249 }
1250 
int get_base_count() const
Definition: SEC_root.hxx:110
static PaintData paintData
Definition: SEC_paint.cxx:121
AW::Vector transform(const AW::Vector &vec) const
Definition: aw_device.hxx:144
Vector & rotate135deg()
void align_helix_strands(SEC_root *root, SEC_region *other_region)
Definition: SEC_paint.cxx:1150
Vector & rotate90deg()
const AW_bitset AW_SIZE
Definition: aw_device.hxx:37
const AW_bitset AW_PRINTER_EXT
Definition: aw_device.hxx:40
const AW_bitset AW_SCREEN
Definition: aw_device.hxx:34
double centroid(const double &val1, const double &val2)
Definition: aw_position.hxx:77
int rel_2_abs(int rel) const
Definition: BI_basepos.hxx:87
const AW_screen_area & get_area_size() const
Definition: AW_device.cxx:57
Position centroid() const
void space()
Definition: test_unit.h:403
const SEC_db_interface * get_db() const
Definition: SEC_root.hxx:747
bool valid() const
const double & get_char_radius(int gc) const
Definition: SEC_root.hxx:755
void set_cd2(AW_CL cd)
Definition: aw_device.hxx:351
void set_line_attributes(int gc, short width, AW_linestyle style)
Definition: AW_device.cxx:465
void paintSearchPatternStrings(AW_device *device, int clickedPos, AW_pos xPos, AW_pos yPos)
Definition: SEC_paint.cxx:465
int getBackgroundColor(int abspos)
Definition: SEC_root.hxx:821
virtual void clear_part(const AW::Rectangle &rect, AW_bitset filteri)
Definition: AW_device.cxx:317
static int pos1
Definition: ClustalV.cxx:58
const BI_helix * get_helixDef() const
Definition: SEC_root.hxx:750
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:204
const SEC_displayParams & display_params() const
Definition: SEC_root.hxx:758
size_t opposite_position(size_t pos) const
Definition: BI_helix.hxx:96
STL namespace.
int base_count() const
Definition: BI_basepos.hxx:100
SEC_BASE_TYPE get_show_constraints()
Definition: SEC_root.hxx:838
double length() const
#define SEC_BOND_PAIR_CHARS
Definition: SEC_bonddef.hxx:27
const Vector & normal() const
Position realpos[2]
Definition: SEC_paint.cxx:643
#define M_PI
Vector & set_length(double new_length)
SEC_structure_toggler * structure() const
Definition: SEC_db.hxx:169
const AW_bitset AW_ALL_DEVICES_SCALED
Definition: aw_device.hxx:45
static HelixNrInfo * start
int get_linePropertyGC(int gc1, int gc2)
Definition: SEC_paint.cxx:112
const AW_bitset AW_PRINTER
Definition: aw_device.hxx:39
void paintBackgroundColor(AW_device *device, SEC_bgpaint_mode mode, const Position &p1, int color1, int gc1, const Position &p2, int color2, int gc2, int skel_gc)
Definition: SEC_paint.cxx:402
double AW_pos
Definition: aw_base.hxx:29
double rtransform_size(const double &size) const
Definition: aw_device.hxx:136
AW_bitset get_filter() const
Definition: aw_device.hxx:383
int abs_2_rel(int abs) const
Definition: BI_basepos.hxx:76
const char * decode(char iupac, GB_alignment_type aliType, bool decode_amino_iupac_groups)
Definition: iupac.cxx:239
Vector & rotate270deg()
const Vector & get_center_char_vector(int gc)
Definition: SEC_root.hxx:822
int get_string_size(int gc, long textlen) const
Definition: AW_device.cxx:443
ShowBonds show_bonds
Definition: SEC_root.hxx:638
TYPE * ARB_alloc(size_t nelem)
Definition: arb_mem.h:56
#define SEC_BOND_PAIR_CHAR
Definition: SEC_bonddef.hxx:28
bool circle(int gc, AW::FillStyle filled, const AW::Position &center, const AW::Vector &radius, AW_bitset filteri=AW_ALL_DEVICES_SCALED)
Definition: aw_device.hxx:481
const double & ypos() const
Angle & rotate270deg()
double distance_between_strands
Definition: SEC_root.hxx:636
double hypotenuse(double cath1, double cath2)
AW_CL get_cd1() const
Definition: aw_device.hxx:347
bool line(int gc, const AW::LineVector &Line, AW_bitset filteri=AW_ALL_DEVICES_SCALED)
Definition: aw_device.hxx:430
AW::Vector rtransform(const AW::Vector &vec) const
Definition: aw_device.hxx:145
static void error(const char *msg)
Definition: mkptypes.cxx:96
AW_CL get_cd2() const
Definition: aw_device.hxx:348
const Position & upper_left_corner() const
CONSTEXPR_INLINE_Cxx14 void swap(unsigned char &c1, unsigned char &c2)
Definition: ad_io_inline.h:19
double get_bondThickWorld() const
Definition: SEC_root.hxx:862
ASSERTING_CONSTEXPR_INLINE int info2bio(int infopos)
Definition: arb_defs.h:27
void clear_announced_positions()
Definition: SEC_paint.cxx:320
const char * helixNr(size_t pos) const
Definition: BI_helix.hxx:102
CONSTEXPR_INLINE bool valid(SpeciesCreationMode m)
Definition: ed4_class.hxx:2246
static int pos2
Definition: ClustalV.cxx:59
void paintAnnotation(AW_device *device, int gc, const Position &annotate, const Position &left, const Position &right, double noteDistance, const char *text, bool lineToAnnotated, bool linesToLeftRight, bool boxText)
Definition: SEC_paint.cxx:126
const Vector & diagonal() const
SEC_bgpaint_mode
Definition: SEC_root.hxx:672
const Vector & line_vector() const
GB_ERROR paint(AW_device *device)
Definition: SEC_paint.cxx:996
ASSERTING_CONSTEXPR_INLINE int bio2info(int biopos)
Definition: arb_defs.h:26
const double & length() const
BI_ecoli_ref * ecoli() const
Definition: SEC_db.hxx:167
BI_PAIR_TYPE pairtype(size_t pos) const
Definition: BI_helix.hxx:101
long AW_CL
Definition: cb.h:21
void announce_base_position(int base_pos, const Position &draw_pos)
Definition: SEC_paint.cxx:317
static char * get_error()
Definition: BI_helix.hxx:74
int getBasePos(int basenr) const
Definition: SEC_root.hxx:127
void paintPosAnnotation(AW_device *device, int gc, size_t absPos, const char *text, bool lineToBase, bool boxText)
Definition: SEC_paint.cxx:222
Vector & normalize()
#define abs(x)
Definition: f2c.h:151
const AW_bitset AW_ALL_DEVICES_UNSCALED
Definition: aw_device.hxx:46
Position head() const
void aw_message(const char *msg)
Definition: AW_status.cxx:932
char baseAt(size_t abspos) const
Definition: SEC_db.hxx:156
int convert_BackgroundGC(int edit4_gc) const
Definition: SEC_paint.cxx:106
bool arc(int gc, AW::FillStyle filled, AW_pos x0, AW_pos y0, AW_pos xradius, AW_pos yradius, int start_degrees, int arc_degrees, AW_bitset filteri=AW_ALL_DEVICES_SCALED)
Definition: aw_device.hxx:493
const double & xpos() const
#define NULp
Definition: cxxforward.h:97
const char * name()
Definition: SEC_toggle.cxx:213
BI_PAIR_TYPE getBondtype(int abspos)
Definition: SEC_root.hxx:751
SEC_bond_def * bonds() const
Definition: SEC_db.hxx:168
bool box(int gc, AW::FillStyle filled, const AW::Rectangle &rect, AW_bitset filteri=AW_ALL_DEVICES_SCALED)
Definition: aw_device.hxx:471
bool valid_cb_params(AW_CL cd1, AW_CL cd2)
Definition: SEC_paint.cxx:35
size_t length
#define min(a, b)
Definition: f2c.h:153
#define sec_assert(cond)
Definition: SEC_defs.hxx:19
bool text(int gc, const SizedCstr &cstr, const AW::Position &pos, AW_pos alignment=0.0, AW_bitset filteri=AW_ALL_DEVICES_UNSCALED)
Definition: aw_device.hxx:440
const AW_click_cd * get_click_cd() const
Definition: aw_device.hxx:382
GB_ERROR mid(GBL_command_arguments *args, int start_index)
Definition: adlang1.cxx:906
#define max(a, b)
Definition: f2c.h:154