Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Ve kreslení s Direct2D jsme viděli, že Metoda ID2D1RenderTarget::FillEllipse nakreslí elipsu, která je zarovnaná k osám x a y. Ale řekněme, že chcete nakreslit elipsu nakloněnou pod úhlem?
Pomocí transformací můžete tvar změnit následujícími způsoby.
- Otočení kolem bodu.
- Škálování.
- Překlad (posun ve směru X nebo Y)
- Nerovnoměrná distribuce (označovaná také jako shear).
Transformace je matematická operace, která zobrazí množinu bodů na novou množinu bodů. Například následující diagram znázorňuje trojúhelník otočený kolem bodu P3. Po použití otočení se bod P1 mapuje na P1', bod P2 se mapuje na P2' a bod P3 se mapuje na sebe.
Transformace se implementují pomocí matic. Nemusíte ale rozumět matematikě matic, abyste je mohli použít. Další informace o matematických operacích najdete v dodatku: Transformace matice.
Chcete-li použít transformaci v Direct2D, zavolejte metodu ID2D1RenderTarget::SetTransform. Tato metoda přebírá D2D1_MATRIX_3X2_F strukturu, která definuje transformaci. Tuto strukturu můžete inicializovat voláním metod ve třídě D2D1::Matrix3x2F . Tato třída obsahuje statické metody, které vracejí matici pro každý druh transformace:
Například následující kód použije otočení o 20 stupňů kolem bodu (100, 100).
pRenderTarget->SetTransform(
D2D1::Matrix3x2F::Rotation(20, D2D1::Point2F(100,100)));
Transformace se použije u všech pozdějších operací kreslení, dokud znovu nevoláte SetTransform . Chcete-li odebrat aktuální transformaci, zavolejte SetTransform s maticí identity. Pokud chcete vytvořit matici identity, zavolejte funkci Matrix3x2F::Identity .
pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
Kreslení ručiček hodin
Pojďme využít transformace a převést náš program Circle na analogové hodiny. Můžeme to udělat přidáním řádků pro ruce.
Místo výpočtu souřadnic pro čáry můžeme vypočítat úhel a pak použít transformaci otočení. Následující kód ukazuje funkci, která nakreslí jednu hodinovou ruku. Parametr fAngle dává úhel ruky ve stupních.
void Scene::DrawClockHand(float fHandLength, float fAngle, float fStrokeWidth)
{
m_pRenderTarget->SetTransform(
D2D1::Matrix3x2F::Rotation(fAngle, m_ellipse.point)
);
// endPoint defines one end of the hand.
D2D_POINT_2F endPoint = D2D1::Point2F(
m_ellipse.point.x,
m_ellipse.point.y - (m_ellipse.radiusY * fHandLength)
);
// Draw a line from the center of the ellipse to endPoint.
m_pRenderTarget->DrawLine(
m_ellipse.point, endPoint, m_pStroke, fStrokeWidth);
}
Tento kód nakreslí svislou čáru, počínaje středem ciferníku a končící v místě koncového bodu. Čára se otočí kolem středu elipsy použitím rotace transformace. Středem otáčení je střed elipsy, který tvoří ciferník.
Následující kód ukazuje, jak se vykresluje celý hodinový ciferník.
void Scene::RenderScene()
{
m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::SkyBlue));
m_pRenderTarget->FillEllipse(m_ellipse, m_pFill);
m_pRenderTarget->DrawEllipse(m_ellipse, m_pStroke);
// Draw hands
SYSTEMTIME time;
GetLocalTime(&time);
// 60 minutes = 30 degrees, 1 minute = 0.5 degree
const float fHourAngle = (360.0f / 12) * (time.wHour) + (time.wMinute * 0.5f);
const float fMinuteAngle =(360.0f / 60) * (time.wMinute);
DrawClockHand(0.6f, fHourAngle, 6);
DrawClockHand(0.85f, fMinuteAngle, 4);
// Restore the identity transformation.
m_pRenderTarget->SetTransform( D2D1::Matrix3x2F::Identity() );
}
Kompletní projekt sady Visual Studio si můžete stáhnout z ukázky hodin Direct2D. (Jen pro zábavu, stažená verze přidá paprskový přechod na ciferník.)
Kombinování transformací
Čtyři základní transformace lze kombinovat vynásobením dvou nebo více matic. Například následující kód kombinuje otočení s překladem.
const D2D1::Matrix3x2F rot = D2D1::Matrix3x2F::Rotation(20);
const D2D1::Matrix3x2F trans = D2D1::Matrix3x2F::Translation(40, 10);
pRenderTarget->SetTransform(rot * trans);
Třída Matrix3x2F poskytuje operátor*() pro násobení matice. Pořadí, ve kterém násobíte matice, je důležité. Nastavení transformace (M × N) znamená "Použít M jako první, následované N". Tady je například rotace následovaná překladem:
Tady je kód pro tuto transformaci:
const D2D1::Matrix3x2F rot = D2D1::Matrix3x2F::Rotation(45, center);
const D2D1::Matrix3x2F trans = D2D1::Matrix3x2F::Translation(x, 0);
pRenderTarget->SetTransform(rot * trans);
Teď porovnejte tuto transformaci s transformací v obráceném pořadí, kdy je nejdříve překládána a následně otáčena.
Otočení se provádí kolem středu původního obdélníku. Tady je kód této transformace.
D2D1::Matrix3x2F rot = D2D1::Matrix3x2F::Rotation(45, center);
D2D1::Matrix3x2F trans = D2D1::Matrix3x2F::Translation(x, 0);
pRenderTarget->SetTransform(trans * rot);
Jak vidíte, matice jsou stejné, ale pořadí operací se změnilo. K tomu dochází, protože násobení matice není komutativní: M × N ≠ N × M.