foreach ( SkyObject* obj, obs ) { bool visible = false; QPointF o = m_proj->toScreen( obj, true, &visible ); if( !visible || !m_proj->onScreen(o) ) continue; float size = 20.; float x1 = o.x() - 0.5*size; float y1 = o.y() - 0.5*size; drawArc( QRectF(x1, y1, size, size), -60*16, 120*16 ); drawArc( QRectF(x1, y1, size, size), 120*16, 120*16 ); }
Adesk::Boolean SimpleDoubleGateDraw::subWorldDraw ( AcGiWorldDraw* mode ) { assertReadEnabled () ; drawArc( mode, m_insertPt, m_angle, m_gap, m_radius ); drawLine( mode, m_insertPt, m_angle, m_gap, 0, m_length ); drawArc( mode, m_insertPt, m_angle + PI, m_gap, m_radius ); drawLine( mode, m_insertPt, m_angle + PI, m_gap, 0, m_length ); return Adesk::kTrue; }
// 円弧を描画(回転、拡大縮小つき) // center_x, center_y 円の中心位置 // radius_x, radius_y 半径(横と縦) // start_rad, end_rad 開始・終了角度 // division 円の分割数(数値が大きいと滑らかな円になる) // line_width 線幅 // color 色 // angle_rad 回転角度(ラジアン) // scaling 横、縦の拡大縮小率 // origin 矩形の原点位置 void drawArc(const float center_x, const float center_y, const float radius_x, const float radius_y, const float start_rad, const float end_rad, const int division, const float line_width, const Color& color, const float angle_rad, const Vec2f& scaling, const Vec2f& origin) { // 回転、拡大縮小の行列を生成 auto matrix = transformMatrix2D(angle_rad, Vec3f(center_x, center_y, 0.0f), Vec3f(scaling.x(), scaling.y(), 1.0f)); // 行列をOpenGLに設定 glPushMatrix(); glMultMatrixf(matrix.data()); // 描画 drawArc(-origin.x(), -origin.y(), radius_x, radius_y, start_rad, end_rad, division, line_width, color); // 行列を元に戻す glPopMatrix(); }
/** * Draws a circle. * @param cx center in x * @param cy center in y * @param radius Radius */ void RS_PainterQt::drawCircle(const RS_Vector& cp, double radius) { // RVT_PORT if (drawingMode==RS2::ModeXOR && radius<500) { if (radius<500) { // This is _very_ slow for large arcs: QPainter::drawEllipse(toScreenX(cp.x-radius), toScreenY(cp.y-radius), RS_Math::round(2.0*radius), RS_Math::round(2.0*radius)); } else { #ifdef __APPLE1__ drawArcMac(cp, radius, 0.0, 2*M_PI, false); #else drawArc(cp, radius, 0.0, 2*M_PI, cp + RS_Vector(radius, 0.0), cp + RS_Vector(radius, 0.0), false); #endif } }
//------------------------------------------------------------------------- // draw the current shape //------------------------------------------------------------------------- void drawShape () { switch (currentShape) { case DRAW_OVAL: drawOval (0, 0, width[currentShape], height[currentShape], segments[currentShape]); break; case FILL_OVAL: fillOval (0, 0, width[currentShape], height[currentShape], segments[currentShape]); break; case DRAW_ARC: drawArc (0, 0, width[currentShape], height[currentShape], startAngleW, arcAngleW, segments[currentShape]); break; case FILL_ARC: fillArc (0, 0, width[currentShape], height[currentShape], startAngleF, arcAngleF, segments[currentShape]); break; } }
int main(void) { drawRect(20,20,100,100); drawArc(20,20,100,100,0,360); }
int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent ) { BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); DRAWSEGMENT* arc = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT; BOARD_COMMIT commit( m_frame ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ARC ); m_frame->SetToolID( m_editModules ? ID_MODEDIT_ARC_TOOL : ID_PCB_ARC_BUTT, wxCURSOR_PENCIL, _( "Add graphic arc" ) ); while( drawArc( arc ) ) { if( arc ) { commit.Add( arc ); commit.Push( _( "Draw an arc" ) ); } arc = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT; } m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); return 0; }
/** * Aufforderung zur Neuzeichnung. * @param window Verweis auf das Fenster, in dem die Figur * erscheinen soll. * @param cellWidth Breite einer Zelle auf dem Spielfeld in Pixeln. * @param cellHeight Hoehe einer Zelle auf dem Spielfeld in Pixeln. */ void Cherry::draw(Gosu::Graphics& graphics, int cellWidth, int cellHeight) { // die Stiele for (int i = 0; i < 2; i++) { drawArc(graphics, Gosu::Color(255, 128, 64), cellWidth, cellHeight, false, Descriptor.stalks[ i ], 90, 70); } // die Fruechte selbst for (int i = 0; i < 2; i++) { drawArc(graphics, Gosu::Color(204, 0, 0), cellWidth, cellHeight, true, Descriptor.cherries[ i ], 0, 360); } // die Reflektionen auf den Fruechten for (int i = 0; i < 4; i++) { drawArc(graphics, Gosu::Color(255, 255, 255), cellWidth, cellHeight, true, Descriptor.reflection[ i ], 0, 360); } }
int main(void) { setSize(900, 700); drawImage(150,0,700,500,"file:background.png"); //Text setColourGradient("white","yellow"); drawString(200,470,"H a p p y...W i n t e r"); //SnowMan Body setColourGradient("gray","white"); fillOval(440.0,160.0,65.0,60.0); fillOval(430.0,220.0,90.0,80.0); fillOval(400.0,300.0,150.0,160.0); //Facial Features setColourGradient("black","green"); fillOval(455.0,175.0,10.0,10.0); fillOval(480.0,175.0,10.0,10.0); drawArc(470,200,20,50,30,40); //Hands setColour(white); drawLine(440,240,395,200); drawLine(520,240,565,200); //Accessories drawOval(472,235,10,10); drawOval(472,255,10,10); drawOval(472,275,10,10); return 0; }
void swcRectangle::drawOuterCornerX(bool en_multisample) { (en_multisample) ? glEnable(GL_MULTISAMPLE_ARB) : glDisable(GL_MULTISAMPLE_ARB); //outer-border-corner-top-left if (radius_top_left == 0) drawTriRect(true, -border_size_left, -border_size_top, border_size_left, border_size_top, &border_colors[0], &border_colors[48], opacity); else drawArc(radius_top_left.x, radius_top_left.y, 180, 90, radius_top_left.x + border_size_left, radius_top_left.y + border_size_top, &border_colors[0], opacity); //outer-border-corner-top-right if (radius_top_right == 0) drawTriRect(false, width, -border_size_top, border_size_right, border_size_top, &border_colors[0], &border_colors[16], opacity); else drawArc(width - radius_top_right.x, radius_top_right.y, 90, 0, radius_top_right.x + border_size_right, radius_top_right.y + border_size_top, &border_colors[4], opacity); //outer-border-corner-bottom-right if (radius_bottom_right == 0) drawTriRect(true, width, height, border_size_right, border_size_bottom, &border_colors[16], &border_colors[32], opacity); else drawArc(width - radius_bottom_right.x, height - radius_bottom_right.y, 270, 360, radius_bottom_right.x + border_size_right, radius_bottom_right.y + border_size_bottom, &border_colors[12],opacity); //outer-border-corner-bottom-left if (radius_bottom_left == 0) drawTriRect(false, -border_size_left, height, border_size_left, border_size_bottom, &border_colors[48], &border_colors[32], opacity); else drawArc(radius_bottom_left.x, height - radius_bottom_left.y, 180, 270, radius_bottom_left.x + border_size_left, radius_bottom_left.y + border_size_bottom, &border_colors[20], opacity); if (en_multisample) glDisable(GL_MULTISAMPLE_ARB); }
int main(void) { drawOval(30,30,100,150); drawOval(0,0,499,299); drawArc(100,100,90,120,0,180); return 0; }
int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent ) { if( m_editModules ) { m_frame->SetToolID( ID_MODEDIT_ARC_TOOL, wxCURSOR_PENCIL, _( "Add graphic arc" ) ); EDGE_MODULE* arc = new EDGE_MODULE( m_board->m_Modules ); while( drawArc( reinterpret_cast<DRAWSEGMENT*&>( arc ) ) ) { if( arc ) { m_frame->OnModify(); m_frame->SaveCopyInUndoList( m_board->m_Modules, UR_MODEDIT ); arc->SetParent( m_board->m_Modules ); arc->SetLocalCoord(); m_board->m_Modules->GraphicalItems().PushFront( arc ); } arc = new EDGE_MODULE( m_board->m_Modules ); } } else // !m_editModules case { m_frame->SetToolID( ID_PCB_ARC_BUTT, wxCURSOR_PENCIL, _( "Add graphic arc" ) ); DRAWSEGMENT* arc = new DRAWSEGMENT; while( drawArc( arc ) ) { if( arc ) { m_board->Add( arc ); m_frame->OnModify(); m_frame->SaveCopyInUndoList( arc, UR_NEW ); } arc = new DRAWSEGMENT; } } m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); return 0; }
int main(void) { drawArc(30, 30, 100, 100, 0, 360); drawRect(45, 45, 70, 70); return 0; }
void myDisplay() { glClear(GL_COLOR_BUFFER_BIT); //Clear the screen and set color glColor3f(1.0, 0.0, 0.0); Point p(200, 200); drawArc(p, 100, 0, 400); glFlush(); //Send to the screen }
void myDisplay() { glClear(GL_COLOR_BUFFER_BIT); //Clear the screen glColor3f(1.0, 0.0, 0.0); Point2 p(200, 200); drawArc(p, 100, 0, 400); glFlush(); //Send to the output screen from buffer }
bool GiGraphics::drawArc3P(const GiContext* ctx, const Point2d& startpt, const Point2d& midpt, const Point2d& endpt, bool modelUnit) { Point2d center; float r, startAngle, sweepAngle; return (mgcurv::arc3P(startpt, midpt, endpt, center, r, &startAngle, &sweepAngle) && drawArc(ctx, center, r, r, startAngle, sweepAngle, modelUnit)); }
void uiDrawPathArcTo(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative) { struct arc a; a.xCenter = xCenter; a.yCenter = yCenter; a.radius = radius; a.startAngle = startAngle; a.sweep = sweep; a.negative = negative; drawArc(p, &a, uiDrawPathLineTo); }
void WgtSonar::paintEvent(QPaintEvent *event) { QPainter *p = new QPainter(this); p->setRenderHint(QPainter::Antialiasing, true); p->setPen(QColor(255, 0, 0)); p->setBrush(QColor(255, 0, 0)); for(int i = 0; i < 7; i++) drawArc(rand()%120 + 50, i, p); p->setPen(QColor(200, 200, 200)); for(int i = 1; i < 4; i++) drawCircle(i*40 + 50, p); }
void swcRectangle::drawInnerCornerCurves(bool en_multisample) { (en_multisample) ? glEnable(GL_MULTISAMPLE_ARB) : glDisable(GL_MULTISAMPLE_ARB); //border-radius-top-left drawArc(radius_top_left.x, radius_top_left.y, 180, 90, radius_top_left.x, radius_top_left.y, &colors[0], opacity); //border-radius-top-right drawArc(width - radius_top_right.x, radius_top_right.y, 90, 0, radius_top_right.x, radius_top_right.y, &colors[4], opacity); //border-radius-bottom-right drawArc(width - radius_bottom_right.x, height - radius_bottom_right.y, 270, 360, radius_bottom_right.x, radius_bottom_right.y, &colors[12], opacity); //border-radius-bottom-left drawArc(radius_bottom_left.x, height - radius_bottom_left.y, 180, 270, radius_bottom_left.x, radius_bottom_left.y, &colors[20], opacity); if (en_multisample) glDisable(GL_MULTISAMPLE_ARB); }
void UBGraphicsCompass::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (UBDrawingController::drawingController ()->stylusTool() != UBStylusTool::Selector && UBDrawingController::drawingController ()->stylusTool() != UBStylusTool::Play) return; if (!mResizing && !mRotating && !mDrawing) { QGraphicsRectItem::mouseMoveEvent(event); mDrewCenterCross = false; } else { if (mResizing) { QPointF delta = event->pos() - event->lastPos(); if (rect().width() + delta.x() < sMinRadius) delta.setX(sMinRadius - rect().width()); setRect(QRectF(rect().topLeft(), QSizeF(rect().width() + delta.x(), rect().height()))); } else { QLineF currentLine(needlePosition(), event->pos()); QLineF lastLine(needlePosition(), event->lastPos()); qreal deltaAngle = currentLine.angleTo(lastLine); if (deltaAngle > 180) deltaAngle -= 360; else if (deltaAngle < -180) deltaAngle += 360; rotateAroundNeedle(deltaAngle); if (mDrawing) { mSpanAngleInDegrees += deltaAngle; if (mSpanAngleInDegrees >= 1080) mSpanAngleInDegrees -= 360; else if (mSpanAngleInDegrees < -1080) mSpanAngleInDegrees += 360; drawArc(); } } event->accept(); } }
void arco::paintEvent(QPaintEvent *e){ QPainter painter(this); QPen pointPen(Qt::black); pointPen.setWidth(2); painter.setPen(pointPen); if (drawArcArco){ QString radioStr = ui->radioTxt->toPlainText(); QString anguloStr = ui->angulosTxt->toPlainText(); if (!radioStr.isEmpty() && !anguloStr.isEmpty()) { angulo = anguloStr.toInt(); radio = radioStr.toInt(); for(int i=0; i<transforms.size(); ++i){ painter.setTransform(transforms[i],true); drawArc(angulo, radio,painter); } } } }
/** * Aufforderung zur Neuzeichnung. * @param window Verweis auf das Fenster, in dem die Figur * erscheinen soll. * @param cellWidth Breite einer Zelle auf dem Spielfeld in Pixeln. * @param cellHeight Hoehe einer Zelle auf dem Spielfeld in Pixeln. */ void Pacman::draw(Gosu::Graphics& graphics, int cellWidth, int cellHeight) { Gosu::Color foo(255, 255, 0); //this->spriteset[mouthStatus]->draw(4 + xOffset + this->cellX * cellWidth, 4 + yOffset + this->cellY * cellHeight, 2); /*graphics.drawQuad(xOffset + this->cellX * cellWidth, yOffset + this->cellY * cellHeight, foo, xOffset + this->cellX * cellWidth + cellWidth, yOffset + this->cellY * cellHeight, foo, xOffset + this->cellX * cellWidth, yOffset + this->cellY * cellHeight + cellHeight, foo, xOffset + this->cellX * cellWidth + cellWidth, yOffset + this->cellY * cellHeight + cellHeight, foo, 3);*/ drawArc(graphics, foo, cellWidth, cellHeight, true, Descriptor.circle, (mouthOpenAngle / 2 + getAngleFromDirection() * 90), (360 - mouthOpenAngle)); /* QPainter painter(window); // Zeichenfarbe setzen painter.setPen(QColor(255, 255, 0)); painter.setBrush(Qt::SolidPattern); painter.setRenderHint(QPainter::Antialiasing); // Kreissegment zeichnen drawArc(painter, cellWidth, cellHeight, true, Descriptor.circle, (mouthOpenAngle / 2 + getAngleFromDirection() * 90), (360 - mouthOpenAngle)); */ }
void HexEdge::redrawedge() { double pc0[3], pc1[3]; globalVertices->GetPoint(vertIds->GetId(0),pc0); globalVertices->GetPoint(vertIds->GetId(1),pc1); myPoints->SetPoint(0,pc0); switch(edgeType) { case LINE: myPoints->SetPoint(1,pc1); drawLine(); break; case ARC: double c[3],arcpnt[3]; myPoints->GetPoint(cntrlPointsIds->GetId(0),arcpnt); myPoints->SetPoint(arcNpoints-1,pc1); vtkMath::Solve3PointCircle(pc0,arcpnt,pc1,c); drawArc(c); break; } data->Modified(); tube->Modified(); }
//Draws the 3D scene void drawScene() { int i; //Clear information from last draw glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective glLoadIdentity(); //Reset the drawing perspective glColor3f(0.0f,0.0f,0.0f); glBegin(GL_QUADS); glVertex3f(-2.0f,-2.0f,-5.0f); glVertex3f(-2.0f,2.0f,-5.0f); glVertex3f(2.0f,2.0f,-5.0f); glVertex3f(2.0f,-2.0f,-5.0f); glEnd();//outer black quad glColor3f(0.99f, 0.84f, 0.61f); glBegin(GL_QUADS); glVertex3f(-1.8f,-1.8f,-5.0f); glVertex3f(-1.8f,1.8f,-5.0f); glVertex3f(1.8f,1.8f,-5.0f); glVertex3f(1.8f,-1.8f,-5.0f); glEnd();//board glColor3f(0.0f,0.0f,0.0f); drawDisc(0.0f,0.0f,0.42f,1000); glColor3f(0.99f, 0.84f, 0.61f); drawDisc(0.0f,0.0f,0.40f,1000); glColor3f(0.0f, 0.0f, 0.0f); drawDisc(0.0f,0.0f,0.38f,1000); glColor3f(0.99f, 0.84f, 0.61f); drawDisc(0.0f,0.0f,0.36f,1000);//central circle glColor3f(0.0f,0.0f,0.0f); drawDisc(0.0f,0.0f,0.08f,1000); glColor3f(1.0f,0.0f,0.0f); drawDisc(0.0f,0.0f,0.06f,1000);//central disc drawCircle(0.0f,0.0f,0.08f); drawTri();//for stars for(i=0;i<4;i++){ //symmetric codes glColor3f(0.52f, 0.37f, 0.26f); drawDisc(1.69f, 1.69f, 0.11f,1000);//holes //drawArc(0.6f,0.6f,0.2121f); glColor3f(0.0f, 0.0f, 0.0f); //drawArc(0.6f,0.6f,0.2121f); glBegin(GL_LINE_STRIP); glVertex3f(0.45f,0.45f,-5.0f);//45 degree line glVertex3f(1.4f,1.4f,-5.0f); glBegin(GL_LINE_STRIP); glVertex3f(1.4f,1.4f,-5.0f);//arrows glVertex3f(1.36f,1.4f,-5.0f); glVertex3f(1.4f,1.4f,-5.0f);//arrows glVertex3f(1.4f,1.36f,-5.0f); glEnd(); drawArc(0.6f,0.6f,0.2121f); glColor3f(0.0f,0.0f,0.0f); glBegin(GL_QUADS);//base line glVertex3f(1.1f, 1.2f, -5.0f); glVertex3f(1.1f, 1.21f, -5.0f); glVertex3f(-1.1f, 1.21f, -5.0f); glVertex3f(-1.1f, 1.2f, -5.0f); glVertex3f(1.1f, 1.35f, -5.0f); glVertex3f(1.1f, 1.33f, -5.0f); glVertex3f(-1.1f, 1.33f, -5.0f); glVertex3f(-1.1f, 1.35f, -5.0f); glEnd(); glColor3f(1.0f, 0.0f, 0.0f);//base line circles drawDisc(1.1f, 1.275f, 0.075f,1000); drawDisc(-1.1f, 1.275f, 0.075f,1000); glColor3f(0.0f,0.0f,0.0f); drawCircle(1.1f, 1.275f, 0.075f); drawCircle(-1.1f, 1.275f, 0.075f); glRotatef(90.0f,0.0f,0.0f,1.0f); } reDraw(); glutSwapBuffers(); //Send the 3D scene to the screen }
void WPainter::drawArc(double x, double y, double width, double height, int startAngle, int spanAngle) { drawArc(WRectF(x, y, width, height), startAngle, spanAngle); }
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setupUi(this); setWindowTitle(tr("GD CAD")); newFile(); qApp->installEventFilter(this); <<<<<<< HEAD connect(ui->pointButton, SIGNAL(clicked()), this, SLOT(drawPoint())); connect(ui->lineButton, SIGNAL(clicked()), this, SLOT(drawLine())); connect(ui->circleButton, SIGNAL(clicked()), this, SLOT(drawCircle())); connect(ui->ellipseButton, SIGNAL(clicked()), this, SLOT(drawEllipse())); connect(ui->arcButton, SIGNAL(clicked()),this, SLOT(drawArc())); connect(ui->polylineButton, SIGNAL(clicked()),this, SLOT(drawPolyline())); connect(ui->actionPoints, SIGNAL(triggered()), this, SLOT(drawPoint())); connect(ui->actionLine, SIGNAL(triggered()), this, SLOT(drawLine())); connect(ui->actionCircle, SIGNAL(triggered()), this, SLOT(drawCircle())); connect(ui->actionEllipse, SIGNAL(triggered()), this, SLOT(drawEllipse())); connect(ui->actionArc, SIGNAL(triggered()), this, SLOT(drawArc())); connect(ui->actionPolyline, SIGNAL(triggered()), this, SLOT(drawPolyline())); addToolbars(); connect(ui->actionNew, SIGNAL(triggered()), this, SLOT(newFile())); connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(close()));
void KivioShapePainter::drawShape( KivioShape *pShape, float x, float y, float w, float h ) { KivioShapeData *pShapeData; m_x = x; m_y = y; m_w = w; m_h = h; m_pShape = pShape; pShapeData = pShape->shapeData(); switch( pShapeData->shapeType() ) { case KivioShapeData::kstArc: drawArc(); break; case KivioShapeData::kstPie: drawPie(); break; case KivioShapeData::kstLineArray: drawLineArray(); break; case KivioShapeData::kstPolyline: drawPolyline(); break; case KivioShapeData::kstPolygon: drawPolygon(); break; case KivioShapeData::kstBezier: drawBezier(); break; case KivioShapeData::kstRectangle: drawRectangle(); break; case KivioShapeData::kstRoundRectangle: drawRoundRectangle(); break; case KivioShapeData::kstEllipse: drawEllipse(); break; case KivioShapeData::kstOpenPath: drawOpenPath(); break; case KivioShapeData::kstClosedPath: drawClosedPath(); break; case KivioShapeData::kstTextBox: drawTextBox(); break; case KivioShapeData::kstNone: default: break; } }
static void drawArc(uiDrawPath *p, struct arc *a, void (*startFunction)(uiDrawPath *, double, double)) { double sinx, cosx; double startX, startY; double endX, endY; D2D1_ARC_SEGMENT as; BOOL fullCircle; double absSweep; // as above, we can't do a full circle with one arc // simulate it with two half-circles // of course, we have a dragon: equality on floating-point values! // I've chosen to do the AlmostEqualRelative() technique in https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ fullCircle = FALSE; // use the absolute value to tackle both ≥2π and ≤-2π at the same time absSweep = fabs(a->sweep); if (absSweep > (2 * M_PI)) // this part is easy fullCircle = TRUE; else { double aerDiff; aerDiff = fabs(absSweep - (2 * M_PI)); // if we got here then we know a->sweep is larger (or the same!) fullCircle = aerDiff <= absSweep * aerMax; } // TODO make sure this works right for the negative direction if (fullCircle) { a->sweep = M_PI; drawArc(p, a, startFunction); a->startAngle += M_PI; drawArc(p, a, NULL); return; } // first, figure out the arc's endpoints // unfortunately D2D1SinCos() is only defined on Windows 8 and newer // the MSDN page doesn't say this, but says it requires d2d1_1.h, which is listed as only supported on Windows 8 and newer elsewhere on MSDN // so we must use sin() and cos() and hope it's right... sinx = sin(a->startAngle); cosx = cos(a->startAngle); startX = a->xCenter + a->radius * cosx; startY = a->yCenter + a->radius * sinx; sinx = sin(a->startAngle + a->sweep); cosx = cos(a->startAngle + a->sweep); endX = a->xCenter + a->radius * cosx; endY = a->yCenter + a->radius * sinx; // now do the initial step to get the current point to be the start point // this is either creating a new figure, drawing a line, or (in the case of our full circle code above) doing nothing if (startFunction != NULL) (*startFunction)(p, startX, startY); // now we can draw the arc as.point.x = endX; as.point.y = endY; as.size.width = a->radius; as.size.height = a->radius; as.rotationAngle = 0; // as above, not relevant for circles if (a->negative) as.sweepDirection = D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE; else as.sweepDirection = D2D1_SWEEP_DIRECTION_CLOCKWISE; // TODO explain the outer if if (!a->negative) if (a->sweep > M_PI) as.arcSize = D2D1_ARC_SIZE_LARGE; else as.arcSize = D2D1_ARC_SIZE_SMALL; else // TODO especially this part if (a->sweep > M_PI) as.arcSize = D2D1_ARC_SIZE_SMALL; else as.arcSize = D2D1_ARC_SIZE_LARGE; ID2D1GeometrySink_AddArc(p->sink, &as); }
namespace SkRecords { // NoOps draw nothing. template <> void Draw::draw(const NoOp&) {} #define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; } DRAW(Restore, restore()); DRAW(Save, save()); DRAW(SaveLayer, saveLayer(SkCanvas::SaveLayerRec(r.bounds, r.paint, r.backdrop.get(), r.saveLayerFlags))); DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix))); DRAW(Concat, concat(r.matrix)); DRAW(Translate, translate(r.dx, r.dy)); DRAW(ClipPath, clipPath(r.path, r.opAA.op, r.opAA.aa)); DRAW(ClipRRect, clipRRect(r.rrect, r.opAA.op, r.opAA.aa)); DRAW(ClipRect, clipRect(r.rect, r.opAA.op, r.opAA.aa)); DRAW(ClipRegion, clipRegion(r.region, r.op)); #ifdef SK_EXPERIMENTAL_SHADOWING DRAW(TranslateZ, SkCanvas::translateZ(r.z)); #else template <> void Draw::draw(const TranslateZ& r) { } #endif DRAW(DrawArc, drawArc(r.oval, r.startAngle, r.sweepAngle, r.useCenter, r.paint)); DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint)); DRAW(DrawImage, drawImage(r.image.get(), r.left, r.top, r.paint)); template <> void Draw::draw(const DrawImageLattice& r) { SkCanvas::Lattice lattice; lattice.fXCount = r.xCount; lattice.fXDivs = r.xDivs; lattice.fYCount = r.yCount; lattice.fYDivs = r.yDivs; lattice.fFlags = (0 == r.flagCount) ? nullptr : r.flags; lattice.fBounds = &r.src; fCanvas->drawImageLattice(r.image.get(), lattice, r.dst, r.paint); } DRAW(DrawImageRect, legacy_drawImageRect(r.image.get(), r.src, r.dst, r.paint, r.constraint)); DRAW(DrawImageNine, drawImageNine(r.image.get(), r.center, r.dst, r.paint)); DRAW(DrawOval, drawOval(r.oval, r.paint)); DRAW(DrawPaint, drawPaint(r.paint)); DRAW(DrawPath, drawPath(r.path, r.paint)); DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode, r.paint)); DRAW(DrawPicture, drawPicture(r.picture.get(), &r.matrix, r.paint)); #ifdef SK_EXPERIMENTAL_SHADOWING DRAW(DrawShadowedPicture, drawShadowedPicture(r.picture.get(), &r.matrix, r.paint, r.params)); #else template <> void Draw::draw(const DrawShadowedPicture& r) { } #endif DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint)); DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint)); DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint)); DRAW(DrawRRect, drawRRect(r.rrect, r.paint)); DRAW(DrawRect, drawRect(r.rect, r.paint)); DRAW(DrawRegion, drawRegion(r.region, r.paint)); DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint)); DRAW(DrawTextBlob, drawTextBlob(r.blob.get(), r.x, r.y, r.paint)); DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, &r.matrix, r.paint)); DRAW(DrawTextRSXform, drawTextRSXform(r.text, r.byteLength, r.xforms, r.cull, r.paint)); DRAW(DrawAtlas, drawAtlas(r.atlas.get(), r.xforms, r.texs, r.colors, r.count, r.mode, r.cull, r.paint)); DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors, r.xmode, r.indices, r.indexCount, r.paint)); DRAW(DrawAnnotation, drawAnnotation(r.rect, r.key.c_str(), r.value.get())); #undef DRAW template <> void Draw::draw(const DrawDrawable& r) { SkASSERT(r.index >= 0); SkASSERT(r.index < fDrawableCount); if (fDrawables) { SkASSERT(nullptr == fDrawablePicts); fCanvas->drawDrawable(fDrawables[r.index], r.matrix); } else { fCanvas->drawPicture(fDrawablePicts[r.index], r.matrix, nullptr); } } // This is an SkRecord visitor that fills an SkBBoxHierarchy. // // The interesting part here is how to calculate bounds for ops which don't // have intrinsic bounds. What is the bounds of a Save or a Translate? // // We answer this by thinking about a particular definition of bounds: if I // don't execute this op, pixels in this rectangle might draw incorrectly. So // the bounds of a Save, a Translate, a Restore, etc. are the union of the // bounds of Draw* ops that they might have an effect on. For any given // Save/Restore block, the bounds of the Save, the Restore, and any other // non-drawing ("control") ops inside are exactly the union of the bounds of // the drawing ops inside that block. // // To implement this, we keep a stack of active Save blocks. As we consume ops // inside the Save/Restore block, drawing ops are unioned with the bounds of // the block, and control ops are stashed away for later. When we finish the // block with a Restore, our bounds are complete, and we go back and fill them // in for all the control ops we stashed away. class FillBounds : SkNoncopyable { public: FillBounds(const SkRect& cullRect, const SkRecord& record, SkRect bounds[]) : fNumRecords(record.count()) , fCullRect(cullRect) , fBounds(bounds) { fCTM = SkMatrix::I(); fCurrentClipBounds = fCullRect; } void cleanUp() { // If we have any lingering unpaired Saves, simulate restores to make // sure all ops in those Save blocks have their bounds calculated. while (!fSaveStack.isEmpty()) { this->popSaveBlock(); } // Any control ops not part of any Save/Restore block draw everywhere. while (!fControlIndices.isEmpty()) { this->popControl(fCullRect); } } void setCurrentOp(int currentOp) { fCurrentOp = currentOp; } template <typename T> void operator()(const T& op) { this->updateCTM(op); this->updateClipBounds(op); this->trackBounds(op); } // In this file, SkRect are in local coordinates, Bounds are translated back to identity space. typedef SkRect Bounds; int currentOp() const { return fCurrentOp; } const SkMatrix& ctm() const { return fCTM; } const Bounds& getBounds(int index) const { return fBounds[index]; } // Adjust rect for all paints that may affect its geometry, then map it to identity space. Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const { // Inverted rectangles really confuse our BBHs. rect.sort(); // Adjust the rect for its own paint. if (!AdjustForPaint(paint, &rect)) { // The paint could do anything to our bounds. The only safe answer is the current clip. return fCurrentClipBounds; } // Adjust rect for all the paints from the SaveLayers we're inside. if (!this->adjustForSaveLayerPaints(&rect)) { // Same deal as above. return fCurrentClipBounds; } // Map the rect back to identity space. fCTM.mapRect(&rect); // Nothing can draw outside the current clip. if (!rect.intersect(fCurrentClipBounds)) { return Bounds::MakeEmpty(); } return rect; } private: struct SaveBounds { int controlOps; // Number of control ops in this Save block, including the Save. Bounds bounds; // Bounds of everything in the block. const SkPaint* paint; // Unowned. If set, adjusts the bounds of all ops in this block. SkMatrix ctm; }; // Only Restore, SetMatrix, Concat, and Translate change the CTM. template <typename T> void updateCTM(const T&) {} void updateCTM(const Restore& op) { fCTM = op.matrix; } void updateCTM(const SetMatrix& op) { fCTM = op.matrix; } void updateCTM(const Concat& op) { fCTM.preConcat(op.matrix); } void updateCTM(const Translate& op) { fCTM.preTranslate(op.dx, op.dy); } // Most ops don't change the clip. template <typename T> void updateClipBounds(const T&) {} // Clip{Path,RRect,Rect,Region} obviously change the clip. They all know their bounds already. void updateClipBounds(const ClipPath& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRRect& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRect& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRegion& op) { this->updateClipBoundsForClipOp(op.devBounds); } // The bounds of clip ops need to be adjusted for the paints of saveLayers they're inside. void updateClipBoundsForClipOp(const SkIRect& devBounds) { Bounds clip = SkRect::Make(devBounds); // We don't call adjustAndMap() because as its last step it would intersect the adjusted // clip bounds with the previous clip, exactly what we can't do when the clip grows. if (this->adjustForSaveLayerPaints(&clip)) { fCurrentClipBounds = clip.intersect(fCullRect) ? clip : Bounds::MakeEmpty(); } else { fCurrentClipBounds = fCullRect; } } // Restore holds the devBounds for the clip after the {save,saveLayer}/restore block completes. void updateClipBounds(const Restore& op) { // This is just like the clip ops above, but we need to skip the effects (if any) of our // paired saveLayer (if it is one); it has not yet been popped off the save stack. Our // devBounds reflect the state of the world after the saveLayer/restore block is done, // so they are not affected by the saveLayer's paint. const int kSavesToIgnore = 1; Bounds clip = SkRect::Make(op.devBounds); if (this->adjustForSaveLayerPaints(&clip, kSavesToIgnore)) { fCurrentClipBounds = clip.intersect(fCullRect) ? clip : Bounds::MakeEmpty(); } else { fCurrentClipBounds = fCullRect; } } // We also take advantage of SaveLayer bounds when present to further cut the clip down. void updateClipBounds(const SaveLayer& op) { if (op.bounds) { // adjustAndMap() intersects these layer bounds with the previous clip for us. fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint); } } // The bounds of these ops must be calculated when we hit the Restore // from the bounds of the ops in the same Save block. void trackBounds(const Save&) { this->pushSaveBlock(nullptr); } void trackBounds(const SaveLayer& op) { this->pushSaveBlock(op.paint); } void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(); } void trackBounds(const SetMatrix&) { this->pushControl(); } void trackBounds(const Concat&) { this->pushControl(); } void trackBounds(const Translate&) { this->pushControl(); } void trackBounds(const TranslateZ&) { this->pushControl(); } void trackBounds(const ClipRect&) { this->pushControl(); } void trackBounds(const ClipRRect&) { this->pushControl(); } void trackBounds(const ClipPath&) { this->pushControl(); } void trackBounds(const ClipRegion&) { this->pushControl(); } // For all other ops, we can calculate and store the bounds directly now. template <typename T> void trackBounds(const T& op) { fBounds[fCurrentOp] = this->bounds(op); this->updateSaveBounds(fBounds[fCurrentOp]); } void pushSaveBlock(const SkPaint* paint) { // Starting a new Save block. Push a new entry to represent that. SaveBounds sb; sb.controlOps = 0; // If the paint affects transparent black, the bound shouldn't be smaller // than the current clip bounds. sb.bounds = PaintMayAffectTransparentBlack(paint) ? fCurrentClipBounds : Bounds::MakeEmpty(); sb.paint = paint; sb.ctm = this->fCTM; fSaveStack.push(sb); this->pushControl(); } static bool PaintMayAffectTransparentBlack(const SkPaint* paint) { if (paint) { // FIXME: this is very conservative if (paint->getImageFilter() || paint->getColorFilter()) { return true; } // Unusual blendmodes require us to process a saved layer // even with operations outisde the clip. // For example, DstIn is used by masking layers. // https://code.google.com/p/skia/issues/detail?id=1291 // https://crbug.com/401593 switch (paint->getBlendMode()) { // For each of the following transfer modes, if the source // alpha is zero (our transparent black), the resulting // blended alpha is not necessarily equal to the original // destination alpha. case SkBlendMode::kClear: case SkBlendMode::kSrc: case SkBlendMode::kSrcIn: case SkBlendMode::kDstIn: case SkBlendMode::kSrcOut: case SkBlendMode::kDstATop: case SkBlendMode::kModulate: return true; break; default: break; } } return false; } Bounds popSaveBlock() { // We're done the Save block. Apply the block's bounds to all control ops inside it. SaveBounds sb; fSaveStack.pop(&sb); while (sb.controlOps --> 0) { this->popControl(sb.bounds); } // This whole Save block may be part another Save block. this->updateSaveBounds(sb.bounds); // If called from a real Restore (not a phony one for balance), it'll need the bounds. return sb.bounds; } void pushControl() { fControlIndices.push(fCurrentOp); if (!fSaveStack.isEmpty()) { fSaveStack.top().controlOps++; } } void popControl(const Bounds& bounds) { fBounds[fControlIndices.top()] = bounds; fControlIndices.pop(); } void updateSaveBounds(const Bounds& bounds) { // If we're in a Save block, expand its bounds to cover these bounds too. if (!fSaveStack.isEmpty()) { fSaveStack.top().bounds.join(bounds); } } // FIXME: this method could use better bounds Bounds bounds(const DrawText&) const { return fCurrentClipBounds; } Bounds bounds(const DrawPaint&) const { return fCurrentClipBounds; } Bounds bounds(const NoOp&) const { return Bounds::MakeEmpty(); } // NoOps don't draw. Bounds bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); } Bounds bounds(const DrawRegion& op) const { SkRect rect = SkRect::Make(op.region.getBounds()); return this->adjustAndMap(rect, &op.paint); } Bounds bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval, &op.paint); } // Tighter arc bounds? Bounds bounds(const DrawArc& op) const { return this->adjustAndMap(op.oval, &op.paint); } Bounds bounds(const DrawRRect& op) const { return this->adjustAndMap(op.rrect.rect(), &op.paint); } Bounds bounds(const DrawDRRect& op) const { return this->adjustAndMap(op.outer.rect(), &op.paint); } Bounds bounds(const DrawImage& op) const { const SkImage* image = op.image.get(); SkRect rect = SkRect::MakeXYWH(op.left, op.top, image->width(), image->height()); return this->adjustAndMap(rect, op.paint); } Bounds bounds(const DrawImageLattice& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawImageRect& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawImageNine& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawPath& op) const { return op.path.isInverseFillType() ? fCurrentClipBounds : this->adjustAndMap(op.path.getBounds(), &op.paint); } Bounds bounds(const DrawPoints& op) const { SkRect dst; dst.set(op.pts, op.count); // Pad the bounding box a little to make sure hairline points' bounds aren't empty. SkScalar stroke = SkMaxScalar(op.paint.getStrokeWidth(), 0.01f); dst.outset(stroke/2, stroke/2); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawPatch& op) const { SkRect dst; dst.set(op.cubics, SkPatchUtils::kNumCtrlPts); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawVertices& op) const { SkRect dst; dst.set(op.vertices, op.vertexCount); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawAtlas& op) const { if (op.cull) { // TODO: <reed> can we pass nullptr for the paint? Isn't cull already "correct" // for the paint (by the caller)? return this->adjustAndMap(*op.cull, op.paint); } else { return fCurrentClipBounds; } } Bounds bounds(const DrawPicture& op) const { SkRect dst = op.picture->cullRect(); op.matrix.mapRect(&dst); return this->adjustAndMap(dst, op.paint); } Bounds bounds(const DrawShadowedPicture& op) const { SkRect dst = op.picture->cullRect(); op.matrix.mapRect(&dst); return this->adjustAndMap(dst, op.paint); } Bounds bounds(const DrawPosText& op) const { const int N = op.paint.countText(op.text, op.byteLength); if (N == 0) { return Bounds::MakeEmpty(); } SkRect dst; dst.set(op.pos, N); AdjustTextForFontMetrics(&dst, op.paint); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawPosTextH& op) const { const int N = op.paint.countText(op.text, op.byteLength); if (N == 0) { return Bounds::MakeEmpty(); } SkScalar left = op.xpos[0], right = op.xpos[0]; for (int i = 1; i < N; i++) { left = SkMinScalar(left, op.xpos[i]); right = SkMaxScalar(right, op.xpos[i]); } SkRect dst = { left, op.y, right, op.y }; AdjustTextForFontMetrics(&dst, op.paint); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawTextOnPath& op) const { SkRect dst = op.path.getBounds(); // Pad all sides by the maximum padding in any direction we'd normally apply. SkRect pad = { 0, 0, 0, 0}; AdjustTextForFontMetrics(&pad, op.paint); // That maximum padding happens to always be the right pad today. SkASSERT(pad.fLeft == -pad.fRight); SkASSERT(pad.fTop == -pad.fBottom); SkASSERT(pad.fRight > pad.fBottom); dst.outset(pad.fRight, pad.fRight); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawTextRSXform& op) const { if (op.cull) { return this->adjustAndMap(*op.cull, nullptr); } else { return fCurrentClipBounds; } } Bounds bounds(const DrawTextBlob& op) const { SkRect dst = op.blob->bounds(); dst.offset(op.x, op.y); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawDrawable& op) const { return this->adjustAndMap(op.worstCaseBounds, nullptr); } Bounds bounds(const DrawAnnotation& op) const { return this->adjustAndMap(op.rect, nullptr); } static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { #ifdef SK_DEBUG SkRect correct = *rect; #endif // crbug.com/373785 ~~> xPad = 4x yPad // crbug.com/424824 ~~> bump yPad from 2x text size to 2.5x const SkScalar yPad = 2.5f * paint.getTextSize(), xPad = 4.0f * yPad; rect->outset(xPad, yPad); #ifdef SK_DEBUG SkPaint::FontMetrics metrics; paint.getFontMetrics(&metrics); correct.fLeft += metrics.fXMin; correct.fTop += metrics.fTop; correct.fRight += metrics.fXMax; correct.fBottom += metrics.fBottom; // See skia:2862 for why we ignore small text sizes. SkASSERTF(paint.getTextSize() < 0.001f || rect->contains(correct), "%f %f %f %f vs. %f %f %f %f\n", -xPad, -yPad, +xPad, +yPad, metrics.fXMin, metrics.fTop, metrics.fXMax, metrics.fBottom); #endif } // Returns true if rect was meaningfully adjusted for the effects of paint, // false if the paint could affect the rect in unknown ways. static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) { if (paint) { if (paint->canComputeFastBounds()) { *rect = paint->computeFastBounds(*rect, rect); return true; } return false; } return true; } bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const { for (int i = fSaveStack.count() - 1 - savesToIgnore; i >= 0; i--) { SkMatrix inverse; if (!fSaveStack[i].ctm.invert(&inverse)) { return false; } inverse.mapRect(rect); if (!AdjustForPaint(fSaveStack[i].paint, rect)) { return false; } fSaveStack[i].ctm.mapRect(rect); } return true; } const int fNumRecords; // We do not guarantee anything for operations outside of the cull rect const SkRect fCullRect; // Conservative identity-space bounds for each op in the SkRecord. Bounds* fBounds; // We walk fCurrentOp through the SkRecord, as we go using updateCTM() // and updateClipBounds() to maintain the exact CTM (fCTM) and conservative // identity-space bounds of the current clip (fCurrentClipBounds). int fCurrentOp; SkMatrix fCTM; Bounds fCurrentClipBounds; // Used to track the bounds of Save/Restore blocks and the control ops inside them. SkTDArray<SaveBounds> fSaveStack; SkTDArray<int> fControlIndices; }; } // namespace SkRecords
void execute_commands(char instruction[]) { bool axisSelected; // Do we have lineNr and checksums in this gcode? if((bool)(gc.seen[GCODE_CHECKSUM]) | (bool)(gc.seen[GCODE_N])) { // Check that if recieved a L code, we also got a C code. If not, one of them has been lost, and we have to reset queue if( (bool)(gc.seen[GCODE_CHECKSUM]) != (bool)(gc.seen[GCODE_N]) ) { if(SendDebug & DEBUG_ERRORS) { if(gc.seen[GCODE_CHECKSUM]) sprintf(talkToHost.string(), "Serial Error: checksum without line number. Checksum: %d, line received: %s", gc.Checksum, instruction); else sprintf(talkToHost.string(), "Serial Error: line number without checksum. Linenumber: %ld, line received: %s", gc.N, instruction); } talkToHost.setResend(gc.LastLineNrRecieved+1); return; } // Check checksum of this string. Flush buffers and re-request line of error is found if(gc.seen[GCODE_CHECKSUM]) // if we recieved a line nr, we know we also recieved a Checksum, so check it { // Calc checksum. byte checksum = 0; byte count=0; while(instruction[count] != '*') checksum = checksum^instruction[count++]; // Check checksum. if(gc.Checksum != (int)checksum) { if(SendDebug & DEBUG_ERRORS) sprintf(talkToHost.string(), "Serial Error: checksum mismatch. Remote (%d) not equal to local (%d), line received: %s", gc.Checksum, (int)checksum, instruction); talkToHost.setResend(gc.LastLineNrRecieved+1); return; } // Check that this lineNr is LastLineNrRecieved+1. If not, flush if(!( (bool)(gc.seen[GCODE_M]) && gc.M == 110)) // unless this is a reset-lineNr command if(gc.N != gc.LastLineNrRecieved+1) { if(SendDebug & DEBUG_ERRORS) sprintf(talkToHost.string(), "Serial Error: Linenumber (%ld) is not last + 1 (%ld), line received: %s", gc.N, gc.LastLineNrRecieved+1, instruction); talkToHost.setResend(gc.LastLineNrRecieved+1); return; } //If we reach this point, communication is a succes, update our "last good line nr" and continue gc.LastLineNrRecieved = gc.N; } } /* if no command was seen, but parameters were, then use the last G code as * the current command */ if ((!(gc.seen[GCODE_G] | gc.seen[GCODE_M] | gc.seen[GCODE_T])) && (seenAnything() && (last_gcode_g >= 0))) { /* yes - so use the previous command with the new parameters */ gc.G[0] = last_gcode_g; gc.GIndex=1; gc.seen[GCODE_G]=true; } // Deal with emergency stop as No 1 priority if ((gc.seen[GCODE_M]) && (gc.M == 112)) sharedMachineModel.shutdown(); //did we get a gcode? if (gc.seen[GCODE_G]) { // Handle all GCodes in this line for(int gIndex=0; gIndex<gc.GIndex; gIndex++) { last_gcode_g = gc.G[gIndex]; /* remember this for future instructions */ unsigned long endTime; // For Dwell // Process the buffered move commands first bool gCodeHandled=false; switch (gc.G[gIndex]) { //////////////////////// // Buffered commands //////////////////////// case 0: //Rapid move fetchCartesianParameters(); rapidMove(fp); break; case 1: // Controlled move; fetchCartesianParameters(); sharedMachineModel.qMove(fp); break; case 2: // G2, Clockwise arc case 3: // G3, Counterclockwise arc fetchCartesianParameters(); if(gc.seen[GCODE_R]) { //drawRadius(tempX, tempY, rVal, (gc.G[gIndex]==2)); if(SendDebug & DEBUG_ERRORS) sprintf(talkToHost.string(), "Dud G code: G%d with R param not yet implemented", gc.G[gIndex]); talkToHost.setResend(gc.LastLineNrRecieved+1); } else if(gc.seen[GCODE_I] || gc.seen[GCODE_J]) { drawArc(fp.x+gc.I, fp.y+gc.J, fp.x, fp.y, (gc.G[gIndex]==2)); } else { if(SendDebug & DEBUG_ERRORS) sprintf(talkToHost.string(), "Dud G code: G%d without I or J params", gc.G[gIndex]); talkToHost.setResend(gc.LastLineNrRecieved+1); } break; case 28: //go home. If we send coordinates (regardless of their value) only zero those axes fetchCartesianParameters(); axisSelected = false; if(gc.seen[GCODE_Z]) { sharedMachineModel.zeroZ(); axisSelected = true; } if(gc.seen[GCODE_X]) { sharedMachineModel.zeroX(); axisSelected = true; } if(gc.seen[GCODE_Y]) { sharedMachineModel.zeroY(); axisSelected = true; } if(!axisSelected) { sharedMachineModel.zeroZ(); sharedMachineModel.zeroX(); sharedMachineModel.zeroY(); sharedMachineModel.absolutePositionValid=true; } sharedMachineModel.localPosition.f = SLOW_FEEDRATE; // Most sensible feedrate to leave it in break; //////////////////////// // Non-Buffered commands //////////////////////// case 4: //Dwell sharedMachineModel.waitFor_qEmpty(); // Non-buffered G command. Wait till the buffer q is empty first endTime = millis() + (int)(gc.P + 0.5); while(millis() < endTime) sharedMachineModel.manage(true); break; case 20: //Inches for Units sharedMachineModel.waitFor_qEmpty(); // Non-buffered G command. Wait till the buffer q is empty first sharedMachineModel.setUnits(false); break; case 21: //mm for Units sharedMachineModel.waitFor_qEmpty(); // Non-buffered G command. Wait till the buffer q is empty first sharedMachineModel.setUnits(true); break; case 54: case 55: case 56: case 57: case 58: case 59: // Switch to Workin Coordinate System sharedMachineModel.waitFor_qEmpty(); // Non-buffered G command. Wait till the buffer q is empty first if(!sharedMachineModel.switchToWCS(gc.G[gIndex]-54)) { if(SendDebug & DEBUG_ERRORS) sprintf(talkToHost.string(), "Dud G code: G%d not possible, probably machine not homed", gc.G[gIndex]); talkToHost.setResend(gc.LastLineNrRecieved+1); } break; case 73: // Peck drilling cycle for milling - high-speed case 81: // Drill Cycle case 82: // Drill Cycle with dwell case 83: // Drill Cycle peck drilling case 85: // Drill Cycle, slow retract case 89: // Drill Cycle with dwell and slow reredract sharedMachineModel.waitFor_qEmpty(); // Non-buffered G command. Wait till the buffer q is empty first fetchCartesianParameters(); doDrillCycle(gc.G[gIndex], fp); break; case 90: //Absolute Positioning sharedMachineModel.waitFor_qEmpty(); // Non-buffered G command. Wait till the buffer q is empty first sharedMachineModel.setAbsMode(true); break; case 91: //Incremental Positioning sharedMachineModel.waitFor_qEmpty(); // Non-buffered G command. Wait till the buffer q is empty first sharedMachineModel.setAbsMode(false); break; case 92: //Set position as fp sharedMachineModel.waitFor_qEmpty(); // Non-buffered G command. Wait till the buffer q is empty first fetchCartesianParameters(); sharedMachineModel.setLocalZero(fp); break; case 98: // Return to initial Z level in canned cycle sharedMachineModel.waitFor_qEmpty(); // Non-buffered G command. Wait till the buffer q is empty first sharedMachineModel.setRetractMode(true); break; case 99: // Return to R level in canned cycle sharedMachineModel.waitFor_qEmpty(); // Non-buffered G command. Wait till the buffer q is empty first sharedMachineModel.setRetractMode(false); break; default: if(SendDebug & DEBUG_ERRORS) sprintf(talkToHost.string(), "Dud G code: G%d", gc.G[gIndex]); talkToHost.setResend(gc.LastLineNrRecieved+1); } // switch } // for } // Gcode // Get feedrate if supplied and queue is empty if ( gc.seen[GCODE_F] && sharedMachineModel.qEmpty()) sharedMachineModel.localPosition.f=MIN(gc.F, FAST_XY_FEEDRATE); //find us an m code. if (gc.seen[GCODE_M]) { // Wait till the q is empty first sharedMachineModel.waitFor_qEmpty(); switch (gc.M) { case 0: sharedMachineModel.shutdown(); break; case 1: //todo: optional stop break; case 2: //todo: program end break; case 6: // Tool change if(gc.seen[GCODE_T]) sharedMachineModel.manualToolChange(gc.T); else sharedMachineModel.manualToolChange(-1); break; //custom code for temperature control // case 104: // if (gc.seen[GCODE_S]) // { // ex[extruder_in_use]->setTemperature((int)gc.S); // } // break; //custom code for temperature reading // case 105: // talkToHost.setETemp(ex[extruder_in_use]->getTemperature()); // talkToHost.setBTemp(heatedBed.getTemperature()); // break; // // //turn fan on // case 106: // ex[extruder_in_use]->setCooler(255); // break; // // //turn fan off // case 107: // ex[extruder_in_use]->setCooler(0); // break; // // // // Set the temperature and wait for it to get there // case 109: // ex[extruder_in_use]->setTemperature((int)gc.S); // ex[extruder_in_use]->waitForTemperature(); // break; // Starting a new print, reset the gc.LastLineNrRecieved counter case 110: if (gc.seen[GCODE_N]) gc.LastLineNrRecieved = gc.N; break; case 111: SendDebug = gc.S; break; case 112: // STOP! (priority commnand) sharedMachineModel.shutdown(); break; //custom code for returning current coordinates case 114: talkToHost.setCoords(sharedMachineModel.localPosition); break; //Reserved for returning machine capabilities in keyword:value pairs //custom code for returning Firmware Version and Capabilities case 115: talkToHost.capabilities(); break; // // TODO: make this work properly // case 116: // ex[extruder_in_use]->waitForTemperature(); // break; //custom code for returning zero-hit coordinates // case 117: // talkToHost.setCoords(zeroHit); // break; // The valve (real, or virtual...) is now the way to control any extruder (such as // a pressurised paste extruder) that cannot move using E codes. // // Open the valve // case 126: // ex[extruder_in_use]->valveSet(true, (int)(gc.P + 0.5)); // break; // // // Close the valve // case 127: // ex[extruder_in_use]->valveSet(false, (int)(gc.P + 0.5)); // break; // case 140: // if (gc.seen[GCODE_S]) // { // heatedBed.setTemperature((int)gc.S); // } // break; case 141: //TODO: set chamber temperature break; case 142: //TODO: set holding pressure break; // Pleasant Mill priority commands // These commands are executed, even if the machine isn't in "armed for data" mode case 900: // Machine-Identification sprintf(talkToHost.string(), "Pleasant Mill[%s]", FW_VERSION); break; case 901: // Get Device Name sprintf(talkToHost.string(), EEPROM_ReadString(EEPROM_ADR_DEVICENAME, strBuffer)); break; case 902: // Set Device Name: The string argument is found in the commen if(strlen(strArgBuffer)>0) { strBuffer[16]=0x0; EEPROM_WriteString(EEPROM_ADR_DEVICENAME, strArgBuffer); } else { if(SendDebug & DEBUG_ERRORS) sprintf(talkToHost.string(), "Error: M902 not possible, bad device name argument: %s", strArgBuffer); talkToHost.setResend(gc.LastLineNrRecieved+1); } break; default: if(SendDebug & DEBUG_ERRORS) sprintf(talkToHost.string(), "Dud M code: M%d", gc.M); talkToHost.setResend(gc.LastLineNrRecieved+1); } } // Tool (i.e. extruder) change? if (gc.seen[GCODE_T]) { sharedMachineModel.waitFor_qEmpty(); // newExtruder(gc.T); } }