Esempio n. 1
0
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;
}
Esempio n. 2
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;
}