apeescape2.com
  • Põhiline
  • Tooteinimesed Ja Meeskonnad
  • Kujundusprotsess
  • Insenerihaldus
  • Tulud Ja Kasv
Tagumine Ots

Kuidas saada ümardatud nurkkujusid C ++ versioonis Bezieri kõverate ja QPainteri abil: samm-sammuline juhend

Sissejuhatus

The graafika kujundamise praegune suundumus on kasutada palju ümardatud nurki igasugustes kujundites. Seda fakti võime jälgida paljudel veebilehtedel, mobiilseadmetes ja töölauarakendustes. Kõige tähelepanuväärsemad näited on rakenduse nupud, mida kasutatakse klõpsamisel mõne toimingu käivitamiseks. Rangelt ristkülikukujulise kuju asemel, mille nurkades on 90-kraadised nurgad, joonistatakse need sageli ümardatud nurkadega. Ümarad nurgad muudavad kasutajaliidese sujuvamaks ja kenamaks. Ma pole selles täielikult veendunud, kuid mu disainerist sõber ütleb mulle seda.

Ümarad nurgad muudavad kasutajaliidese sujuvamaks ja kenamaks



Ümarad nurgad muudavad kasutajaliidese sujuvamaks ja kenamaks. Piiksuma

Kasutajaliideste visuaalsed elemendid on loodud disainerite poolt ja programmeerijal tuleb need vaid õigesse kohta paigutada. Aga mis juhtub, kui peame looma ümarate nurkadega kuju käigu pealt ja me ei saa seda eelkoormata? Mõni programmeerimisraamatukogu pakub piiratud võimalusi ümardatud nurkadega ettemääratud kujundite loomiseks, kuid tavaliselt ei saa neid keerulisematel juhtudel kasutada. Näiteks, Qt raamistik on klass QPainter , mida kasutatakse kõigi QPaintDevice -st tuletatud klasside, sealhulgas vidinate, pikslikaartide ja piltide joonistamiseks. Sellel on meetod nimega drawRoundedRect, mis, nagu nimigi ütleb, joonistab ümardatud nurkadega ristküliku. Kuid kui vajame veidi keerukamat kuju, peame selle ise rakendama. Kuidas saaksime seda teha hulknurga, tasapinnalise kujuga, mida piirab sirgjooneliste segmentide rühm? Kui meil on paberile pliiatsiga joonistatud hulknurk, oleks minu esimene idee kasutada kustutuskummi ja kustutada väike osa joontest igas nurgas ning seejärel ühendada ülejäänud segmendi otsad ringkaarega. Kogu protsessi saab illustreerida alloleval joonisel.

Ümarate nurkade käsitsi loomine

Klass QPainter on mõned ülekoormatud meetodid nimega drawArc, mis võivad joonistada ringkaari. Kõik need nõuavad parameetreid, mis määratlevad kaare keskpunkti ja suuruse, algusnurga ja kaare pikkuse. Kuigi pööramata ristküliku jaoks on nende parameetrite vajalikke väärtusi lihtne kindlaks määrata, on see hoopis teine ​​asi, kui tegemist on keerukamate hulknurkadega. Lisaks peaksime seda arvutust korrata iga hulknurga tipu kohta. See arvutus on pikk ja väsitav ülesanne ning inimestel on selle käigus kalduvus igasuguste arvutusvigade tekkimiseks. Kuid tarkvaraarendajate ülesanne on panna arvutid inimestele tööle, mitte vastupidi. Niisiis, siin ma näitan, kuidas arendada lihtsat klassi, mis võib keeruka hulknurga muuta ümarate nurkadega kujundiks. Selle klassi kasutajad peavad lisama ainult hulknurga tipud ja ülejäänud teeb klass. Oluline matemaatiline tööriist, mida selle ülesande jaoks kasutan, on Bezieri kõver .



Bezier kõverdub

Bezieri kõverate teooriat kirjeldavaid matemaatilisi raamatuid ja Interneti-ressursse on palju, nii et toon lühidalt asjakohased omadused.

Definitsiooni järgi on Bezieri kõver kõver kahe punkti vahel kahemõõtmelisel pinnal, mille trajektoori juhib üks või mitu kontrollpunkti. Rangelt võttes on kahe punkti vaheline kõver ilma täiendavate kontrollpunktideta ka Bezieri kõver. Kuna selle tulemuseks on kahe punkti vaheline sirgjoon, pole see eriti huvitav ega kasulik.

Kraadiline Bezier kõverad

Bezieri ruutkõveratel on üks kontrollpunkt. Teooria ütleb, et ruutu kandev Bezier kõverub punktide vahel P0 ja P2 kontrollpunktiga Püks on määratletud järgmiselt:



visuaalse taju geštaltpõhimõtted

B (t) = (1 - t)2P0+ 2t (1 - t) Püks+ t2P2, kus 0 ≤ t ≤ 1 (üks)

Millal siis t on võrdne 0 , B (t) annab järele P0 , millal t on võrdne üks , B (t) annab järele P2 , kuid igal teisel juhul väärtus B (t) sõltub ka Püks . Kuna väljend 2t (1 - t) maksimaalne väärtus on t = 0,5 , seal on mõju Püks peal B (t) saab olema suurim. Me võime välja mõelda Püks kui kujuteldav raskusallikas, mis tõmbab funktsiooni trajektoori enda poole. Alloleval joonisel on toodud mõned näited Bezieri ruutkõverate koos nende algus-, lõpp- ja kontrollpunktidega.

Kraadiline Bezier kõverad

Niisiis, kuidas lahendada oma probleem Bezieri kõverate abil? Allpool olev joonis pakub selgitust.

Kuidas koodi abil ümardatud nurki luua

Kui kujutame ette hulknurga tipu ja lühikese osa ühendatud joone segmentide kustutamist selle ümbruses, võime mõelda ühele rea lõigu otsale P0 , teise rea segmendi ots lõpeb P2 ja kustutatud tipp alates Püks . Rakendame sellele punktide komplektile ruutu Bezieri kõverat ja voila, seal on soovitud ümardatud nurk.

C ++ / Qt juurutamine QPainteri abil

Klass QPainter pole viisi, kuidas joonistada ruutkorralduslikke Bezieri kõveraid. Ehkki seda on võrrandi (1) järgi nullist juurutamine üsna lihtne, pakub Qt teek siiski paremat lahendust. 2D joonistamiseks on veel üks võimas klass: QPainterPath. Klass QPainterPath on joonte ja kõverate kogum, mida saab hiljem lisada QPainter -ga objekt. On mõned ülekoormatud meetodid, mis lisavad Bezieri kõverad praegusele kogu. Eelkõige meetodid quadTo lisab ruutu Bezieri kõverad. Kõver algab praegusest QPainterPath punkt ( P0 ), samas Püks ja P2 tuleb edastada quadTo parameetritena.

QPainter Meetod drawPath kasutatakse joonte ja kõverate kogu joonistamiseks QPainterPath objekt, mis tuleb anda parameetrina, aktiivse pliiatsi ja harjaga.

Nii et vaatame klassi deklaratsiooni:

class RoundedPolygon : public QPolygon { public: RoundedPolygon() { SetRadius(10); } void SetRadius(unsigned int iRadius) { m_iRadius = iRadius; } const QPainterPath& GetPath(); private: QPointF GetLineStart(int i) const; QPointF GetLineEnd(int i) const; float GetDistance(QPoint pt1, QPoint pt2) const; private: QPainterPath m_path; unsigned int m_iRadius; };

Otsustasin alamklassi QPolygon et ma ei peaks tippude ja muu kraami lisamist ise teostama. Lisaks konstruktorile, mis seab raadiuse mõnele mõistlikule algväärtusele, on sellel klassil veel kaks avalikku meetodit:

  • SetRadius meetod määrab raadiuseks antud väärtuse. Raadius on sirgjoone pikkus (pikslites) iga tipu lähedal, mis ümardatud nurga korral kustutatakse (või täpsemalt joonistamata).
  • GetPath on kõik arvutused. See tagastab QPainterPath RoundedPolygon -i lisatud hulknurga punktidest loodud objekt.

