void View::DrawThickBezierCurve(DeviceContext *dc, Point p1, Point p2, Point c1, Point c2, int thickness, int staffSize, float angle) { assert( dc ); int bez1[6], bez2[6]; // filled array with control points and end point Point c1Rotated = c1; Point c2Rotated = c2; c1Rotated.y += thickness / 2; c2Rotated.y += thickness / 2; if (angle != 0.0) { c1Rotated = CalcPositionAfterRotation(c1Rotated, angle, c1); c2Rotated = CalcPositionAfterRotation(c2Rotated, angle, c2); } // Points for first bez, they go from xy to x1y1 bez1[0] = ToDeviceContextX(c1Rotated.x); bez1[1] = ToDeviceContextY(c1Rotated.y); bez1[2] = ToDeviceContextX(c2Rotated.x); bez1[3] = ToDeviceContextY(c2Rotated.y); bez1[4] = ToDeviceContextX(p2.x); bez1[5] = ToDeviceContextY(p2.y); c1Rotated = c1; c2Rotated = c2; c1Rotated.y -= thickness / 2; c2Rotated.y -= thickness / 2; if (angle != 0.0) { c1Rotated = CalcPositionAfterRotation(c1Rotated, angle, c1); c2Rotated = CalcPositionAfterRotation(c2Rotated, angle, c2); } // second bez. goes back bez2[0] = ToDeviceContextX(c2Rotated.x); bez2[1] = ToDeviceContextY(c2Rotated.y); bez2[2] = ToDeviceContextX(c1Rotated.x); bez2[3] = ToDeviceContextY(c1Rotated.y); bez2[4] = ToDeviceContextX(p1.x); bez2[5] = ToDeviceContextY(p1.y); // Actually draw it dc->SetPen( m_currentColour, std::max( 1, m_doc->GetDrawingStemWidth(staffSize) / 2 ), AxSOLID ); dc->DrawComplexBezierPath(ToDeviceContextX(p1.x), ToDeviceContextY(p1.y), bez1, bez2); dc->ResetPen(); }
/** x1 y1 = point de depart x2 y2 = point d'arrivee up = liaison vers le haut heigth = hauteur de la liaison ( ‡ plat ) **/ void MusRC::DrawSlur( MusDC *dc, MusLayer *layer, int x1, int y1, int x2, int y2, bool up, int height ) { wxASSERT_MSG( layer, "Pointer to layer cannot be NULL" ); wxASSERT_MSG( layer->m_parent, "Pointer to staff cannot be NULL" ); dc->SetPen( m_currentColour, 1, wxSOLID ); dc->SetBrush( m_currentColour, wxSOLID ); int distX = x1 - x2; int distY = y1 - y2; // pythagore, distance entre les points de depart et d'arrivee int dist = (int)sqrt( pow( (double)distX, 2 ) + pow( (double)distY, 2 ) ); // angle float alpha2 = float( distY ) / float( distX ); alpha2 = atan( alpha2 ); MusPoint orig(0,0); int step = dist / 10; // espace entre les points int nbpoints = dist / step; dist += 2*step; // ajout d'un pas de chaque cote, supprime ‡ l'affichage if ( nbpoints <= 2) nbpoints = 3; else if ( !(nbpoints % 2) ) // nombre impair de points nbpoints++; int i,j, k; double a, b; a = dist / 2; // largeur de l'ellipse int nbp2 = nbpoints/2; MusPoint *points = new MusPoint[2*nbpoints]; // buffer double - aller retour // aller b = 100; // hauteur de l'ellipse points[nbp2].x = (int)a; // point central points[nbp2].y = (int)b; for(i = 0, j = nbpoints - 1, k = 1; i < nbp2; i++, j--, k++) // calcul de l'ellipse { points[i].x = k*step; points[i+nbp2+1].y = (int)sqrt( (1 - pow((double)points[i].x,2) / pow(a,2)) * pow(b,2) ); points[j].x = dist - points[i].x; points[j-nbp2-1].y = points[i+nbp2+1].y; } int dec_y = points[0].y; // decalage y ‡ cause des 2 pas ajoutes for(i = 0; i < nbpoints; i++) { points[i] = CalcPositionAfterRotation( points[i], alpha2, orig ); // rotation points[i].x = ToRendererX( points[i].x + x1 - 1*step ); // transposition points[i].y = ToRendererY( points[i].y + y1 - dec_y ); } dc->DrawSpline( nbpoints, points ); // retour idem b = 90; points[nbp2+nbpoints].x = (int)a; points[nbp2+nbpoints].y = (int)b; for(i = nbpoints, j = 2*nbpoints - 1, k = 1; i < nbp2+nbpoints; i++, j--, k++) { points[j].x = k*step; points[i+nbp2+1].y = (int)sqrt( (1 - pow((double)points[j].x,2) / pow(a,2)) * pow(b,2) ); points[i].x = dist - points[j].x; points[j-nbp2-1].y = points[i+nbp2+1].y; } dec_y = points[nbpoints].y; for(i = nbpoints; i < 2*nbpoints; i++) { points[i] = CalcPositionAfterRotation( points[i], alpha2, orig ); points[i].x = ToRendererX( points[i].x + x1 - 1*step ); points[i].y = ToRendererY( points[i].y + y1 - dec_y ); } dc->DrawSpline( nbpoints, points+nbpoints ); // remplissage ? dc->ResetPen( ); dc->ResetBrush( ); delete[] points; }