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