⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 canvas.cpp

📁 C++&datastructure书籍源码,以前外教提供现在与大家共享
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "mathutils.h"
#include "canvas.h"
#include "CMUgraphics.h"
#include "image.h"
#include "auxil.h"
#include "canvasiterator.h"
#include <typeinfo>
#include <sstream>
#include <fstream>
#include <cmath>



Box::Box(int xul, int yul, int xlr, int ylr)
  : myLeft(xul, yul),
    myRight(xlr, ylr)
{ 

}

Box::Box(const Point& ul, const Point& lr)
  : myLeft(ul),
    myRight(lr)
{

}

Box::Box()
  : myLeft(0,0),
    myRight(0,0)
{

}

const Box& Box::operator += (const Box& rhs)
{
   myLeft.x = min(myLeft.x, rhs.myLeft.x);
   myLeft.y = min(myLeft.y, rhs.myLeft.y);
   myRight.x = max(myRight.x, rhs.myRight.x);
   myRight.y = max(myRight.y, rhs.myRight.y);
   
   return *this;
}

Box operator + (const Box& lhs, const Box& rhs)
{
    Box copy(lhs);
    copy += rhs;
    return copy;
}

Point Box::getUL() const
{
    return myLeft;
}

Point Box::getLR() const
{
    return myRight;
}

double Box::width() const
{
    return myRight.x - myLeft.x;
}

double Box::height() const
{
    return myRight.y - myLeft.y;
}

bool Box::contains(const Point& p) const
{
    Point ul = getUL();
    Point ur = getLR();
    
    return ul.x <= p.x && p.x <= ur.x &&
           ul.y <= p.y && p.y <= ur.y;
}

bool Box::intersects(const Box& b) const
{
    Point LL = b.getUL(); LL.y = b.getLR().y;
    Point UR = b.getLR(); LL.x = b.getUL().x;
    
    Point myLL = getUL(); myLL.y = getLR().y;
    Point myUR = getLR(); myUR.x = getUL().x;
    
    return contains(LL) || contains(UR) || 
           contains(b.getUL()) || contains(b.getLR()) ||
           b.contains(myLL) || b.contains(myUR) ||
           b.contains(myLeft) || b.contains(myRight);
}

string Box::tostring() const
{
    ostringstream out;
    out << "[ " << getUL() << ", " << getLR() << " ]";
    return out.str();
}

ostream& operator << (ostream& os, const Box& b)
{
  // os << "[ " << b.getUL() << ", " << b.getLR() << " ]";
  os << b.tostring();
  return os;
  
}

int BaseCanvas::ourCount = 0;
const int BaseCanvas::BBARHEIGHT = 20;

BaseCanvas::BaseCanvas(int w, int h, int x, int y)
  : myWindow(new window(w,h,x,y)),
    myHeight(h),
    myFilled(true),
    myCoords(BaseCanvas::top_origin)
{
    myWindow->SetBuffering(false);
    myWindow->ChangeTitle("Tapestry Canvas");
    myCount = ourCount;
    ourCount++;
    if (myCount == 0)
    {
        SetColor(CanvasColor::BLACK);
        DrawString("click with mouse to begin",Point(0,h/2));
        int x,y;
        myWindow->WaitMouseClick(x,y);
        Clear();
        SetColor(CanvasColor::BLACK);
    }
}

double BaseCanvas::ycoord(double d)
{
    if (myCoords == BaseCanvas::top_origin)
    {   return d;
    }
    else
    {   return height() - d;
    }   
}

Point BaseCanvas::ycoord(const Point& p)
{
    return Point(p.x,ycoord(p.y));
}

void BaseCanvas::MakeBBar()
{
    SetColor(CanvasColor::BLACK);
    DrawLine(Point(0,height()-BBARHEIGHT),Point(width(),height()-BBARHEIGHT));
    SetColor(myColor);
    myHeight = height() - BBARHEIGHT;
}

BaseCanvas::~BaseCanvas()
{
    // delete myBackground;
    ourCount--;
    // delete myWindow;
}

int BaseCanvas::height()
{
    return myHeight; // myWindow->GetHeight();
}

int BaseCanvas::width()
{
    return myWindow->GetWidth();
}

void BaseCanvas::Print()
{
    myWindow->Print();
}

AnimatedCanvas::AnimatedCanvas(int w, int h, int x, int y, bool isBuffered)
  : BaseCanvas(w,h,x,y),
    myShapes(),
    myShapeCount(0),
    myButtonCount(0),
    myBackground(0),
    myClickPoint(-1,-1),
    myKey(0),
    myIsBuffered(isBuffered),
    myIsRunning(false)
{
    myShapes.reserve(8);  // space for some shapes to start
    myWindow->SetBuffering(myIsBuffered);
}

AnimatedCanvas::~AnimatedCanvas()
{
    int k;
    for(k=0; k < myShapes.size(); k++)
    {
        // delete myShapes[k];
    }
}

void AnimatedCanvas::repaint()
{
    if (myIsBuffered)
    {
	    Clear();
	     
	    if (myBackground != 0)
	    {
	        myWindow->DrawImage(myBackground,0,0,width(),height());
	    }
    }
    
    int k;
    poll();
    
    Point p = getClick();
    if( ! myKey.isnothing())
    {
	    for(k=0; k < myShapeCount; k++)
	    {
	        Keyable * ks = dynamic_cast<Keyable *>(myShapes[k]);
	        if (ks != 0)
	        {
	            ks->processKey(myKey,*this);   
	        }
	    }  
    }
    if (p.x != -1)
    {
	    for(k=0; k < myShapeCount; k++)
	    {
	        Mouseable * ms = dynamic_cast<Mouseable *>(myShapes[k]);
	        if (ms != 0)
	        {
	            ms->processClick(p,*this);   
	        }
	    }
    }
    
    for(k=0; k < myShapeCount; k++)
    {
        myShapes[k]->draw(*this);
    }
    myIsRunning = false;
    int limit = myDeadShapes.size();
    for(k=0; k < limit; k++)
    {
        removeShape(myDeadShapes[k]);
    }
    myDeadShapes.clear();
    
    limit = myLiveShapes.size();
    for(k=0; k < limit; k++)
    {
        addShape(myLiveShapes[k]);
    }
    myLiveShapes.clear();
    
    myIsRunning = true;
    
    myWindow->UpdateBuffer();
}


void AnimatedCanvas::setBackground(image& im)
{
    myBackground= &im;
}


void AnimatedCanvas::addShape(Shape * s)
{
    if (myIsRunning)
    {
        myLiveShapes.push_back(s);
        return;
    }
    myShapes.push_back(s);
    myShapeCount++;
}

void AnimatedCanvas::addShape(Shape& s)
{
    addShape(s.clone());
}

void AnimatedCanvas::addShape(Button& b)
{
    addShape((Button *) b.clone());
}

void AnimatedCanvas::addShape(Button * b)
{
    addShape((Shape *) b);
    if (myButtonCount == 0)
    {
        MakeBBar();
    }
    b->setLocation(Point(myButtonCount, ycoord(height())));
    myButtonCount += b->bbox().width() + 5;
}

void AnimatedCanvas::removeShape(Shape * s)
{
    if (myIsRunning)
    {
        myDeadShapes.push_back(s);
        return;
    }
    int k;
    for(k=0; k < myShapeCount; k++)
    {
        if (myShapes[k]->id() == s->id())
        {
            myShapes[k] = myShapes[myShapeCount-1];
            myShapes.pop_back();
            myShapeCount--;
            return;
        }
    }
}

void AnimatedCanvas::removeShape(Shape& s)
{
    removeShape(&s);
}

void BaseCanvas::SetFrame()
{
    myFilled = false;
    SetColor(myColor);
}
void BaseCanvas::SetFilled()
{
    myFilled = true;
    SetColor(myColor);
}

void BaseCanvas::SetColor(const color&c )
{
    myColor = c;
    myWindow->SetPen(c,0);
    if (myFilled)
    {
        myWindow->SetBrush(c);
    }
    else
    {
        myWindow->SetBrush(WHITE);
    }
}

void BaseCanvas::Clear()
{
    SetColor(WHITE);
    myWindow->DrawRectangle(0,0,width(),height());   
}

void BaseCanvas::DrawPixel(int x, int y)
{
    DrawPixel(Point(x,y));
}

void BaseCanvas::DrawPixel(const Point& p)
{
    myWindow->DrawPixel(p.x,p.y);
}

CanvasColor BaseCanvas::GetPixel(const Point& p) const
{
    return CanvasColor(myWindow->GetColor(static_cast<int>(p.x),
					  static_cast<int>(p.y)));
}

void BaseCanvas::DrawLine(int x1, int y1, int x2, int y2)
{
    DrawLine(Point(x1,y1), Point(x2,y2));
}

void BaseCanvas::DrawLine(const Point& p1, const Point& p2)
{
    //myWindow->DrawLine(p1.x, p1.y, p2.x+1, p2.y+1);
    
    Process();
    myWindow->DrawLine(p1.x,p1.y,p2.x,p2.y);
}

void BaseCanvas::DrawRectangle(int x1, int y1, int x2, int y2)
{
    DrawRectangle(Point(x1,y1),Point(x2,y2));
}

void BaseCanvas::DrawRectangle(const Point& p1, const Point& p2)
{
    Process();
    myWindow->DrawRectangle(p1.x,p1.y,p2.x,p2.y);
}

void BaseCanvas::DrawCircle(int x, int y, int radius)
{
    DrawCircle(Point(x,y),radius);
}

void BaseCanvas::DrawCircle(const Point& center, int radius)
{
    Process();
    myWindow->DrawCircle(center.x,center.y,radius);
}

void BaseCanvas::DrawEllipse(int x1, int y1, int x2, int y2)
{
    DrawEllipse(Point(x1,y1),Point(x2,y2));
}

void BaseCanvas::DrawEllipse(const Point& p1, const Point& p2)
{
    Process();
    myWindow->DrawEllipse(p1.x,p1.y,p2.x,p2.y);
}

void BaseCanvas::DrawTriangle(const Point& p1, const Point& p2, const Point& p3)
{
    tvector<Point> t;
    t.push_back(p1);
    t.push_back(p2);
    t.push_back(p3);
    DrawPolygon(t,3);
}

void BaseCanvas::DrawPolygon(const tvector<Point>& a, int numPoints)
{
    const int SIZE = 100;
    static int MAX = SIZE;
    static int x[SIZE];
    static int y[SIZE];  
    static int * xp = x;
    static int * yp = y;
    
    Process();
    
    if (numPoints > MAX)
    {
        xp = new int[numPoints];
        yp = new int[numPoints];
        MAX = numPoints;
    }
    int k;
    for(k=0; k < numPoints; k++)
    {
        xp[k] = a[k].x;
        yp[k] = a[k].y;
    }
    myWindow->DrawPolygon(xp,yp,numPoints);
}


void BaseCanvas::DrawImage(image& im, int x, int y, double scale)
{
    Process();
    myWindow->DrawImage(im,x,y, im.GetWidth()*scale, im.GetHeight()*scale);
}

void BaseCanvas::DrawImage(image& im, const Point& p, double scale)
{
    DrawImage(im,p.x,p.y,scale);
}

void BaseCanvas::DrawPieWedge(const Point& p, int radius, double startRad, double endRad)
{
    myWindow->DrawArc(p.x, p.y, p.x+2*radius, p.y+2*radius,
                      startRad,endRad, myFilled ? FILLED : FRAME,RADIANS);
}

void BaseCanvas::DrawString(const string& s, int x, int y, int fontsize)
{   
    Process();
    myWindow->SetFont(fontsize,BOLD,SWISS);
    myWindow->DrawString(x,y,s);
}

void BaseCanvas::DrawString(const string& s, const Point& p, int fontsize)
{   
    DrawString(s,p.x,p.y,fontsize);
}

void BaseCanvas::GetStringSize(int & w, int & h, const string& s)
{
    myWindow->GetStringSize(w,h,s.c_str());
}

void BaseCanvas::SetTitle(const string& s)
{
    myWindow->ChangeTitle(const_cast<char *>(s.c_str()));
}

void BaseCanvas::Process()
{

}

IteratorRef<Shape> * AnimatedCanvas::makeIterator()
{
    return new CanvasIterator(myShapes,myShapeCount);
}

void AnimatedCanvas::poll()
{
    clicktype click;
    keytype press;
    //myWindow->FlushMouseQueue();
    int x,y;
    char ch;
    click = myWindow->GetMouseClick(x,y);
    Point p(x,y);
    
    press = myWindow->GetKeyPress(ch);
    
    if (click != NO_CLICK)
    {
        myClickPoint = p;
    }
    else
    {
        myClickPoint = Point(-1,-1);
    }
    
    if (press == NO_KEYPRESS)
    {
        myKey = Key(ch,Key::none);
    }
    else
    {
        switch(press)
        {
            case ESCAPE:
                myKey = Key(ch,Key::escape);
                break;
            case ASCII:
                myKey = Key(ch,Key::ascii);
                break;
            case FUNCTION:
                myKey = Key(ch,Key::function);
                break;
            case ARROW:
                myKey = Key(ch,Key::arrow);
                break; 
            default:
                myKey = Key(ch,Key::ascii);
                break;
        }
    }
}

void AnimatedCanvas::run(int steps,int pause)
{
    myIsRunning = true;
    for(int k=0; k < steps; k++)
    {
        repaint();
        Pause(pause);
    }
    myIsRunning = false;
}

void AnimatedCanvas::runUntilEscape(int pause)
{
    myIsRunning = true;
    while (true)
    {
        repaint();
        if (myKey.isescape()) break;
        Pause(pause);
    }
    myIsRunning = false;
}


Point AnimatedCanvas::getClick()
{
    return myClickPoint;
}

int Shape::ourCount = 0;

Shape::Shape()
{
    myCount = ourCount;
    ourCount++;
}

bool Shape::contains(const Point& p) const
{
    return bbox().contains(p);
}

bool Shape::overlaps(const Shape& s) const
{
    return bbox().intersects(s.bbox());   
}

Shape * Shape::clone()
{
    cerr << "error, called Shape::clone()" << endl;
    return 0;  // intentionally return NULL/0, clients should override
}

string Shape::tostring() const
{
    ostringstream out;
    out << typeid(*this).name() << " " << id() << " " << bbox();
    return out.str();
}

CircleShape::CircleShape(const Point& p, double r, color c)
  : myPoint(p),
    myRadius(r),
    myColor(c)
{
 
}

CircleShape::CircleShape(const CircleShape& c)
  : myPoint(c.myPoint),
    myRadius(c.myRadius),
    myColor(c.myColor)
{

}

Box CircleShape::bbox() const
{
    return Box (myPoint.x - myRadius, myPoint.y - myRadius,
                myPoint.x + myRadius, myPoint.y + myRadius);
}

void CircleShape::draw(AnimatedCanvas& c)
{
    c.SetColor(myColor);
    c.DrawCircle(myPoint.x, myPoint.y, myRadius);
}

Shape * CircleShape::clone()
{
    CircleShape * c = new CircleShape(*this);
    return c;
}

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

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

string CircleShape::tostring() const
{
   return string("circle ") + bbox().tostring();
}

EllipseShape::EllipseShape(const Point& ul, const Point& lr, color c)
  : myPoint(ul),
    myBox(ul,lr),
    myColor(c)
{

}

void EllipseShape::draw(AnimatedCanvas& c)
{
    c.SetColor(myColor);
    Point ul = myBox.getUL();
    Point lr = myBox.getLR();
    c.DrawEllipse(ul.x,ul.y,lr.x,lr.y);
}

void EllipseShape::setLocation(const Point& p)
{
    Point ul = myBox.getUL();
    Point lr = myBox.getLR();
    //myBox = Box(p,Point(lr.x + (p.x - ul.x), lr.y + (p.y - ul.y)));
    myBox = Box(p,Point(p.x+myBox.width(),p.y+myBox.height()));
    myPoint = p;
}

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

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

Shape * EllipseShape::clone()
{
    EllipseShape * e = new EllipseShape(myBox.getUL(),myBox.getLR(),myColor);
    return e;
}

string EllipseShape::tostring() const

⌨️ 快捷键说明

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