Privaatse osa meetodid on vaid abimeetodid, mida GetPath kasutavad.

parim staatilise saidi generaator 2018

Vaatame rakendust ja alustan privaatsetest meetoditest:

float RoundedPolygon::GetDistance(QPoint pt1, QPoint pt2) const { float fD = (pt1.x() - pt2.x())*(pt1.x() - pt2.x()) + (pt1.y() - pt2.y()) * (pt1.y() - pt2.y()); return sqrtf(fD); }

Siinkohal pole palju seletatav, meetod tagastab eukleidilise kauguse antud kahe punkti vahel.

QPointF RoundedPolygon::GetLineStart(int i) const { QPointF pt; QPoint pt1 = at(i); QPoint pt2 = at((i+1) % count()); float fRat = m_uiRadius / GetDistance(pt1, pt2); if (fRat > 0.5f) fRat = 0.5f; pt.setX((1.0f-fRat)*pt1.x() + fRat*pt2.x()); pt.setY((1.0f-fRat)*pt1.y() + fRat*pt2.y()); return pt; }

Meetod GetLineStart arvutab punkti asukoha P2 viimasest joonisest, kui punktid lisatakse hulknurgale päripäeva. Täpsemalt tagastab see punkti, mis on m_uiRadius pikslit i -st tipust kaugemale (i+1) -nda tipu suunas. (i+1) -Nda tipu juurde pääsemisel peame meeles pidama, et hulknurgas on ka viimase ja esimese tipu vahel sirgjoon, mis teeb sellest suletud kuju, seega avaldise (i+1)%count() . See takistab ka meetodil ulatusest välja minemist ja pöördub selle asemel esimese punkti poole. Muutuja fRat hoiab raadiuse ja i -nda rea ​​lõigu pikkuse suhet. Samuti on kontroll, mis takistab fRat väärtusest üle 0.5. Kui fRat väärtus oli üle 0.5, siis kattuksid kaks järjestikust ümardatud nurka, mis põhjustaks halva visuaalse tulemuse.

Punktist reisides Püks kuni P2 sirgjooneliselt ja läbides 30 protsenti distantsist, saame valemi abil määrata oma asukoha 0,7 • Püks+ 0,3 • P2 . Üldiselt, kui saavutame murdosa kogu distantsist, ja a = 1 tähistab täispikkust, praegune asukoht on (1 - α) • P1 + α • P2 .

Nii on GetLineStart meetod määrab punkti asukoha, mis on m_uiRadius pikslit i -nda tipu kaugusel (i+1) -th suunas.

QPointF RoundedPolygon::GetLineEnd(int i) const { QPointF pt; QPoint pt1 = at(i); QPoint pt2 = at((i+1) % count()); float fRat = m_uiRadius / GetDistance(pt1, pt2); if (fRat > 0.5f) fRat = 0.5f; pt.setX(fRat*pt1.x() + (1.0f - fRat)*pt2.x()); pt.setY(fRat*pt1.y() + (1.0f - fRat)*pt2.y()); return pt; }

See meetod on väga sarnane GetLineStart See arvutab punkti asukoha P0 (i+1) -nda tipu jaoks, mitte i -th. Teisisõnu, kui tõmbame joone GetLineStart(i) -st kuni GetLineEnd(i) iga i kohta vahel 0 ja n-1, kus n on hulknurga tippude arv, saaksime kustutatud tippudega hulknurga ja nende lähiümbruse.

Ja nüüd, põhiklassi meetod:

