📄 abstract_character.cpp
字号:
* 获得字符真实高度 * 参数:c 字符 * angle 角度 * 返回:高度******************************************************************************/float abstract_character::get_real_height(const character &c, float angle){ transformation T(angle, 1, (c.min_x+c.max_x)/2.0, -c.max_y); for(list<singular_point>::const_iterator i=c.spl.begin(); i!=c.spl.end(); ++i) { float x,y; for(list<inner_sequence_start>::const_iterator j=i->sequences.begin(); j!=i->sequences.end(); ++j) { if( j->is_start ) { for(list<skeleton_sequence>::const_iterator k=j->connect->sseql.begin(); k!=j->connect->sseql.end(); ++k) stroke(T, c.line_thickness, k->first->aligned_x, k->first->aligned_y, k->last->aligned_x, k->last->aligned_y); if( !j->connect->sseql.empty() ) { stroke(T, c.line_thickness, i->x, i->y, j->connect->sseql.front().first->aligned_x, j->connect->sseql.front().first->aligned_x); stroke(T, c.line_thickness, j->connect->sseql.back().last->aligned_x, j->connect->sseql.back().last->aligned_y, j->connect->point2->x, j->connect->point2->y); } } } T.transform(i->x,i->y,x,y); } return T.transformed_height();}/****************************************************************************** * 构造函数******************************************************************************/abstract_character::abstract_character(const character &c, float base_line_pos, float reference_height, float angle){ if( base_line_pos==FLT_MAX ) base_line_pos=-c.max_y; else base_line_pos=-c.max_y-base_line_pos; if( reference_height==0 ) reference_height=c.max_y-c.min_y+1; // 确保size总是>=1 transformation T(angle, 1/reference_height, (c.min_x+c.max_x)/2.0, base_line_pos); hash_map<const singular_point*, int, hash<const singular_point*> > spmap; hash_map<const connection*, int, hash<const connection*> > conmap; // 预申请内存 int num_sp=0; int num_con=0; for(list<singular_point>::const_iterator i=c.spl.begin(); i!=c.spl.end(); ++i) { num_sp++; for(list< inner_sequence_start >::const_iterator j=i->sequences.begin(); j!=i->sequences.end(); ++j) if( j->is_start ) num_con++; } aspv.reserve(num_sp); acv.reserve(num_con); for(list<singular_point>::const_iterator i=c.spl.begin(); i!=c.spl.end(); ++i) resolve_sp(&(*i),spmap,conmap,T); // 旋转后纠正x坐标 float center_x=(T.minx()+T.maxx())/2; for(vector<abstract_singular_point>::iterator i=aspv.begin(); i!=aspv.end(); ++i) i->x-=center_x; for(vector<abstract_connection>::iterator i=acv.begin(); i!=acv.end(); ++i) for(list< point<float> >::iterator j=i->polyline.begin(); j!=i->polyline.end(); ++j) j->x-=center_x;}/****************************************************************************** * 写文件******************************************************************************/void abstract_character::write(fstream &fs) const{ ostream &o=fs; for(vector<abstract_singular_point>::const_iterator i=aspv.begin(); i!=aspv.end(); ++i) { o << i->x << ' ' << i->y << ' ' << i->type; for(list<int>::const_iterator j=i->acl.begin(); j!=i->acl.end(); ++j) o << ' ' << *j; o << '\n'; } o << "CON\n"; for(vector<abstract_connection>::const_iterator i=acv.begin(); i!=acv.end(); ++i) { o << i->singular_point_1 << ' ' << i->singular_point_2 << ' ' << i->type; for(list< point<float> >::const_iterator j=i->polyline.begin(); j!=i->polyline.end(); ++j) o << ' ' << j->x << ',' << j->y; o << '\n'; } o << '\n';}/****************************************************************************** * 读文件******************************************************************************/void abstract_character::read(fstream &fs){ int max_sp=-1, max_con=-1; istream &is=fs; aspv.clear(); acv.clear(); string s; char *endptr; while( (s=get_next_token(is))!="" ) { if( s=="CON" ) break; aspv.push_back( abstract_singular_point() ); abstract_singular_point &asp=aspv.back(); asp.x=strtod(s.c_str(),&endptr); asp.y=get_next_float(is); s=get_next_token(is); if( s=="end_point" ) asp.type=end_point; else if( s=="branching_point" ) asp.type=branching_point; else asp.type=turning_point; while( (s=get_next_token(is))!="" && s!="\n" ) asp.acl.push_back( my_max(strtol(s.c_str(),&endptr,10),max_con) ); } get_next_token(is); // nl while( (s=get_next_token(is))!="" && s!="\n" ) { acv.push_back( abstract_connection() ); abstract_connection &ac=acv.back(); ac.singular_point_1=my_max(strtol(s.c_str(),&endptr,10),max_sp); ac.singular_point_2=my_max(get_next_int(is),max_sp); s=get_next_token(is); if( s=="straight" ) ac.type=straight; else if( s=="left_curved" ) ac.type=left_curved; else ac.type=right_curved; while( is.peek()!=EOF && static_cast<char>(is.peek())!='\n' ) { float x=get_next_float(is); get_next_token(is); float y=get_next_float(is); ac.polyline.push_back( point<float>(x,y) ); } get_next_token(is); } assert( max_sp < static_cast<int>(aspv.size()) && max_con < static_cast<int>(acv.size()) );}/****************************************************************************** * 增加连接******************************************************************************/void abstract_singular_point::add_connection(int cnr){ // 确保元素唯一 for(list<int>::iterator i=acl.begin(); i!=acl.end(); ++i) if( *i==cnr ) return; acl.push_back(cnr);}/****************************************************************************** * 重置匹配状态******************************************************************************/void abstract_character::reset_matching_state(){ for(vector<abstract_connection>::iterator i=acv.begin(); i!=acv.end(); ++i) i->reset_matching_state();}/****************************************************************************** * line类******************************************************************************/struct line : public straight_line{ line(const point<float> &start_point, const point<float> &end_point) : straight_line(start_point.x,start_point.y,end_point.x,end_point.y), start(start_point), end(end_point) {} bool is_on_line(point<float> p) const; bool intersect_line(const line &l, point<float> &p, bool &have_straight_intersection) const; bool intersect_line(const line &l, point<float> &p) const; point<float> start; point<float> end;};/****************************************************************************** * 判断一个点是否在线上 * 参数:p 点 * 返回:在线上,返回true;否则返回false******************************************************************************/bool line::is_on_line(point<float> p) const{ return is_part_of(start.x,start.y, end.x,end.y, p.x,p.y);}/****************************************************************************** * 交叉线******************************************************************************/bool line::intersect_line(const line &l, point<float> &p) const{ return intersect(l,p.x,p.y) && is_on_line(p) && l.is_on_line(p);}/****************************************************************************** * 交叉线******************************************************************************/bool line::intersect_line(const line &l, point<float> &p, bool &have_straight_intersection) const{ return (have_straight_intersection=intersect(l,p.x,p.y)) && is_on_line(p) && l.is_on_line(p);}/****************************************************************************** * check_point结构******************************************************************************/struct check_point{ typedef enum {db_end_point, other_end_point, intersection_point} check_point_type; check_point_type type; // check_point的类型 point<float> db_cpoint; // 参考线上的点 point<float> other_cpoint; // 直线上另一边的对应点 line* db_line; line* other_line; bool is_valid; bool source_is_db; bool is_start; float coefficient; check_point() {} check_point(line& db, line& other, bool isdb, bool isstart); check_point(const point<float> p, line& rl, line& other) : type(intersection_point), db_cpoint(p), other_cpoint(p), db_line(&rl), other_line(&other), is_valid(true) { set_line_coefficient(); coefficient+=10*FLT_EPSILON; } void set_line_coefficient(); float line_coefficient() const { return coefficient; } bool operator<(const check_point& c) const { return line_coefficient()<c.line_coefficient(); }};/****************************************************************************** * 构造函数******************************************************************************/check_point::check_point(line& db, line& other, bool isdb, bool isstart) : db_line(&db), other_line(&other), source_is_db(isdb), is_start(isstart){ if( source_is_db ) { type=db_end_point; db_cpoint=is_start ? db_line->start : db_line->end; is_valid=other_line->intersect(db_line->normal(db_cpoint.x,db_cpoint.y),other_cpoint.x,other_cpoint.y) && other_line->is_on_line(other_cpoint); } else { type=other_end_point; other_cpoint=is_start ? other_line->start : other_line->end; db_line->construct_perpendicular(other_cpoint.x,other_cpoint.y,db_cpoint.x,db_cpoint.y); is_valid=db_line->is_on_line(db_cpoint); } set_line_coefficient();}/****************************************************************************** * 设置line的相关系数******************************************************************************/void check_point::set_line_coefficient(){ // 参考向量 const float v1 = db_line->end.x-db_line->start.x; const float v2 = db_line->end.y-db_line->start.y; // 测试向量 const float w1 = db_cpoint.x-db_line->start.x; const float w2 = db_cpoint.y-db_line->start.y; // 卷积 coefficient = v1*w1+v2*w2;}bool path::match_connection(const path &other_path, float &divergence, match_debug_info *mdi) const{ #ifdef DEBUG_MATCHING if( mdi ) { cout << "--- match_connection ---" << endl; cout << "database path: " << *this << endl; cout << "real path : " << other_path << endl; } #endif float total_area=0; match_debug_info curr_mdi; // 数据库端 const_iterator db_iter=begin(); const_iterator db_end=end(); line db_line(*db_iter, *(++db_iter)); line new_db_line=db_line; // 其它端 const_iterator other_iter=other_path.begin(); const_iterator other_end=other_path.end(); line other_line(*other_iter, *(++other_iter)); line new_other_line=other_line; bool run_loop=true; float weight; do { weight=other_iter.get_weight(); slist<check_point> cpl; for(int i=0; i<4; i++) cpl.insert_sorted( check_point(db_line,other_line,i<2,i%2) ); bool have_intersection, have_line_intersection; point<float> p_intersect; if( (have_line_intersection=db_line.intersect_line(other_line,p_intersect,have_intersection)) ) cpl.insert_sorted( check_point(p_intersect,db_line,other_line) ); point<float>* other_line_lower_start=NULL; slist<check_point>::iterator i=cpl.begin(); while( !is_equal(euklidian_distance(new_db_line.start.x,new_db_line.start.y, new_db_line.end.x,new_db_line.end.y),0) && !is_equal(euklidian_distance(new_other_line.start.x,new_other_line.start.y, new_other_line.end.x,new_other_line.end.y),0) ) { check_point &first=*i; check_point &second=*(++i); if( !other_line_lower_start && first.type==check_point::other_end_point ) other_line_lower_start=first.is_start?&new_other_line.start:&new_other_line.end; if( !other_line_lower_start && second.type==check_point::other_end_point ) other_line_lower_start=second.is_start?&new_other_line.start:&new_other_line.end; if( first.is_valid ) // 计算包围域 { float tmp_area=fabs(0.5 *((first.db_cpoint.x-first.other_cpoint.x) * (first.db_cpoint.y+first.other_cpoint.y)+ (first.other_cpoint.x-second.other_cpoint.x) * (first.other_cpoint.y+second.other_cpoint.y)+ (second.other_cpoint.x-second.db_cpoint.x) * (second.other_cpoint.y+second.db_cpoint.y)+ (second.db_cpoint.x-first.db_cpoint.x) * (second.db_cpoint.y+first.db_cpoint.y))); int color=0; if( have_intersection ) { float angle=fabs(angle_between(db_line.start.x,db_line.start.y, p_intersect.x,p_intersect.y, other_line.start.x,other_line.start.y)); if( angle>M_PI_2 ) angle=M_PI-angle; float tmp_area2=euklidian_distance(first.other_cpoint.x,first.other_cpoint.y, second.other_cpoint.x,second.other_cpoint.y); tmp_area2=angle/M_PI_2*tmp_area2*tmp_area2; if( tmp_area2>tmp_area ) { tmp_area=tmp_area2; color=1; } } if ( mdi ) curr_mdi.add_square(first.db_cpoint,first.other_cpoint,second.other_cpoint,second.db_cpoint,color); total_area+=weight*tmp_area; // 通过匹配线削短余下的线 new_db_line.start=second.db_cpoint; *other_line_lower_start=second.other_cpoint; } else // 未匹配的线段 { float segment_area; if( first.source_is_db ) { if( mdi )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -