canvas.cpp

来自「C++&datastructure书籍源码,以前外教提供现在与大家共享」· C++ 代码 · 共 1,412 行 · 第 1/2 页

CPP
1,412
字号
{
   return string("ellipse ") + bbox().tostring();
}

RectangleShape::RectangleShape(const Point& p, double w, double h, color c)
 : myPoint(p),
   myWidth(w),
   myHeight(h),
   myColor(c)
{
    // note: + 1 ?? is because of how rectangles are drawn in
    // graphics.h, they go from xul,yul to xlr-1,ylr-1
}


void RectangleShape::draw(AnimatedCanvas& c)
{
    c.SetColor(myColor);
    c.DrawRectangle(myPoint.x,myPoint.y,
                    myPoint.x + myWidth,
                    myPoint.y + myHeight);
}

Box RectangleShape::bbox() const
{
    return Box(myPoint.x, myPoint.y, 
               myPoint.x + myWidth, myPoint.y + myHeight);
}

Shape * RectangleShape::clone()
{
    RectangleShape * r = new RectangleShape(myPoint,myWidth,myHeight,myColor);
    return r;
}

void RectangleShape::setLocation(const Point& p)
{
    myPoint = p;
}

Point RectangleShape::getLocation() const
{
    return myPoint;
}

string RectangleShape::tostring() const
{
   return string("rectangle ") + bbox().tostring();
}

TriangleShape::TriangleShape(const Point& p1, const Point& p2, const Point& p3,
                             color c)
{
    tvector<Point> p(3);
    p[0] = p1;
    p[1] = p2;
    p[2] = p3;
    myShape = new PolygonShape(p,3,c);
    myShape->setLocation(myShape->getLocation());
}

void TriangleShape::setLocation(const Point& p)
{
    myShape->setLocation(p);
}

Point TriangleShape::getLocation() const
{
    return myShape->getLocation();
}

TriangleShape::TriangleShape(const TriangleShape& ts)
{
    myShape = dynamic_cast<PolygonShape *> (ts.myShape->clone());
    myShape->setLocation(myShape->getLocation());
}

const TriangleShape& TriangleShape::operator =(const TriangleShape& ts)
{
    if (this != &ts)
    {
        // delete myShape;
        myShape = dynamic_cast<PolygonShape *> (ts.myShape->clone());
    }
    return *this;
}

TriangleShape::~TriangleShape()
{
    // delete myShape;
    myShape = 0;
}

void TriangleShape::draw(AnimatedCanvas& c)
{
    myShape->draw(c);
}

Box TriangleShape::bbox() const
{
    return myShape->bbox();
}

Shape * TriangleShape::clone()
{
    return new TriangleShape(*this);
}

string TriangleShape::tostring() const
{
   return string("triangle ") + bbox().tostring();
}

PolygonShape::PolygonShape(const tvector<Point>& a, int numPoints, color c)
  : myXdeltas(numPoints),
    myYdeltas(numPoints),
    myColor(c)
{
    Point minp = a[0];
    Point maxp = a[0];
    double miny = a[0].y;
    double maxy = a[0].y;
    int k;
    for(k=1; k < numPoints; k++)
    {
        minp = min(minp,a[k]);
        maxp = max(maxp,a[k]); 
        miny = min(miny,a[k].y);
        maxy = max(maxy,a[k].y);
    }
    myMin = myPoint = minp;
    for(k=0; k < numPoints; k++)
    {
        myXdeltas[k] = a[k].x - minp.x;
        myYdeltas[k] = a[k].y - minp.y;
    }
    // create bounding box
    myBox = Box(minp.x,miny,maxp.x,maxy);
    myPoint = myBox.getUL();
}

void PolygonShape::setLocation(const Point& p)
{
    double dx = p.x - myPoint.x;
    double dy = p.y - myPoint.y;
    myPoint = p;
    //myMin.x += dx;
    //myMin.y += dy;
    int k;
    for(k=0; k < myXdeltas.size(); k++)
    {
        myXdeltas[k] += dx;
        myYdeltas[k] += dy;
    }
    Point ul = myBox.getUL();
    Point lr = myBox.getLR();
    // myBox = Box(ul.x + dx, ul.y + dy, lr.x + dx, lr.y + dy);
    myBox = Box(myPoint.x, myPoint.y, myPoint.x + myBox.width(), myPoint.y + myBox.height());
}

Point PolygonShape::getLocation() const
{
    return myPoint;
    // return myBox.getUL();
}

void PolygonShape::draw(AnimatedCanvas& c)
{

    tvector<Point> p(myXdeltas.capacity());
    
    //static int * xa = new int[myXdeltas.length()];
    //static int * ya = new int[myXdeltas.length()];
    
    int k; 
    int len = myXdeltas.capacity();
    for(k=0; k < len; k++)
    {
      //  xa[k] = myMin.x + myXdeltas[k];
      //  ya[k] = myMin.y + myYdeltas[k];
        p[k].x = myMin.x + myXdeltas[k];
        p[k].y = myMin.y + myYdeltas[k];
    }
    c.SetColor(myColor);
    c.DrawPolygon(p,len);
}

Box PolygonShape::bbox() const
{
   return myBox;  
}

Shape * PolygonShape::clone()
{
    tvector<Point> p(myXdeltas.size());
    int k;
    for(k=0; k < myXdeltas.size(); k++)
    {
        p[k] = Point(myMin.x + myXdeltas[k], myMin.y + myYdeltas[k]);
    }
    PolygonShape * ps = new PolygonShape(p, myXdeltas.size(),myColor);
    return ps;
}

string PolygonShape::tostring() const
{
   return string("polygon ") + bbox().tostring();
}

ImageShape::ImageShape(const Point& p, const string& filename,double scale)
  : myPoint(p),
    myScale(scale)
{
    ifstream in(filename.c_str());
    if (in.fail())
    {
        cerr << "could not access " << filename << "in ImageShape" << endl;
        exit(1);
    }
    in.close();
    myImage = new image((char *)filename.c_str(),JPEG);
}

ImageShape::ImageShape(const ImageShape& is)
  : myPoint(is.getLocation()),
    myImage(is.myImage),
    myScale(is.myScale)
{

}

void ImageShape::draw(AnimatedCanvas& c)
{
    c.DrawImage(*myImage,myPoint.x,myPoint.y, myScale);
}

Box ImageShape::bbox() const
{
    return Box(myPoint.x,
               myPoint.y,
               myPoint.x + myImage->GetWidth()*myScale,
               myPoint.y + myImage->GetHeight()*myScale);
}

Shape * ImageShape::clone()
{
    ImageShape * im = new ImageShape(*this);
    return im;
}

void ImageShape::setLocation(const Point& p)
{
    myPoint = p;
}

Point ImageShape::getLocation() const
{
    return myPoint;
}

string ImageShape::tostring() const
{
   return string("image ") + bbox().tostring();
}

TextShape::TextShape( const Point& p, const string& s, color c)
  : myPoint(p),
    myString(s),
    myColor(c),
    myBox(p,Point(p.x+s.length()*4,p.y+5)),
    myInitialized(false)
{
    // to get real box dimensions we need a canvas
    // so this is a gross approximation  
}

void TextShape::changeText(const string& s)
{
    myString = s;
    myInitialized = false;
}

void TextShape::draw(AnimatedCanvas& c)
{
    if (! myInitialized)
    {
        int w,h;
        c.GetStringSize(w,h,myString.c_str());
        myBox = Box(myPoint.x,myPoint.y,
                    myPoint.x+w, myPoint.y+h);
        myInitialized = true;
    }
    c.SetColor(myColor),
    c.DrawString(myString,myPoint.x,myPoint.y);
}
  
Box TextShape::bbox() const
{
    return myBox;
}  


Shape * TextShape::clone()
{
    TextShape * t = new TextShape(myPoint,myString,myColor);
    return t;
} 

void TextShape::setLocation(const Point& p)
{
    myPoint = p;
}

Point TextShape::getLocation() const
{
    return myPoint;
}

string TextShape::tostring() const
{
   return string("text ") + myString + " " + bbox().tostring();
}

Mover::Mover(Shape& cs)
  : Shape(),
    myShape(&cs)
{

}

void Mover::draw(AnimatedCanvas& c)
{
    myShape->draw(c);
}

Box Mover::bbox() const
{
    return myShape->bbox();
}

void Mover::moveTo(const Point& p)
{
    myShape->setLocation(p);
}

void Mover::moveBy(double dx, double dy)
{
    Point p = myShape->getLocation();
    p.x += dx;
    p.y += dy;
    myShape->setLocation(p);
}

Shape * Mover::clone()
{
    return myShape->clone();
}

void Mover::setLocation(const Point& p)
{
    myShape->setLocation(p);
}

Point Mover::getLocation() const
{
    return myShape->getLocation();
}

CompositeShape::CompositeShape()
  : myShapes(),
    myBox(0,0,0,0)
{

}

void CompositeShape::draw(AnimatedCanvas& c)
{
    int k;
    for(k=0; k < myShapes.size(); k++)
    {
        myShapes[k]->draw(c);
    }
}

void CompositeShape::add(Shape& sh)
{
    add(sh.clone());
}

void CompositeShape::add(Shape* sh)
{
    myShapes.push_back(sh);
    if (myShapes.size() == 1)
    {
        myBox = sh->bbox();
        myPoint = sh->bbox().getUL(); // setLocation(sh->bbox().getUL());
    }
    else
    {
        myBox += sh->bbox();
        // myPoint = min(getLocation(),sh->bbox().getUL());
        myPoint = myBox.getUL();
    }
}

Point CompositeShape::getLocation() const
{
    return myPoint;
}

void CompositeShape::setLocation(const Point& p)
{
    Point old = getLocation();
    double dx = p.x - old.x;
    double dy = p.y - old.y;
    for(int k=0; k < myShapes.size(); k++)
    { 
        old = myShapes[k]->getLocation();
        old.x += dx;
        old.y += dy;
        myShapes[k]->setLocation(old);
    }
    myPoint = p;
}

Box CompositeShape::bbox() const
{
    return Box(myPoint.x,myPoint.y,
               myPoint.x + myBox.width(), myPoint.y + myBox.height());
}

Shape* CompositeShape::clone()
{
   CompositeShape * c = new CompositeShape;
   int k;
   for(k=0; k < myShapes.size(); k++)
   {
       Shape * s = myShapes[k]->clone();
       if (s != 0)
       {
           c->add(s);
       }
   }
   return c;
}

string CompositeShape::tostring() const
{
  string s = string("composite ") + bbox().tostring();
  int k;
  for(k=0; k < myShapes.size(); k++)
  {
      s += myShapes[k]->tostring();
  }
  return s;
}

Bouncer::Bouncer(Shape * cs, double angle, double v)
  : Shape(),
    myShape(cs),
    myAngle(angle),
    myVelocity(v)
{

}

Bouncer::Bouncer(Shape& cs, double angle, double v)
  : Shape(),
    myShape(cs.clone()),
    myAngle(angle),
    myVelocity(v)
{

}

Bouncer::Bouncer(const Bouncer& b)
  : Shape(),
    myShape(b.myShape->clone()),
    myAngle(b.myAngle),
    myVelocity(b.myVelocity)
{

}

Shape * Bouncer::clone()
{
    return new Bouncer(*this);
}

void Bouncer::updatetop(AnimatedCanvas& c, Point& p)
{
    myAngle = 2*PI - myAngle;
    p.y -= bbox().getUL().y;
}

void Bouncer::updatebottom(AnimatedCanvas& c, Point& p)
{
    myAngle = 2*PI - myAngle;
    p.y += c.height() - bbox().getLR().y;
}

void Bouncer::updateleft(AnimatedCanvas& c, Point& p)
{
    myAngle = PI - myAngle;
    p.x -= bbox().getUL().x;
}

void Bouncer::updateright(AnimatedCanvas& c, Point& p)
{
    myAngle = PI - myAngle;
    p.x += c.width() - bbox().getLR().x;
}
void Bouncer::update(AnimatedCanvas& c)
{
    Box b = bbox();
    
    Point p = myShape->getLocation();
    Point newP = p;
    
    double xchange = myVelocity*cos(myAngle);
    double ychange = myVelocity*sin(myAngle);
    bool   didChangeX = false,didChangeY=false;
  
    if (b.getUL().x + xchange < 0)
    {
        updateleft(c,p);
        didChangeX = true;
    }
    else if (b.getLR().x + xchange > c.width())
    {
        updateright(c,p);
        didChangeX = true;
    }
    else if (b.getUL().y + ychange < 0)
    {
       updatetop(c,p);
       didChangeY = true;
    }
    else if (b.getLR().y + ychange > c.height())
    {
        updatebottom(c,p);
        didChangeY = true;
    }
    else
    {   p.x += xchange;
        p.y += ychange;
    }
    setLocation(p);
}          

void Bouncer::draw(AnimatedCanvas& c)
{
    update(c);
    myShape->draw(c);
    // c.DrawRectangle(bbox().getUL(),bbox().getLR());
}

Box Bouncer::bbox() const
{
    return myShape->bbox();
}

void Bouncer::setLocation(const Point& p)
{
    myShape->setLocation(p);
}

Point Bouncer::getLocation() const
{
    return myShape->getLocation();
}

double Bouncer::getAngle() const
{
    return  myAngle;
}

double Bouncer::getVelocity() const
{
    return myVelocity;
}

Mouseable::~Mouseable()
{

}

Keyable::~Keyable()
{

}

MKAdapter::MKAdapter()
{

}

void MKAdapter::processClick(const Point& p, AnimatedCanvas& c)
{

}

void MKAdapter::processKey(const Key& k, AnimatedCanvas& c)
{

}

CanvasAble::~CanvasAble()
{

}

EmptyShape::EmptyShape()
{

}

void EmptyShape::draw(AnimatedCanvas& c)
{
  // do nothing
}

Box EmptyShape::bbox() const
{
    return Box(Point(0,0),Point(0,0));
}

Shape * EmptyShape::clone()
{
    return this;
}

void EmptyShape::setLocation(const Point& p)
{
}

Point EmptyShape::getLocation() const
{
    return Point(0,0);
}

PrintWatcher::PrintWatcher(const Key& key)
  : myKey(key)
{

}

void PrintWatcher::processKey(const Key& key, AnimatedCanvas& c)
{
    if (key == myKey) c.Print();
}

Button::Button(const string& label)
 : myLabel(label)
{
    myShape = new TextShape(Point(0,0),label,CanvasColor::DARKBLUE);
}

Button::Button(const string& label,const color& c)
 : myLabel(label)
{
    myShape = new TextShape(Point(0,0),label,c);
}

void Button::draw(AnimatedCanvas& c)
{
    c.SetColor(CanvasColor::KHAKI);
    Point p = getLocation();
    c.DrawRectangle(p.x,c.ycoord(p.y+1),p.x + bbox().width()-1,
                    c.ycoord(p.y + bbox().height() - 1));
    myShape->draw(c);
}

void Button::setLocation(const Point& p)
{
    myShape->setLocation(p);
}

Box Button::bbox() const
{
    return myShape->bbox();
}

Point Button::getLocation() const
{
    return myShape->getLocation();
}

void Button::execute(AnimatedCanvas& c)
{
 
}

void Button::processClick(const Point& p, AnimatedCanvas& c)
{
    if (contains(p))
    {
        execute(c);
    }
}

Shape * Button::clone()
{
    return this;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?