tundlik veebikujundusmeedia päring
const QPainterPath& RoundedPolygon::GetPath() { m_path = QPainterPath(); if (count() <3) { qWarning() << 'Polygon should have at least 3 points!'; return m_path; } QPointF pt1; QPointF pt2; for (int i = 0; i < count(); i++) { pt1 = GetLineStart(i); if (i == 0) m_path.moveTo(pt1); else m_path.quadTo(at(i), pt1); pt2 = GetLineEnd(i); m_path.lineTo(pt2); } // close the last corner pt1 = GetLineStart(0); m_path.quadTo(at(0), pt1); return m_path; }

Selle meetodi korral ehitame QPainterPath objekt. Kui hulknurgal pole vähemalt kolme tippu, ei ole meil enam tegemist 2D-kujuga ja antud juhul annab meetod hoiatuse ja tagastab tühja tee. Kui punkte on piisavalt, liigume läbi hulknurga kõik sirgjoonelõigud (joonelõikude arv on loomulikult võrdne tippude arvuga), arvutades iga sirgjoone alguse ja lõpu ümardatud vahel nurgad. Nende kahe punkti vahele panime sirgjoone ja eelmise joonelõigu lõpu ning voolu alguse vahele ruutu Bezieri kõvera, kasutades kontrollpunktina praeguse tipu asukohta. Pärast silmust peame tee sulgema Bezieri kõveraga viimase ja esimese rea segmentide vahel, sest silmusesse tõmbasime ühe sirge rohkem kui Bezieri kõverad.

Klass RoundedPolygon kasutamine ja tulemused

Nüüd on aeg vaadata, kuidas seda klassi praktikas kasutada.

QPixmap pix1(300, 200); QPixmap pix2(300, 200); pix1.fill(Qt::white); pix2.fill(Qt::white); QPainter P1(&pix1); QPainter P2(&pix2); P1.setRenderHints(QPainter::Antialiasing); P2.setRenderHints(QPainter::Antialiasing); P1.setPen(QPen(Qt::blue, 2)); P1.setBrush(Qt::red); P2.setPen(QPen(Qt::blue, 2)); P2.setBrush(Qt::red); RoundedPolygon poly; poly << QPoint(147, 187) << QPoint(95, 187) << QPoint(100, 175) << QPoint(145, 165) << QPoint(140, 95) << QPoint(5, 85) << QPoint(5, 70) << QPoint(140, 70) << QPoint(135, 45) << QPoint(138, 25) << QPoint(145, 5) << QPoint(155, 5) << QPoint(162, 25) << QPoint(165, 45) << QPoint(160, 70) << QPoint(295, 70) << QPoint(295, 85) << QPoint(160, 95) << QPoint(155, 165) << QPoint(200, 175) << QPoint(205, 187) << QPoint(153, 187) << QPoint(150, 199); P1.drawPolygon(poly); P2.drawPath(poly.GetPath()); pix1.save('1.png'); pix2.save('2.png');

See lähtekoodi osa on üsna sirgjooneline. Pärast kahe QPixmaps initsialiseerimist ja nende QPainters, loome RoundedPolygon objekt ja täitke see punktidega. Maalikunstnik P1 joonistab korrapärase hulknurga, samal ajal kui P2 joonistab QPainterPath ümarate nurkadega, mis on loodud hulknurgast. Mõlemad saadud pikslikud salvestatakse nende failidesse ja tulemused on järgmised:

Ümarad nurgad QPainteri abil

Järeldus

Oleme näinud, et ümarate nurkadega kuju genereerimine polügoonilt pole lõppude lõpuks nii keeruline, eriti kui kasutame head programmeerimisraamistikku, näiteks Qt. Seda protsessi saab automatiseerida klassiga, mida olen siin blogis kontseptsiooni tõestuseks kirjeldanud. Siiski on veel palju arenguruumi, näiteks:

  • Ümardatud nurki tehke ainult valitud tippudes ja mitte kõigis.
  • Tehke ümmargused erineva raadiusega tipud.
  • Rakendage meetod, mille abil luuakse ümarate nurkadega polüliin (Qyl terminoloogias olev polüliin on täpselt nagu hulknurk, välja arvatud see, et see ei ole suletud kuju, kuna sellel puudub viimase ja esimese tipu vaheline joon.
  • Kasutage RoundedPolygon bitikaartide genereerimiseks, mida saab kasutada taustavidina maskina pöörase kujuga vidinate tootmiseks.
  • RoundedPolygon klass pole rakendamise kiiruse jaoks optimeeritud; Jätsin selle mõiste lihtsamaks mõistmiseks nii, nagu see on. Optimeerimine võib hõlmata paljude vaheväärtuste arvutamist, kui polügoonile lisatakse uus tipp. Samuti, kui GetPath tagastab viite loodud QPainterPath -le, võib see määrata lipu, mis näitab, et objekt on ajakohane. Järgmine kõne GetPath tagastaks ainult sama QPainterPath objekti ümber arvutamata. Arendaja peaks siiski veenduma, et see lipp kustutatakse iga polügooni tipu iga muutuse korral ja ka iga uue tipu korral, mis paneb mind mõtlema, et optimeeritud klassi oleks parem arendada nullist ja seda ei tuletataks alates QPolygon. Hea uudis on see, et see pole nii keeruline kui tundub.

Kokku on RoundedPolygon klassi, nagu see on, saab kasutada tööriistana alati, kui soovime lisada a disaineri puudutus meie graafilise kasutajaliidese juurde lennult, ilma et oleks eelnevalt pixmapse või kujundeid ette valmistanud.

Seotud: C- ja C ++ -keelte õppimine: ülim nimekiri

Tooteanalüütik, kasvuturundus

Muu

Tooteanalüütik, kasvuturundus
Aktsiatest maksimumi võtmine - endise uurimisanalüütiku õppetunnid

Aktsiatest maksimumi võtmine - endise uurimisanalüütiku õppetunnid

Investorid Ja Rahastamine

Lemmik Postitused
Nurga vs. Reageerige: mis on veebiarenduse jaoks parim?
Nurga vs. Reageerige: mis on veebiarenduse jaoks parim?
Pood UX mobiilse kasutuskogemuse jaoks
Pood UX mobiilse kasutuskogemuse jaoks
Eliksiiri programmeerimiskeelega alustamine
Eliksiiri programmeerimiskeelega alustamine
Krüptoraha mannekeenidele: Bitcoin ja kaugemalgi
Krüptoraha mannekeenidele: Bitcoin ja kaugemalgi
Andmebaaside ränne: Röövikute muutmine liblikateks
Andmebaaside ränne: Röövikute muutmine liblikateks
 
RxSwift ja animatsioonid iOS-is
RxSwift ja animatsioonid iOS-is
Tarkvara kulude hindamine agiilses projektijuhtimises
Tarkvara kulude hindamine agiilses projektijuhtimises
Disainmõtlemise väärtus ettevõtluses
Disainmõtlemise väärtus ettevõtluses
Xamarin Forms, MVVMCross ja SkiaSharp: platvormidevaheliste rakenduste arendamise püha kolmainsus
Xamarin Forms, MVVMCross ja SkiaSharp: platvormidevaheliste rakenduste arendamise püha kolmainsus
API-d sotsiaalsetes võrgustikes: Interneti-portaal reaalsesse maailma
API-d sotsiaalsetes võrgustikes: Interneti-portaal reaalsesse maailma
Lemmik Postitused
  • kogemust on võimatu mõõta, sest see on tunne.
  • kuidas kodeerida c ++
  • on llc s või c ettevõte
  • Warren Buffetti artiklid investeerimise kohta
  • ostja ja tarnija jõud
  • palju ja targa kodu tehnikat
Kategooriad
Tulud Ja Kasv Tehnoloogia Kpi-D Ja Analytics Ux Disain Vilgas Tooteinimesed Ja Meeskonnad Planeerimine Ja Prognoosimine Kujundusprotsess Muu Brändikujundus

© 2021 | Kõik Õigused Kaitstud

apeescape2.com