📄 fpchop.cpp
字号:
delete srcline; //smashed up } else { if (srcbox.left () + srcbox.right () <= chop_coord * 2) //stick whole in left left_it->add_after_then_move (srcline); else right_it->add_before_stay_put (srcline); } }}/********************************************************************** * fixed_chop_outline * * Chop the given outline (if necessary) placing the fragments which * fall either side of the chop line into the appropriate list. * If the outline lies too heavily to one side to chop, FALSE is returned. **********************************************************************/BOOL8 fixed_chop_outline( //chop the outline OUTLINE *srcline, //source outline INT16 chop_coord, //place to chop float pitch_error, //allowed deviation OUTLINE_FRAG_LIST *left_frags, //left half of chop OUTLINE_FRAG_LIST *right_frags //right half of chop ) { BOOL8 not_first; //fragment BOOL8 test_valid; //test pt valid float left_edge; //of outline FCOORD chop_pos; //coords of chop float chop_starty; //test chop pt POLYPT *startpt; //in first fragment //general iterator POLYPT_IT poly_it = srcline->polypts (); POLYPT_IT head_it; //head of fragment POLYPT_IT tail_it; //tail of fragment POLYPT_IT test_tail; //possible chop pt left_edge = poly_it.data ()->pos.x (); tail_it = poly_it; for (poly_it.mark_cycle_pt (); !poly_it.cycled_list (); poly_it.forward ()) { if (poly_it.data ()->pos.x () < left_edge) { left_edge = poly_it.data ()->pos.x (); tail_it = poly_it; //find leftmost pt } } if (left_edge >= chop_coord - pitch_error) return FALSE; //not worth it startpt = tail_it.data (); not_first = FALSE; head_it = tail_it; chop_starty = tail_it.data ()->pos.y (); do { test_valid = FALSE; do { tail_it.forward (); if (test_valid && tail_it.data ()->pos.x () >= chop_coord && tail_it.data ()->pos.x () + tail_it.data ()->vec.x () <= chop_coord) { chop_pos = find_chop_coords (&tail_it, chop_coord); if (chop_pos.y () >= chop_starty) test_valid = FALSE; else { tail_it = test_tail; break; //must chop there } } if (tail_it.data ()->pos.x () <= chop_coord && tail_it.data ()->pos.x () + tail_it.data ()->vec.x () >= chop_coord) { chop_pos = find_chop_coords (&tail_it, chop_coord); chop_starty = chop_pos.y (); test_tail = tail_it; //save possible chop pt test_valid = TRUE; if (tail_it.data ()->vec.x () == 0 && tail_it.data ()->vec.y () < 0) break; //must chop here } } while (tail_it.data () != startpt && tail_it.data ()->pos.x () < chop_coord + pitch_error); //back to start if (tail_it.data () == startpt) { if (not_first) break; else return FALSE; //doesn't cross line } while (tail_it.data ()->pos.x () > chop_coord) tail_it.backward (); if (head_it.data () == tail_it.data ()) insert_extra_pt(&tail_it); insert_chop_pt(&tail_it, chop_coord); if (not_first) { save_chop_fragment(&head_it, &tail_it, left_frags); } else { tail_it.forward (); head_it = tail_it; } test_valid = FALSE; do { tail_it.forward (); if (test_valid && tail_it.data ()->pos.x () <= chop_coord && tail_it.data ()->pos.x () + tail_it.data ()->vec.x () >= chop_coord) { chop_pos = find_chop_coords (&tail_it, chop_coord); if (chop_pos.y () <= chop_starty) test_valid = FALSE; else { tail_it = test_tail; break; //must chop there } } if (tail_it.data ()->pos.x () >= chop_coord && tail_it.data ()->pos.x () + tail_it.data ()->vec.x () <= chop_coord) { chop_pos = find_chop_coords (&tail_it, chop_coord); chop_starty = chop_pos.y (); test_tail = tail_it; test_valid = TRUE; //save possible chop pt if (tail_it.data ()->vec.x () == 0 && tail_it.data ()->vec.y () > 0) break; //must chop here } } while (tail_it.data () != startpt && tail_it.data ()->pos.x () > chop_coord - pitch_error); while (tail_it.data ()->pos.x () < chop_coord) tail_it.backward (); if (head_it.data () == tail_it.data ()) insert_extra_pt(&tail_it); insert_chop_pt(&tail_it, chop_coord); save_chop_fragment(&head_it, &tail_it, right_frags); not_first = TRUE; } while (tail_it.data () != startpt); startpt = head_it.data_relative (-1); while (tail_it.data () != startpt) tail_it.forward (); save_chop_fragment(&head_it, &tail_it, left_frags); return TRUE; //did some chopping}/********************************************************************** * save_chop_fragment * * Store the given fragment in the given fragment list. **********************************************************************/void save_chop_fragment( //chop the outline POLYPT_IT *head_it, //head of fragment POLYPT_IT *tail_it, //tail of fragment OUTLINE_FRAG_LIST *frags //fragment list ) { OUTLINE_FRAG *head; //head of fragment OUTLINE_FRAG *tail; //tail of fragment float tail_y; //ycoord of tail tail_y = tail_it->data ()->pos.y (); head = new OUTLINE_FRAG (head_it, tail_it); tail = new OUTLINE_FRAG (head, tail_y); head->other_end = tail; add_frag_to_list(head, frags); add_frag_to_list(tail, frags); head_it->forward (); tail_it->forward ();}/********************************************************************** * OUTLINE_FRAG::OUTLINE_FRAG * * Constructors for OUTLINE_FRAG. **********************************************************************/OUTLINE_FRAG::OUTLINE_FRAG( //record fragment POLYPT_IT *head_it, //head of fragment POLYPT_IT *tail_it //tail of fragment ) { ycoord = head_it->data ()->pos.y (); other_end = NULL; polypts.assign_to_sublist (head_it, tail_it);}OUTLINE_FRAG::OUTLINE_FRAG( //record fragment OUTLINE_FRAG *head, //other end float tail_y) { ycoord = tail_y; other_end = head;}/********************************************************************** * add_frag_to_list * * Insert the fragment in the list at the appropriate place to keep * them in ascending ycoord order. **********************************************************************/void add_frag_to_list( //ordered add OUTLINE_FRAG *frag, //fragment to add OUTLINE_FRAG_LIST *frags //fragment list ) { //output list OUTLINE_FRAG_IT frag_it = frags; if (!frags->empty ()) { for (frag_it.mark_cycle_pt (); !frag_it.cycled_list (); frag_it.forward ()) { if (frag_it.data ()->ycoord >= frag->ycoord) { frag_it.add_before_then_move (frag); return; } } } frag_it.add_to_end (frag);}/********************************************************************** * insert_chop_pt * * Decide whether or not to use the actual point as chop coord. * Insert either a duplicate of the current point or 2 copies * of the new chop point. Position the iterator at the first. **********************************************************************/void insert_chop_pt( //make chop POLYPT_IT *it, //iterator INT16 chop_coord //required chop pt ) { POLYPT *prev_pt; //point befor chop POLYPT *chop_pt; //new vertex FCOORD chop_pos; //coords of chop FCOORD chop_vec; //vector to next prev_pt = it->data (); if (prev_pt->pos.x () + textord_fp_chop_snap >= chop_coord && prev_pt->pos.x () - textord_fp_chop_snap <= chop_coord) { chop_pt = new POLYPT (prev_pt->pos, prev_pt->vec); } else { chop_pos = FCOORD (chop_coord, prev_pt->pos.y () + prev_pt->vec.y () * (chop_coord - prev_pt->pos.x ()) / prev_pt->vec.x ()); chop_vec = it->data_relative (1)->pos - chop_pos; chop_pt = new POLYPT (chop_pos, chop_vec); it->add_after_then_move (chop_pt); chop_pt = new POLYPT (chop_pos, chop_vec); } it->add_after_stay_put (chop_pt);}/********************************************************************** * find_chop_coords * * Decide whether or not to use the actual point as chop coord. * Return the coords of the chop point. **********************************************************************/FCOORD find_chop_coords( //make chop POLYPT_IT *it, //iterator INT16 chop_coord //required chop pt ) { POLYPT *prev_pt; //point befor chop FCOORD chop_pos; //coords of chop prev_pt = it->data (); if (prev_pt->pos.x () + textord_fp_chop_snap >= chop_coord && prev_pt->pos.x () - textord_fp_chop_snap <= chop_coord) { chop_pos = prev_pt->pos; } else { chop_pos = FCOORD (chop_coord, prev_pt->pos.y () + prev_pt->vec.y () * (chop_coord - prev_pt->pos.x ()) / prev_pt->vec.x ()); } return chop_pos;}/********************************************************************** * insert_extra_pt * * Add an extra pt to prevent single point fragments being made. **********************************************************************/void insert_extra_pt( //make extra POLYPT_IT *it //iterator ) { POLYPT *prev_pt; //point befor chop POLYPT *chop_pt; //new vertex FCOORD chop_pos; //coords of chop FCOORD chop_vec; //vector to next prev_pt = it->data (); if (it->data_relative (1)->pos.y () > it->data_relative (-1)->pos.y ()) { chop_pos = prev_pt->pos + FCOORD (0.0f,
static_cast<float>(textord_fp_chop_snap)); } else { chop_pos = prev_pt->pos - FCOORD (0.0f, static_cast<float>(textord_fp_chop_snap));
} chop_vec = it->data_relative (1)->pos - chop_pos; prev_pt->vec = chop_pos - prev_pt->pos; chop_pt = new POLYPT (chop_pos, chop_vec); it->add_after_then_move (chop_pt);}/********************************************************************** * close_chopped_fragments * * Clear the given list of fragments joining them up into outlines. * Each outline made soaks up any of the child outlines which it encloses. **********************************************************************/void close_chopped_fragments( //chop the outline OUTLINE_FRAG_LIST *frags, //list to clear OUTLINE_LIST *children, //potential children OUTLINE_IT *dest_it //output list ) { //iterator OUTLINE_FRAG_IT frag_it = frags; OUTLINE_FRAG *bottom_frag; //bottom of cut OUTLINE_FRAG *top_frag; //top of cut OUTLINE *outline; //new outline OUTLINE *child; //current child OUTLINE_IT child_it = children; OUTLINE_IT olchild_it; //children of outline POLYPT_IT poly_it; //iterator for constr while (!frag_it.empty ()) { frag_it.move_to_first (); //get bottom one bottom_frag = frag_it.extract (); frag_it.forward (); //and one above it top_frag = frag_it.extract (); while (top_frag->other_end != bottom_frag) { do { frag_it.forward (); } //find other end while (frag_it.data () != top_frag->other_end); join_chopped_fragments(bottom_frag, top_frag); delete top_frag; delete frag_it.extract (); //remove middle section frag_it.forward (); top_frag = frag_it.extract (); } join_chopped_fragments(bottom_frag, top_frag); if (bottom_frag->polypts.empty ()) poly_it.set_to_list (&top_frag->polypts); else poly_it.set_to_list (&bottom_frag->polypts); outline = new OUTLINE (&poly_it); olchild_it.set_to_list (outline->child ()); for (child_it.mark_cycle_pt (); !child_it.cycled_list (); child_it.forward ()) { child = child_it.data (); if (*child < *outline) olchild_it.add_to_end (child_it.extract ()); } dest_it->add_after_then_move (outline); } while (!child_it.empty ()) { dest_it->add_after_then_move (child_it.extract ()); child_it.forward (); }}/********************************************************************** * join_chopped_fragments * * Join the two lists of POLYPTs such that the first OUTLINE_FRAG * operand keeps responsibility for the fragment. **********************************************************************/void join_chopped_fragments( //join pieces OUTLINE_FRAG *bottom, //bottom of cut OUTLINE_FRAG *top //top of cut ) { POLYPT_IT master_it; //dest list POLYPT_IT slave_it; //src list POLYPT *cutpt; //vectors to change POLYPT *nextpt; //other end of cut if (bottom->polypts.empty ()) { master_it.set_to_list (&bottom->other_end->polypts); cutpt = master_it.data_relative (-1); ASSERT_HOST (!top->polypts.empty ()); slave_it.set_to_list (&top->polypts); nextpt = slave_it.data (); if (bottom->other_end != top) { master_it.move_to_last (); master_it.add_list_after (&top->polypts); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -