int process_contour(Image *img, Rect clipr, uchar *cimg, int w, int h, int st, uchar *colors) { int i; short *pt; int npt, apt; Contour contr; apt = 32768; pt = malloc(2 * apt * sizeof pt[0]); uchar color[4]; enum { MaxError = 5 }; /* highlight cracks */ drawrect(img, clipr, color(0x00, 0xff, 0x00, 0xff)); Tess tess[16]; for(i = 0; i < nelem(tess); i++) inittess(tess+i); initcontour(&contr, cimg, w, h, st); int fid; while((npt = nextcontour(&contr, pt, apt, 0, &fid)) != -1){ short orig[2] = { -1, -1 }; int area; int poly[4096]; int npoly; if(npt == apt){ fprintf(stderr, "out of points!\n"); continue; } area = ptarea(pt, npt, orig); if(area > 0){ if((npoly = fitpoly(poly, nelem(poly), pt, npt, MaxError)) == -1) continue; /* not enough points */ if(npoly == nelem(poly) || npoly < 3) continue; if(polyarea(pt, poly, npoly, orig) < 0){ continue; } tessaddpoly(tess+fid, pt, poly, npoly); } else { ptreverse(pt, npt); npoly = fitpoly(poly, nelem(poly), pt, npt, MaxError); if(npoly == nelem(poly) || npoly < 3) continue; if(polyarea(pt, poly, npoly, orig) < 0){ continue; } polyreverse(poly, npoly); tessaddpoly(tess+fid, pt, poly, npoly); } } free(pt); int ntris; int j; for(j = 0; j < nelem(tess); j++){ if((ntris = tesstris(tess+j, &pt)) != -1){ memcpy(color, colors+4*j, sizeof color); for(i = 0; i < ntris; i++){ //idx2color(j, color); //memcpy(color, poscolor, sizeof color); pt[6*i+0+0] += clipr.u0; pt[6*i+0+1] += clipr.v0; pt[6*i+2+0] += clipr.u0; pt[6*i+2+1] += clipr.v0; pt[6*i+4+0] += clipr.u0; pt[6*i+4+1] += clipr.v0; drawtri(img, clipr, pt+6*i+0, pt+6*i+2, pt+6*i+4, color); } free(pt); } freetess(tess+j); } return 0; }
bool logicop::CrossFix::generate(pcollection& plycol, real bfactor) { // the general idea behind the code below: // The list of points resulted from the BO algo shall be traversed to // generate the new polygon(s). The trick is to firler-out properly // redundant points (shapes). The "usual" alternative traversing although // almost working, isn't quite appropriate here - the problem is to find a // proper starting point (see the comment in the previsous versions of // this file). // Another approach has been used here that seem to cover all the // shrink/bloat cases and on top of this is quicker and much simpler. // The algorithm traverses the points produced by BO-modified and creates // ALL shapes. It doesn't filters out anything. ALL possible polygons. // Next step is checking every new polygons // - undersizing (shrink) Check the polygoms for orientation. If it's normally // oriented (anticlockwise) - fine. If it isn't - the polygon should be // deleted. Having in mind that all input polygons were normaly oriented // it means that those parts are inside out and must be removed. When the // input polygon is completely inside out it should dissapear alltogether, but // this case should be catched before this algo is invoked. // - oversized (bloat) All resulting polygons will be normally oriented BUT // some of the polygons could be overlapped entirely by other polygons. The // overlapped fellas should be removed. if (0 == _crossp) return false; polycross::VPoint* centinel = _shape; // Get a non-crossing starting point while (0 == centinel->visited()) centinel = centinel->next(); // traverse the resulting points recursively to get all the polygons traverseOne(centinel, plycol); // if (1 == plycol.size()) return true; assert( plycol.size() > 1 ); if (0 > bfactor) { // undersize case // remove the invalid polygons (negative orientation) logicop::pcollection::iterator CI = plycol.begin(); while (CI != plycol.end()) { if (0 >= polyarea(**CI)) { delete (*CI); CI = plycol.erase(CI); } else CI++; } } else { // oversize case // Oversizing single polygon shall result in a single polygon. // Find the polygon with the biggest area. The rest should be removed // As a samity check (not implemented!)- the biggest polygon should // overlap entirely all the rest word the_one = -1; word current = 0; real biggest_area = 0; for (logicop::pcollection::const_iterator CI = plycol.begin(); CI != plycol.end(); CI++) { real cur_area = polyarea(**CI); if (biggest_area < cur_area) { biggest_area = cur_area; the_one = current; } current++; } assert(the_one != -1); // remove all except the_one current = 0; logicop::pcollection::iterator CI = plycol.begin(); while (CI != plycol.end()) { if (current != the_one) { delete (*CI); CI = plycol.erase(CI); } else CI++; current++; } } if (0 == plycol.size()) return false; else return true; }