📄 polyaprx.cpp
字号:
/********************************************************************** * File: polyaprx.cpp (Formerly polygon.c) * Description: Code for polygonal approximation from old edgeprog. * Author: Ray Smith * Created: Thu Nov 25 11:42:04 GMT 1993 * * (C) Copyright 1993, Hewlett-Packard Ltd. ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** http://www.apache.org/licenses/LICENSE-2.0 ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. * **********************************************************************/#include "mfcpch.h"#include <stdio.h>#ifdef __UNIX__#include <assert.h>#endif//#include "edgeloop.h"#define MAXEDGELENGTH 16000 //must replace#include "polyaprx.h"#include "varable.h"#include "tprintf.h"#define EXTERNEXTERN BOOL_VAR (poly_debug, FALSE, "Debug old poly");EXTERN BOOL_VAR (poly_wide_objects_better, TRUE,"More accurate approx on wide things");static int par1, par2;#define CONVEX 1 /*OUTLINE point is convex */#define CONCAVE 2 /*used and set only in edges */#define FIXED 4 /*OUTLINE point is fixed */#define ONHULL 8 /*on convex hull */#define RUNLENGTH 1 /*length of run */#define DIR 2 /*direction of run */#define CORRECTION 3 /*correction of run *///#define MAXSHORT 32767 /*max value of short*/#define FLAGS 0#define fixed_dist 20 //really an int_variable#define approx_dist 15 //really an int_variable#define point_diff(p,p1,p2) (p).x = (p1).x - (p2).x ; (p).y = (p1).y - (p2).y#define CROSS(a,b) ((a).x * (b).y - (a).y * (b).x)#define LENGTH(a) ((a).x * (a).x + (a).y * (a).y)#define DISTANCE(a,b) (((b).x-(a).x) * ((b).x-(a).x) \ + ((b).y-(a).y) * ((b).y-(a).y))/********************************************************************** * tesspoly_outline * * Approximate an outline from c form using the old tess algorithm. **********************************************************************/OUTLINE *tesspoly_outline( //old approximation C_OUTLINE *c_outline, //input float //xheight ) { EDGEPT *edgept; //converted steps EDGEPT *startpt; //start of outline TBOX loop_box; //bounding box inT32 area; //loop area FCOORD pos; //vertex FCOORD vec; //vector POLYPT_LIST polypts; //output polygon POLYPT *polypt; //converted point POLYPT_IT poly_it = &polypts; //iterator EDGEPT edgepts[MAXEDGELENGTH]; //converted path loop_box = c_outline->bounding_box (); area = loop_box.height (); if (!poly_wide_objects_better && loop_box.width () > area) area = loop_box.width (); area *= area; edgept = edgesteps_to_edgepts (c_outline, edgepts); fix2(edgepts, area); edgept = poly2 (edgepts, area);/*2nd approximation */ startpt = edgept; do { pos = FCOORD (edgept->pos.x, edgept->pos.y); vec = FCOORD (edgept->vec.x, edgept->vec.y); polypt = new POLYPT (pos, vec); //add to list poly_it.add_after_then_move (polypt); edgept = edgept->next; } while (edgept != startpt); if (poly_it.length () <= 2) return NULL; else //turn to outline return new OUTLINE (&poly_it);}/********************************************************************** * edgesteps_to_edgepts * * Convert a C_OUTLINE to EDGEPTs. **********************************************************************/EDGEPT *edgesteps_to_edgepts ( //convert outlineC_OUTLINE * c_outline, //inputEDGEPT edgepts[] //output is array) { inT32 length; //steps in path ICOORD pos; //current coords inT32 stepindex; //current step inT32 stepinc; //increment inT32 epindex; //current EDGEPT inT32 count; //repeated steps ICOORD vec; //for this 8 step ICOORD prev_vec; inT8 epdir; //of this step DIR128 prevdir; //prvious dir DIR128 dir; //of this step pos = c_outline->start_pos (); //start of loop length = c_outline->pathlength (); stepindex = 0; epindex = 0; prevdir = -1; count = 0; do { dir = c_outline->step_dir (stepindex); vec = c_outline->step (stepindex); if (stepindex < length - 1 && c_outline->step_dir (stepindex + 1) - dir == -32) { dir += 128 - 16; vec += c_outline->step (stepindex + 1); stepinc = 2; } else stepinc = 1; if (count == 0) { prevdir = dir; prev_vec = vec; } if (prevdir.get_dir () != dir.get_dir ()) { edgepts[epindex].pos.x = pos.x (); edgepts[epindex].pos.y = pos.y (); prev_vec *= count; edgepts[epindex].vec.x = prev_vec.x (); edgepts[epindex].vec.y = prev_vec.y (); pos += prev_vec; edgepts[epindex].flags[RUNLENGTH] = count; edgepts[epindex].prev = &edgepts[epindex - 1]; edgepts[epindex].flags[FLAGS] = 0; edgepts[epindex].next = &edgepts[epindex + 1]; prevdir += 64; epdir = (DIR128) 0 - prevdir; epdir >>= 4; epdir &= 7; edgepts[epindex].flags[DIR] = epdir; epindex++; prevdir = dir; prev_vec = vec; count = 1; } else count++; stepindex += stepinc; } while (stepindex < length); edgepts[epindex].pos.x = pos.x (); edgepts[epindex].pos.y = pos.y (); prev_vec *= count; edgepts[epindex].vec.x = prev_vec.x (); edgepts[epindex].vec.y = prev_vec.y (); pos += prev_vec; edgepts[epindex].flags[RUNLENGTH] = count; edgepts[epindex].flags[FLAGS] = 0; edgepts[epindex].prev = &edgepts[epindex - 1]; edgepts[epindex].next = &edgepts[0]; prevdir += 64; epdir = (DIR128) 0 - prevdir; epdir >>= 4; epdir &= 7; edgepts[epindex].flags[DIR] = epdir; edgepts[0].prev = &edgepts[epindex]; ASSERT_HOST (pos.x () == c_outline->start_pos ().x () && pos.y () == c_outline->start_pos ().y ()); return &edgepts[0];}/********************************************************************** *fix2(start,area) fixes points on the outline according to a trial method* **********************************************************************///#pragma OPT_LEVEL 1 /*stop compiler bugs*/void fix2( //polygonal approx EDGEPT *start, /*loop to approimate */ int area) { register EDGEPT *edgept; /*current point */ register EDGEPT *edgept1; register EDGEPT *loopstart; /*modified start of loop */ register EDGEPT *linestart; /*start of line segment */ register int dir1, dir2; /*directions of line */ register int sum1, sum2; /*lengths in dir1,dir2 */ int stopped; /*completed flag */ int fixed_count; //no of fixed points int d01, d12, d23, gapmin; TPOINT d01vec, d12vec, d23vec; register EDGEPT *edgefix, *startfix; register EDGEPT *edgefix0, *edgefix1, *edgefix2, *edgefix3; edgept = start; /*start of loop */ while (((edgept->flags[DIR] - edgept->prev->flags[DIR] + 1) & 7) < 3 && (dir1 = (edgept->prev->flags[DIR] - edgept->next->flags[DIR]) & 7) != 2 && dir1 != 6) edgept = edgept->next; /*find suitable start */ loopstart = edgept; /*remember start */ stopped = 0; /*not finished yet */ edgept->flags[FLAGS] |= FIXED; /*fix it */ do { linestart = edgept; /*possible start of line */ dir1 = edgept->flags[DIR]; /*first direction */ /*length of dir1 */ sum1 = edgept->flags[RUNLENGTH]; edgept = edgept->next; dir2 = edgept->flags[DIR]; /*2nd direction */ /*length in dir2 */ sum2 = edgept->flags[RUNLENGTH]; if (((dir1 - dir2 + 1) & 7) < 3) { while (edgept->prev->flags[DIR] == edgept->next->flags[DIR]) { edgept = edgept->next; /*look at next */ if (edgept->flags[DIR] == dir1) /*sum lengths */ sum1 += edgept->flags[RUNLENGTH]; else sum2 += edgept->flags[RUNLENGTH]; } if (edgept == loopstart) stopped = 1; /*finished */ if (sum2 + sum1 > 2 && linestart->prev->flags[DIR] == dir2 && (linestart->prev->flags[RUNLENGTH] > linestart->flags[RUNLENGTH] || sum2 > sum1)) { /*start is back one */ linestart = linestart->prev; linestart->flags[FLAGS] |= FIXED; } if (((edgept->next->flags[DIR] - edgept->flags[DIR] + 1) & 7) >= 3 || (edgept->flags[DIR] == dir1 && sum1 >= sum2) || ((edgept->prev->flags[RUNLENGTH] < edgept->flags[RUNLENGTH] || (edgept->flags[DIR] == dir2 && sum2 >= sum1)) && linestart->next != edgept)) edgept = edgept->next; } /*sharp bend */ edgept->flags[FLAGS] |= FIXED; } /*do whole loop */ while (edgept != loopstart && !stopped); edgept = start; do { if (((edgept->flags[RUNLENGTH] >= 8) && (edgept->flags[DIR] != 2) && (edgept->flags[DIR] != 6)) || ((edgept->flags[RUNLENGTH] >= 8) && ((edgept->flags[DIR] == 2) || (edgept->flags[DIR] == 6)))) { edgept->flags[FLAGS] |= FIXED; edgept1 = edgept->next; edgept1->flags[FLAGS] |= FIXED; } edgept = edgept->next; } while (edgept != start); edgept = start; do { /*single fixed step */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -