Bezier-curves: Interactieve gids voor kwadratische en kubische curves


Bezier-curves zijn een van de meest gebruikte tools om vloeiende paden te tekenen in computergraphics, UI-animatie, vectorillustratie en lettertype-rendering. Zelfs wanneer een curve met de hand getekend lijkt, representeren veel systemen die met een kleine set controlepunten en een deterministische vergelijking. Dat maakt Bezier-curves zowel expressief als betrouwbaar: ontwerpers en engineers kunnen beweging en geometrie vormgeven met slechts een paar waarden.

Dit artikel bouwt vanaf de basis een praktisch begrip op. Je start met het kwadratische geval, bekijkt daarna hoe een enkel punt op de curve daadwerkelijk wordt berekend, en gaat vervolgens door naar kubische curves, de vorm die de meeste designtools aanbieden.

Basisprincipes van Bezier-curves

Een Bezier-curve wordt gedefinieerd door controlepunten. De curve begint bij het eerste controlepunt en eindigt bij het laatste controlepunt. De punten ertussen liggen meestal niet op de curve. In plaats daarvan sturen ze de richting en de mate van kromming.

Voor een kwadratische Bezier-curve zijn er drie punten:

  • P0P_0: start point
  • P1P_1: control point
  • P2P_2: end point

De formule gebruikt een parameter tt van 00 tot 11:

B(t)=(1t)2P0+2(1t)tP1+t2P2B(t) = (1 - t)^2 P_0 + 2(1 - t)t P_1 + t^2 P_2

Je kunt dit lezen als een gewogen combinatie van punten. Bij t=0t = 0 ligt al het gewicht op P0P_0, dus ligt het curvepunt aan het begin. Bij t=1t = 1 ligt al het gewicht op P2P_2, dus ligt het curvepunt aan het einde. Daartussen verschuift het gewicht vloeiend en ontstaat een continu pad.

Het kernidee is dat de vergelijking vloeiendheid garandeert door de constructie zelf. Je tekent niet handmatig elk tussenpunt. Je samplet tt meerdere keren, berekent B(t)B(t) en verbindt die posities.

Kwadratische vorm verkennen

Gebruik deze eerste visualisatie om intuïtie op te bouwen voor hoe het controlepunt de vorm van de curve verandert. Verplaats de sliders van de controlepunten en kijk hoe zowel het controlepolygoon als de uiteindelijke curve wordt bijgewerkt.

P(t)=(1t)2P0+2(1t)tP1+t2P2P(t) = (1 - t)^2 P_0 + 2(1 - t)t P_1 + t^2 P_2 , P1 = (320, 60)

Let tijdens het experimenteren op deze observaties:

  1. De curve begint altijd bij P0P_0 en eindigt bij P2P_2.
  2. Het verplaatsen van P1P_1 verandert de richting bij beide uiteinden, omdat het de raaklijnrichting beïnvloedt.
  3. Als je P1P_1 verder weg trekt, neemt de kromming toe en kan het pad sterk bogen.
  4. Als je P1P_1 dichter bij het segment van P0P_0 naar P2P_2 brengt, wordt de curve vlakker.

Een veelgemaakte beginnersfout is aannemen dat de curve door P1P_1 moet lopen. Voor een kwadratische curve is P1P_1 meestal een aantrekpunt, geen punt op het pad. Precies daarom zijn Bezier-curves zo bruikbaar: je stuurt de vorm indirect en behoudt vloeiendheid.

De Casteljau-constructie

De vergelijking is compact, maar er is een andere manier om over Bezier-curves te denken die in code vaak makkelijker te vertrouwen is: het algoritme van De Casteljau. Daarmee bereken je een punt op de curve via herhaalde lineaire interpolatie.

Voor het kwadratische geval bij een gekozen tt:

  1. Interpoleer tussen P0P_0 en P1P_1 om Q0Q_0 te krijgen.
  2. Interpoleer tussen P1P_1 en P2P_2 om Q1Q_1 te krijgen.
  3. Interpoleer tussen Q0Q_0 en Q1Q_1 om B(t)B(t) te krijgen.

Dat laatste punt geeft hetzelfde resultaat als de kwadratische formule. Het voordeel is dat deze interpolatieprocedure op natuurlijke wijze uitbreidt naar curves van hogere graad en in veel implementaties numeriek stabiel is.

t=t, Q0, Q1, B(t)t = t,\ Q_0,\ Q_1,\ B(t) | t = 0.35 | Q0 = (160.5, 213.0) | Q1 = (397.5, 150.5) | B(t) = (243.5, 191.1)

Probeer de tt-slider langzaam van 00 naar 11 te bewegen. Je ziet Q0Q_0 en Q1Q_1 langs hun lijnsegmenten bewegen, terwijl B(t)B(t) de blauwe curve volgt. Dat geeft direct een geometrische reden waarom de curve binnen de convexe regio blijft die door de controlepunten wordt gevormd.

De Casteljau is ook nuttig om een curve bij elke willekeurige tt op te splitsen in twee kleinere Bezier-curves. Die bewerking wordt veel gebruikt in renderingpipelines, adaptieve tessellatie en hit-testing.

Raaklijnen en bewegingsrichting

Bezier-curves worden vaak gebruikt voor bewegingspaden, niet alleen voor statische tekeningen. In animatie is de lokale raaklijnrichting belangrijk omdat die aangeeft waar een object op dat moment naartoe beweegt.

For a quadratic curve, the derivative is:

B(t)=2(1t)(P1P0)+2t(P2P1)B'(t) = 2(1 - t)(P_1 - P_0) + 2t(P_2 - P_1)

Hieruit volgen twee praktische feiten:

  • Bij het begin (t=0t = 0) komt de richting overeen met P1P0P_1 - P_0.
  • Bij het einde (t=1t = 1) komt de richting overeen met P2P1P_2 - P_1.

Daarom verandert het verplaatsen van het middelste controlepunt hoe de curve vertrekt en aankomt bij de eindpunten. In UI-animatietools zie je ditzelfde concept terug als richtingshandles.

Wanneer beweging natuurlijk moet aanvoelen, is alleen de padgeometrie niet genoeg. Je hebt ook een timingfunctie nodig voor hoe tt in de tijd verandert. Een pad kan vloeiend zijn terwijl de snelheid toch abrupt voelt als de parameterprogressie niet wordt geëased.

Kubische Bezier-curves

De meeste design- en webtools geven de voorkeur aan kubische Bezier-curves. Een kubische curve heeft vier controlepunten:

  • P0P_0: start
  • P1P_1: eerste handle
  • P2P_2: tweede handle
  • P3P_3: einde

De vergelijking is:

B(t)=(1t)3P0+3(1t)2tP1+3(1t)t2P2+t3P3B(t) = (1 - t)^3 P_0 + 3(1 - t)^2 t P_1 + 3(1 - t)t^2 P_2 + t^3 P_3

Vergeleken met kwadratisch voegt kubisch nog een handle toe en veel meer vormcontrole. Je kunt S-curves, vloeiende overgangen of scherpe bochten maken zonder te vroeg meerdere segmenten aan elkaar te ketenen.

t=t, B(t), P1, P2t = t,\ B(t),\ P_1,\ P_2 | t = 0.50 | B(t) = (351.3, 180.0) | P1 = (220, 80) | P2 = (470, 280)

Gebruik deze werkbank om te onderzoeken hoe elke handle bijdraagt:

  1. Verplaats P1P_1 terwijl je P2P_2 vast laat staan. Het vertrek van de curve bij het begin verandert het meest.
  2. Verplaats P2P_2 terwijl je P1P_1 vast laat staan. De aankomst van de curve bij het einde verandert het meest.
  3. Verplaats beide handles naar tegenoverliggende kanten en zie hoe S-vormige paden ontstaan.
  4. Beweeg de Sample t-slider en volg hoe het gemarkeerde punt langs de curve beweegt.

Dit lokale handle-gedrag is de reden dat vectoreditors raaklijnhandles bij ankerpunten tonen. Elk segment kan worden afgesteld zonder het volledige pad handmatig opnieuw te tekenen.

Stukgewijze Bezier-paden en continuiteit

Echte tekeningen bestaan meestal niet uit één enkele curve. Het zijn ketens van Bezier-segmenten. Bij het verbinden van segmenten is continuiteit de belangrijkste kwaliteitsfactor.

Drie nuttige niveaus van continuiteit:

  • C0C_0-continuiteit: segmenten komen samen in hetzelfde punt.
  • C1C_1-continuiteit: eerste afgeleiden komen overeen, dus de richting is continu.
  • C2C_2-continuiteit: tweede afgeleiden komen overeen, dus de kromming verandert vloeiend.

In veel UI- en icoonworkflows is C1C_1 de praktische basis. Als aangrenzende handles collineair en in balans rond een gedeeld ankerpunt staan, zien overgangen er visueel vloeiend uit. Voor oppervlakken met hoge precisie en simulatiepaden kunnen strengere continuiteitsvoorwaarden belangrijk zijn.

Veelvoorkomende implementatiepatronen

Als je Bezier-evaluatie in code implementeert, zijn deze patronen gebruikelijk:

  1. Sampelen op vaste t-stappen voor eenvoudige tekeningen of previews.
  2. Adaptieve onderverdeling gebruiken wanneer hoge kromming dichter samplen vereist.
  3. De Casteljau-splitsing gebruiken voor robuuste recursie en curve clipping.
  4. Gesamplede polylijnen cachen voor snelle hittests en benaderde lengte.

Een subtiel punt is dat gelijke stappen in t geen gelijke afstanden in de ruimte zijn. Als beweging met constante snelheid nodig is, heb je meestal booglengtebenadering en remapping nodig. Voor veel UI-animaties is die benadering voldoende en goedkoper dan exacte symbolische oplossingen.

Typische toepassingen

Bezier-curves komen in veel systemen voor, vaak achter gebruiksvriendelijke editors:

  • SVG-path-commando’s in webgraphics
  • Glyphcontouren van lettertypes in tekstrendering
  • Camerarails en objecttrajecten in 3D-tools
  • Easing-curves voor CSS en animatietimelines (meestal 1D kubische vormen)
  • Tools voor vorminterpolatie in illustratiesoftware

Hoewel de interfaces verschillen, blijft het onderliggende concept hetzelfde: controlepunten definiëren vloeiende trajecten met voorspelbaar gedrag bij de eindpunten.

Praktische mentale checklist

Wanneer een curve er niet goed uitziet, helpt deze checklist om snel te debuggen:

  1. Controleer eerst de posities van de eindpunten.
  2. Inspecteer de handlerichtingen bij elk eindpunt.
  3. Controleer handlelengtes op overmatige buiging.
  4. Verifieer segmentcontinuiteit op aansluitingen.
  5. Scheid problemen met padvorm van timing/easing-problemen.

Zo voorkom je dat geometriebeslissingen en timingbeslissingen door elkaar lopen. De meeste visuele glitches komen uit een van die categorieën, en de oplossing hangt af van het correct identificeren van de oorzaak.

Bezier-curves zijn populair omdat ze expressieve vormen comprimeren tot een kleine, bewerkbare set parameters. Zodra je de invloed van controlepunten, De Casteljau-interpolatie en continuiteit tussen segmenten begrijpt, worden ze een betrouwbaar instrument in plaats van iets mysterieus.