| 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: |
|---|
| 69 | PaintData() { |
|---|
| 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 |
|---|
| 115 | sec_assert(gc1 >= SEC_GC_FIRST_DATA && gc1 <= SEC_GC_LAST_DATA); |
|---|
| 116 | sec_assert(gc2 >= SEC_GC_FIRST_DATA && gc2 <= SEC_GC_LAST_DATA); |
|---|
| 117 | return line_property_gc[gc1][gc2]; |
|---|
| 118 | } |
|---|
| 119 | }; |
|---|
| 120 | |
|---|
| 121 | static PaintData paintData; |
|---|
| 122 | |
|---|
| 123 | // --------------------- |
|---|
| 124 | // Annotations |
|---|
| 125 | |
|---|
| 126 | void SEC_root::paintAnnotation(AW_device *device, int gc, |
|---|
| 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 | } |
|---|
| 320 | void SEC_root::clear_announced_positions() { |
|---|
| 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 | |
|---|
| 638 | struct StrandPositionData { |
|---|
| 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 | |
|---|
| 983 | device->set_line_attributes(SEC_GC_CURSOR, 1, AW_SOLID); |
|---|
| 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 | |
|---|
| 996 | GB_ERROR SEC_root::paint(AW_device *device) { |
|---|
| 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) { |
|---|
| 1007 | sec_assert(SEC_GC_FIRST_FONT == 0); |
|---|
| 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 |
|---|
| 1016 | sec_assert(SEC_GC_FIRST_DATA == 0); |
|---|
| 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 |
|---|
| 1093 | device->set_line_attributes(SEC_GC_CURSOR, 1, AW_DASHED); |
|---|
| 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); |
|---|
| 1112 | device->set_line_attributes(SEC_GC_CURSOR, 3, AW_SOLID); |
|---|
| 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 | |
|---|
| 1150 | void SEC_region::align_helix_strands(SEC_root *root, SEC_region *other_region) { |
|---|
| 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 | |
|---|