Пример #1
0
void clipPoint(Point p, Boundary winEdge, Point wMin, Point wMax, Point * pOut, int * cnt, Point*  first[], Point * s)
{
    Point iPt;
    if (!first[winEdge]) {
        Point * np = new Point;
        *np = p;
        first[winEdge] = np;
    }
    else if (cross(p, s[winEdge], winEdge, wMin, wMax)) {
        iPt = intersect( p, s[winEdge], winEdge, wMin, wMax);
        if (winEdge < Top)
            clipPoint(iPt, (Boundary)((int)winEdge + 1), wMin, wMax, pOut, cnt, first, s);
        else {
            pOut[*cnt] = iPt;
            (*cnt)++;
        }
    }

    s[winEdge] = p;
    if(insideP(p, winEdge, wMin, wMax))
        if(winEdge < Top)
            clipPoint(p, (Boundary)((int)winEdge + 1), wMin, wMax, pOut, cnt, first, s);
        else {
            pOut[*cnt] = p;
            (*cnt)++;
        }
}
bool Clipping::clipCurve(Object *obj){
    auto& coords = obj->getNCoords();
    Coordinates newPath;
    bool prevInside = true;
    Coordinate prev;

    for(unsigned int i = 0; i < coords.size(); i++){
        if(clipPoint(coords[i])){
            if(!prevInside){
                clipLine(prev, coords[i]);
                newPath.push_back(prev);
            }
            newPath.push_back(coords[i]);
            prevInside = true;
        }else{
            if(prevInside && newPath.size() != 0){
                clipLine(prev, coords[i]);
                newPath.push_back(coords[i]);
            }
            prevInside = false;
        }
        prev = coords[i];
    }

    if(newPath.size() == 0)
        return false;

    obj->setNCoord(newPath);
    return true;
}
bool Clipping::clip(Object* obj){
    switch(obj->getType()){
    case ObjType::OBJECT:
        break;
    case ObjType::POINT:
        return clipPoint(obj->getNCoord(0));
    case ObjType::LINE:
        return clipLine(obj->getNCoord(0), obj->getNCoord(1));
    case ObjType::POLYGON:
        return clipPolygon(obj);
    case ObjType::BEZIER_CURVE:
    case ObjType::BSPLINE_CURVE:
        return clipCurve(obj);
    case ObjType::OBJECT3D:{
        Object3D *obj3d = (Object3D*) obj;
        bool draw = false;
        for(auto &face : obj3d->getFaceList()){
            bool tmp = clipPolygon(&face);
            if(!tmp){ face.getNCoords().clear(); }
            draw |= tmp;
        }
        return draw;
    }case ObjType::BEZIER_SURFACE:
    case ObjType::BSPLINE_SURFACE:{
        Surface *surf = (Surface*) obj;
        bool draw = false;
        for(auto &curve : surf->getCurveList()){
            bool tmp = clipCurve(&curve);
            if(!tmp){ curve.getNCoords().clear(); }
            draw |= tmp;
        }
        return draw;
    }}
    return false;
}
Пример #4
0
FORCEINLINE void GFX3D_Clipper::clipSegmentVsPlane(VERT** verts, const int coord, int which)
{
	bool out0, out1;
	if(which==-1)
		out0 = verts[0]->coord[coord] < -verts[0]->coord[3];
	else
		out0 = verts[0]->coord[coord] > verts[0]->coord[3];
	if(which==-1)
		out1 = verts[1]->coord[coord] < -verts[1]->coord[3];
	else
		out1 = verts[1]->coord[coord] > verts[1]->coord[3];

	//CONSIDER: should we try and clip things behind the eye? does this code even successfully do it? not sure.
	//if(coord==2 && which==1) {
	//	out0 = verts[0]->coord[2] < 0;
	//	out1 = verts[1]->coord[2] < 0;
	//}

	//both outside: insert no points
	if(out0 && out1) {
		CLIPLOG(" both outside\n");
	}

	//both inside: insert the first point
	if(!out0 && !out1)
	{
		CLIPLOG(" both inside\n");
		outClippedPoly.clipVerts[outClippedPoly.type++] = *verts[1];
	}

	//exiting volume: insert the clipped point and the first (interior) point
	if(!out0 && out1)
	{
		CLIPLOG(" exiting\n");
		outClippedPoly.clipVerts[outClippedPoly.type++] = clipPoint(verts[0],verts[1], coord, which);
	}

	//entering volume: insert clipped point
	if(out0 && !out1) {
		CLIPLOG(" entering\n");
		outClippedPoly.clipVerts[outClippedPoly.type++] = clipPoint(verts[1],verts[0], coord, which);
		outClippedPoly.clipVerts[outClippedPoly.type++] = *verts[1];

	}
}
Пример #5
0
int polygonClipSuthHodg(Point wMin, Point wMax, int n, Point* pIn, Point *pOut)
{
    Point* first[nClip] = { 0,0,0,0 }, s[nClip];
    int k, cnt = 0;

    for (k = 0; k < n; k++)
        clipPoint(pIn[k], Left, wMin, wMax, pOut, &cnt, first, s);
    closeClip(wMin, wMax, pOut, &cnt, first, s);
    return cnt;
}
bool Clipping::clip(Object* obj){
    switch(obj->getType()){
    case ObjType::POINT:
        return clipPoint(obj->getNCoord(0));
    case ObjType::LINE:
        return clipLine(obj->getNCoord(0), obj->getNCoord(1));
    case ObjType::POLYGON:
        return clipPolygon(obj);
    case ObjType::BEZIER_CURVE:
        return clipCurve(obj);
    default:
        return false;
    }
}
Пример #7
0
void closeClip(Point wMin, Point wMax, Point *pOut, int *cnt, Point* first[], Point *s)
{
    Point pt;
    Boundary winEdge;

    for (winEdge = Left; winEdge <= Top; winEdge++) {
        if(cross(s[winEdge], *first[winEdge], winEdge, wMin, wMax)) {
            pt = intersect(s[winEdge],*first[winEdge],winEdge,wMin,wMax);
            if(winEdge < Top)
                clipPoint(pt, (Boundary)((int)winEdge + 1), wMin, wMax, pOut, cnt, first, s);
            else {
                pOut[*cnt] = pt;
                (*cnt)++;
            }
        }
    }
}
bool Clipping::CohenSutherlandLineClip(Coordinate& c1, Coordinate& c2){
    if(c1 == c2) return clipPoint(c1);

    int rc1 = getCoordRC(c1);
    int rc2 = getCoordRC(c2);

    while(true){
        if( (rc1 | rc2) == 0 )// Dentro
            return true;
        else if( (rc1 & rc2) != 0 )// Fora
            return false;

        double x,y;
        int rc = rc1 ? rc1 : rc2;// (rc1 == 0) => Dentro
        double m = (c2.y-c1.y)/(c2.x-c1.x);

        if(rc & Clipping::RC::TOP){
            x = c1.x + 1/m * (m_w->maxY-c1.y);
            y = m_w->maxY;
        }else if(rc & Clipping::RC::BOTTOM){
            x = c1.x + 1/m * (m_w->minY-c1.y);
            y = m_w->minY;
        }else if(rc & Clipping::RC::RIGHT){
            y = m * (m_w->maxX-c1.x) + c1.y;
            x = m_w->maxX;
        }else if(rc & Clipping::RC::LEFT){
            y = m * (m_w->minX-c1.x) + c1.y;
            x = m_w->minX;
        }

        if(rc == rc1){
            c1.x = x;
            c1.y = y;
            rc1 = getCoordRC(c1);
        }else{
            c2.x = x;
            c2.y = y;
            rc2 = getCoordRC(c2);
        }
    }
}
//http://www.skytopia.com/project/articles/compsci/clipping.html
bool Clipping::LiangBaskyLineClip(Coordinate& c1, Coordinate& c2){
    if(c1 == c2) return clipPoint(c1);

    auto delta = c2 - c1;
    double p,q,r;
    double u1 = 0.0, u2 = 1.0;

    for(int pos = 0; pos<4; pos++){
        if     (pos == 0){ p = -delta.x; q = c1.x - m_w->minX; }
        else if(pos == 1){ p = delta.x; q = m_w->maxX - c1.x; }
        else if(pos == 2){ p = -delta.y; q = c1.y - m_w->minY; }
        else if(pos == 3){ p = delta.y; q = m_w->maxY - c1.y; }

        if(p == 0 && q < 0)
            return false;

        r = q/p;
        if(p < 0){
            if(r > u1)
                u1 = r;
        }else if(p > 0){
            if(r < u2)
                u2 = r;
        }
    }

    if(u1 > u2) return false;

    if(u2 < 1){
        c2.x = c1.x + u2*delta.x;
        c2.y = c1.y + u2*delta.y;
    }
    if(u1 > 0){
        c1.x = c1.x + u1*delta.x;
        c1.y = c1.y + u1*delta.y;
    }
    return true;
}
Пример #10
0
void ClippingService::clip(ViewWindow* window, DrawableObject *object)
{
  clipping_type type = window->getClippingType();
  list<Coordinate> coordinatesWindow = object->getCoordinatesWindow();
  int size = coordinatesWindow.size();

  switch (size) {
    case 1:  // point
    {
      switch(type)
      {
        case PC:
        case PC_CS:
        case PC_LB:
        case PC_CS_SH:
        case PC_LB_SH:
        case PC_SH:
        {
          clipPoint(window, object);
          break;
        }
        default:
        {
          goto DO_NOT_CLIP;
        }
      }
      break;
    }
    case 2:  // line
    {
      switch (type)
      {
        case CS:
        case PC_CS:
        case PC_CS_SH:
        case CS_SH:
        {
          clipCohenSutherland(window, object);
          break;
        }
        case LB:
        case PC_LB:
        case PC_LB_SH:
        case LB_SH:
        {
          clipLiangBarsky(window, object);
          break;
        }
        default:
        {
          goto DO_NOT_CLIP;
        }
      }
      break;
    }
    default:  // wireframe / object3d / curve2d
    {
      if (object->getType() == OBJECT3D)
      {
        switch (type)
        {
          case CS:
          case PC_CS:
          case PC_CS_SH:
          case CS_SH:
          {
            clipCohenSutherland(window, object);
            break;
          }
          case LB:
          case PC_LB:
          case PC_LB_SH:
          case LB_SH:
          {
            clipLiangBarsky(window, object);
            break;
          }
          default:
          {
            goto DO_NOT_CLIP;
          }
        }
        break;
      }
      else
      {
        switch (type)
        {
          case SH:
          case PC_CS_SH:
          case PC_LB_SH:
          case PC_SH:
          case CS_SH:
          case LB_SH:
          {
            clipSutherlandHodgman(window, object);
            break;
          }
          default:
          {
            goto DO_NOT_CLIP;
          }
        }
      }
    }
  }
  return;

  DO_NOT_CLIP:
  object->setCoordinatesClipped(object->getCoordinatesWindow());
}