void C_OUTLINE::plot( //draw it ScrollView* window, // window to draw in ScrollView::Color colour // colour to draw in ) const { inT16 stepindex; // index to cstep ICOORD pos; // current position DIR128 stepdir; // direction of step pos = start; // current position window->Pen(colour); if (stepcount == 0) { window->Rectangle(box.left(), box.top(), box.right(), box.bottom()); return; } window->SetCursor(pos.x(), pos.y()); stepindex = 0; while (stepindex < stepcount) { pos += step(stepindex); // step to next stepdir = step_dir(stepindex); stepindex++; // count steps // merge straight lines while (stepindex < stepcount && stepdir.get_dir() == step_dir(stepindex).get_dir()) { pos += step(stepindex); stepindex++; } window->DrawTo(pos.x(), pos.y()); } }
OUTLINE::OUTLINE(PointS startpt, const vector<DIR>& new_steps) :start(startpt), stepcount(static_cast<int16_t>(new_steps.size())), steps(elem_num(stepcount)){ PointS pos = start; box = RectS(pos, pos); auto lastdir = new_steps.back(); auto prevdir = lastdir; int stepindex = 0; for (int srcindex = 0; srcindex < new_steps.size(); ++srcindex, ++stepindex){ auto dir = new_steps[srcindex]; set_step(stepindex, dir); pos += dir; box += pos; if (dir.isReverse(prevdir) && stepindex > 0){ stepindex -= 2; prevdir = stepindex == -1 ? lastdir : step_dir(stepindex); } else{ prevdir = dir; } } assert(pos.x == start.x&&pos.y == start.y);//ÂÖÀª±ØÐë·â±Õ int begin = 0; while (stepindex - 1 > begin && step_dir(begin).isReverse(step_dir(stepindex - 1))){ start += step_dir(begin); //ÆðµãÏòÇ°ÒÆ ++begin; --stepindex; //cancel there-and-back } for (int i = begin; i < stepindex; ++i){ set_step(i - begin, step_dir(i)); } stepcount = stepindex - begin; assert(stepcount >= 4); }
/********************************************************************** * C_OUTLINE::C_OUTLINE * * Constructor to build a C_OUTLINE from a C_OUTLINE_FRAG. **********************************************************************/ C_OUTLINE::C_OUTLINE ( //constructor //steps to copy ICOORD startpt, DIR128 * new_steps, inT16 length //length of loop ):start (startpt), offsets(NULL) { inT8 dirdiff; //direction difference DIR128 prevdir; //previous direction DIR128 dir; //current direction DIR128 lastdir; //dir of last step TBOX new_box; //easy bounding inT16 stepindex; //index to step inT16 srcindex; //source steps ICOORD pos; //current position pos = startpt; stepcount = length; // No. of steps. ASSERT_HOST(length >= 0); steps = reinterpret_cast<uinT8*>(alloc_mem(step_mem())); // Get memory. memset(steps, 0, step_mem()); lastdir = new_steps[length - 1]; prevdir = lastdir; for (stepindex = 0, srcindex = 0; srcindex < length; stepindex++, srcindex++) { new_box = TBOX (pos, pos); box += new_box; //copy steps dir = new_steps[srcindex]; set_step(stepindex, dir); dirdiff = dir - prevdir; pos += step (stepindex); if ((dirdiff == 64 || dirdiff == -64) && stepindex > 0) { stepindex -= 2; //cancel there-and-back prevdir = stepindex >= 0 ? step_dir (stepindex) : lastdir; } else prevdir = dir; } ASSERT_HOST (pos.x () == startpt.x () && pos.y () == startpt.y ()); do { dirdiff = step_dir (stepindex - 1) - step_dir (0); if (dirdiff == 64 || dirdiff == -64) { start += step (0); stepindex -= 2; //cancel there-and-back for (int i = 0; i < stepindex; ++i) set_step(i, step_dir(i + 1)); } } while (stepindex > 1 && (dirdiff == 64 || dirdiff == -64)); stepcount = stepindex; ASSERT_HOST (stepcount >= 4); }
void C_OUTLINE::reverse() { //reverse drection DIR128 halfturn = MODULUS / 2; //amount to shift DIR128 stepdir; //direction of step inT16 stepindex; //index to cstep inT16 farindex; //index to other side inT16 halfsteps; //half of stepcount halfsteps = (stepcount + 1) / 2; for (stepindex = 0; stepindex < halfsteps; stepindex++) { farindex = stepcount - stepindex - 1; stepdir = step_dir (stepindex); set_step (stepindex, step_dir (farindex) + halfturn); set_step (farindex, stepdir + halfturn); } }
int OUTLINE::winding_num(Point pt) const{ Point vec = start_pos() - pt; Point step_vec; int cross_product; int count = 0; for (int i = 0; i < path_length(); ++i){ step_vec = step_dir(i); if (vec.y <= 0 && vec.y + step_vec.y > 0){ cross_product = vec.cross_product(step_vec); if (cross_product > 0) //ÓÒ±ßÏòÉÏ ++count; else if (cross_product == 0) return INTERSECTING; } else if (vec.y > 0 && vec.y + step_vec.y <= 0){ cross_product = vec.cross_product(step_vec); if (cross_product < 0) //ÓÒ±ßÏòÏ --count; else if (cross_product == 0) return INTERSECTING; } vec += step_vec; } return count; }
inT16 C_OUTLINE::turn_direction() const { //winding number DIR128 prevdir; //previous direction DIR128 dir; //current direction inT16 stepindex; //index to cstep inT8 dirdiff; //direction difference inT16 count; //winding count if (stepcount == 0) return 128; count = 0; prevdir = step_dir (stepcount - 1); for (stepindex = 0; stepindex < stepcount; stepindex++) { dir = step_dir (stepindex); dirdiff = dir - prevdir; ASSERT_HOST (dirdiff == 0 || dirdiff == 32 || dirdiff == -32); count += dirdiff; prevdir = dir; } ASSERT_HOST (count == 128 || count == -128); return count; //winding number }
int OUTLINE::area() const{ Point pos = start_pos(); int total = 0; for (int i = 0; i < path_length(); ++i){ DIR dir = step_dir(i); Point dir_vec = dir; if (dir_vec.x > 0) total += pos.y; else if (dir_vec.x < 0) total -= pos.y; pos += dir_vec; } return total; }
C_OUTLINE::C_OUTLINE( //constructor C_OUTLINE *srcline, //outline to FCOORD rotation //rotate ) : offsets(NULL) { TBOX new_box; //easy bounding inT16 stepindex; //index to step inT16 dirdiff; //direction change ICOORD pos; //current position ICOORD prevpos; //previous dest point ICOORD destpos; //destination point inT16 destindex; //index to step DIR128 dir; //coded direction uinT8 new_step; stepcount = srcline->stepcount * 2; if (stepcount == 0) { steps = NULL; box = srcline->box; box.rotate(rotation); return; } //get memory steps = (uinT8 *) alloc_mem (step_mem()); memset(steps, 0, step_mem()); for (int iteration = 0; iteration < 2; ++iteration) { DIR128 round1 = iteration == 0 ? 32 : 0; DIR128 round2 = iteration != 0 ? 32 : 0; pos = srcline->start; prevpos = pos; prevpos.rotate (rotation); start = prevpos; box = TBOX (start, start); destindex = 0; for (stepindex = 0; stepindex < srcline->stepcount; stepindex++) { pos += srcline->step (stepindex); destpos = pos; destpos.rotate (rotation); // tprintf("%i %i %i %i ", destpos.x(), destpos.y(), pos.x(), pos.y()); while (destpos.x () != prevpos.x () || destpos.y () != prevpos.y ()) { dir = DIR128 (FCOORD (destpos - prevpos)); dir += 64; //turn to step style new_step = dir.get_dir (); // tprintf(" %i\n", new_step); if (new_step & 31) { set_step(destindex++, dir + round1); prevpos += step(destindex - 1); if (destindex < 2 || ((dirdiff = step_dir (destindex - 1) - step_dir (destindex - 2)) != -64 && dirdiff != 64)) { set_step(destindex++, dir + round2); prevpos += step(destindex - 1); } else { prevpos -= step(destindex - 1); destindex--; prevpos -= step(destindex - 1); set_step(destindex - 1, dir + round2); prevpos += step(destindex - 1); } } else { set_step(destindex++, dir); prevpos += step(destindex - 1); } while (destindex >= 2 && ((dirdiff = step_dir (destindex - 1) - step_dir (destindex - 2)) == -64 || dirdiff == 64)) { prevpos -= step(destindex - 1); prevpos -= step(destindex - 2); destindex -= 2; // Forget u turn } //ASSERT_HOST(prevpos.x() == destpos.x() && prevpos.y() == destpos.y()); new_box = TBOX (destpos, destpos); box += new_box; } } ASSERT_HOST (destpos.x () == start.x () && destpos.y () == start.y ()); dirdiff = step_dir (destindex - 1) - step_dir (0); while ((dirdiff == 64 || dirdiff == -64) && destindex > 1) { start += step (0); destindex -= 2; for (int i = 0; i < destindex; ++i) set_step(i, step_dir(i + 1)); dirdiff = step_dir (destindex - 1) - step_dir (0); } if (destindex >= 4) break; } ASSERT_HOST(destindex <= stepcount); stepcount = destindex; destpos = start; for (stepindex = 0; stepindex < stepcount; stepindex++) { destpos += step (stepindex); } ASSERT_HOST (destpos.x () == start.x () && destpos.y () == start.y ()); }