Přizpůsobení tvarů prezentací v C++
Přehled
Tento článek vysvětluje, jak přizpůsobit tvary prezentací v Aspose.Slides úpravou geometrie tvaru pomocí editačních bodů a geometrických cest. Ukazuje, jak pracovat s GeometryPath a IGeometryPath k úpravě existujících tvarů, provádění základních operací úpravy cesty, přidávání nebo odstraňování bodů a aplikaci aktualizované geometrie zpět na tvar.
Také demonstruje, jak vytvořit vlastní a složené tvary, sestavit tvary s zakřivenými rohy a určit, zda je geometrie tvaru uzavřená.
Změna tvaru pomocí editačních bodů
V PowerPointu můžete použít Edit Points k úpravě čtverce:
- Posunout roh dovnitř nebo ven.
- Upravit zakřivení v bodě.
- Přidat nové body.
Úprava bodů vám umožní měnit obrys tvaru nebo použít existující tvar jako základ pro nový.
Tipy pro úpravu tvarů

Při úpravě tvarů v PowerPointu mějte na paměti následující pojmy:
- Tvar (nebo jeho cesta) může být buď uzavřený, nebo otevřený.
- Cesta tvaru se skládá z kotevních bodů spojených segmenty.
- Segment může být přímý nebo zakřivený. Kotevní body a ovládací úchyty určují jeho tvar.
- Kotevní body existují jako rohové body, přímé body nebo hladké body:
- V rohovém bodě se sousední segmenty mohou setkat pod úhlem.
- V hladkém bodě jsou oba ovládací úchyty zarovnané a stejně vzdálené od kotevního bodu.
- V přímém bodě jsou oba ovládací úchyty zarovnané, ale mohou mít různou vzdálenost od kotevního bodu.
- Posun kotevních bodů nebo úprava jejich úchytů mění obrys tvaru.
Pro úpravu tvarů PowerPointu pomocí editačních bodů poskytuje Aspose.Slides třídu GeometryPath a rozhraní IGeometryPath.
- Instance GeometryPath představuje geometrickou cestu objektu IGeometryShape.
- Pro získání GeometryPath z instance IGeometryShape můžete použít metodu IGeometryShape::GetGeometryPaths.
- Pro nastavení GeometryPath pro tvar můžete použít tyto metody: IGeometryShape::SetGeometryPath pro tvary s jednou cestou a IGeometryShape::SetGeometryPaths pro tvary s více cestami.
- Pro přidání segmentů můžete použít metody pod IGeometryPath.
- Pomocí metod IGeometryPath::set_Stroke a IGeometryPath::set_FillMode můžete nastavit vzhled geometrické cesty.
- Pomocí metody IGeometryPath::get_PathData můžete získat geometrickou cestu GeometryShape jako pole segmentů cesty.
Jednoduché operace úpravy
Použijte následující metody k úpravě geometrické cesty. Přetížení, která přijímají index, vloží segment na tuto nulovou pozici v poli segmentů cesty.
| Operace | Metoda |
|---|---|
| Přidat nebo vložit přímou čáru. | GeometryPath::LineTo |
| Přidat nebo vložit kubické Bézierovo zakřivení se dvěma ovládacími body a koncovým bodem. | GeometryPath::CubicBezierTo |
| Přidat nebo vložit kvadratické Bézierovo zakřivení s jedním ovládacím bodem a koncovým bodem. | GeometryPath::QuadraticBezierTo |
| Přidat eliptický oblouk se zadanými rozměry a úhly ve stupních. | GeometryPath::ArcTo |
| Uzavřít aktuální figuru propojením jejího koncového bodu s počátečním bodem. | GeometryPath::CloseFigure |
| Nastavit počáteční bod figury. | GeometryPath::MoveTo |
| Odstranit segment na nulovém indexu. | GeometryPath::RemoveAt |
Přidání vlastních bodů do tvaru
Tento příklad vloží dva body do obdélníkového tvaru pomocí GeometryPath::LineTo a použije upravenou cestu pomocí IGeometryShape::SetGeometryPath. Souřadnice jsou lokální k tvaru: oba nové body jsou ve středu, 100 bodů od levého okraje a 50 bodů od horního okraje. Indexy segmentů 1 a 4 je umístí na horní a dolní hranu a stáhnou tyto hrany dovnitř.
#include <DOM/IAutoShape.h>
#include <DOM/IGeometryPath.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 100.0f, 100.0f, 200.0f, 100.0f);
auto geometryPath = shape->GetGeometryPaths()->idx_get(0);
geometryPath->LineTo(100.0f, 50.0f, 1);
geometryPath->LineTo(100.0f, 50.0f, 4);
shape->SetGeometryPath(geometryPath);

Odstranění bodů z tvaru
Tento příklad mění obrys ve tvaru srdce odstraněním segmentu na nulovém indexu 2 pomocí GeometryPath::RemoveAt. Použití upravené cesty pomocí IGeometryShape::SetGeometryPath aktualizuje konturu tvaru.
#include <DOM/IAutoShape.h>
#include <DOM/IGeometryPath.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Heart, 100.0f, 100.0f, 300.0f, 300.0f);
auto path = shape->GetGeometryPaths()->idx_get(0);
path->RemoveAt(2);
shape->SetGeometryPath(path);

Vytvoření vlastního tvaru
Tento příklad vytvoří pětihrotou hvězdu pomocí GeometryPath. Střídavé vnější a vnitřní poloměry 100 a 50 bodů definují špičky a zapouzdření; krok 72 stupňů rovnoměrně rozmístí pět špiček. Cesta je uzavřena pomocí GeometryPath::CloseFigure a aplikována na obdélníkový tvar pomocí IGeometryShape::SetGeometryPath, čímž nahradí jeho obrys.
#include <DOM/GeometryPath.h>
#include <DOM/IAutoShape.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <drawing/point_f.h>
#include <system/collections/list.h>
#include <system/math.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Drawing;
auto points = System::MakeObject<List<PointF>>();
auto outerRadius = 100.0f;
auto innerRadius = 50.0f;
auto angleStep = 72;
for (auto angle = -90; angle < 270; angle += angleStep)
{
auto radians = angle * (Math::PI / 180.f);
auto x = outerRadius * Math::Cos(radians);
auto y = outerRadius * Math::Sin(radians);
points->Add(PointF((float)x + outerRadius, (float)y + outerRadius));
radians = Math::PI * (angle + angleStep / 2) / 180.0;
x = innerRadius * Math::Cos(radians);
y = innerRadius * Math::Sin(radians);
points->Add(PointF((float)x + outerRadius, (float)y + outerRadius));
}
auto starPath = System::MakeObject<GeometryPath>();
starPath->MoveTo(points->idx_get(0));
for (auto i = 1; i < points->get_Count(); i++)
{
starPath->LineTo(points->idx_get(i));
}
starPath->CloseFigure();
auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 100.0f, 100.0f, outerRadius * 2, outerRadius * 2);
shape->SetGeometryPath(starPath);

Vytvoření složeného vlastního tvaru
Tento příklad definuje dva uzavřené objekty GeometryPath pro horní a dolní třetinu tvaru. Použití obou cest pomocí IGeometryShape::SetGeometryPaths vytvoří jediný složený tvar s prohlášením uprostřed jeho střední třetiny.
#include <DOM/GeometryPath.h>
#include <DOM/IAutoShape.h>
#include <DOM/IGeometryPath.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 100.0f, 100.0f, 200.0f, 100.0f);
auto topPath = System::MakeObject<GeometryPath>();
topPath->MoveTo(0.0f, 0.0f);
topPath->LineTo(shape->get_Width(), 0.0f);
topPath->LineTo(shape->get_Width(), shape->get_Height() / 3);
topPath->LineTo(0.0f, shape->get_Height() / 3);
topPath->CloseFigure();
auto bottomPath = System::MakeObject<GeometryPath>();
bottomPath->MoveTo(shape->get_Height() / 3 * 2, 0.0f);
bottomPath->LineTo(shape->get_Width(), shape->get_Height() / 3 * 2);
bottomPath->LineTo(shape->get_Width(), shape->get_Height());
bottomPath->LineTo(0.0f, shape->get_Height());
bottomPath->CloseFigure();
auto paths = System::MakeArray<SharedPtr<IGeometryPath>>({ topPath, bottomPath });
shape->SetGeometryPaths(paths);

Vytvoření vlastního tvaru se zakřivenými rohy
Tento příklad kombinuje přímé segmenty s GeometryPath::ArcTo k vytvoření tvaru se zakřivenými rohy dovnitř. Každá velikost rohu nastavuje šířku a výšku oblouku v bodech a natočení -90 stupňů kreslí proti směru hodinových ručiček čtvrtkruh elipsy. Dokončená cesta je aplikována pomocí IGeometryShape::SetGeometryPath a prezentace je uložena ve formátu PPTX.
#include <DOM/GeometryPath.h>
#include <DOM/IAutoShape.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <Export/SaveFormat.h>
#include <drawing/point_f.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System::Drawing;
auto shapeX = 20.f;
auto shapeY = 20.f;
auto shapeWidth = 300.f;
auto shapeHeight = 200.f;
auto leftTopSize = 50.f;
auto rightTopSize = 20.f;
auto rightBottomSize = 40.f;
auto leftBottomSize = 10.f;
auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Custom, shapeX, shapeY, shapeWidth, shapeHeight);
auto topLeft = PointF(leftTopSize, 0.0f);
auto topRight = PointF(shapeWidth - rightTopSize, 0.0f);
auto rightBottom = PointF(shapeWidth, shapeHeight - rightBottomSize);
auto bottomLeft = PointF(leftBottomSize, shapeHeight);
auto leftTop = PointF(0.0f, leftTopSize);
auto geometryPath = System::MakeObject<GeometryPath>();
geometryPath->MoveTo(topLeft);
geometryPath->LineTo(topRight);
geometryPath->ArcTo(rightTopSize, rightTopSize, 180.0f, -90.0f);
geometryPath->LineTo(rightBottom);
geometryPath->ArcTo(rightBottomSize, rightBottomSize, -90.0f, -90.0f);
geometryPath->LineTo(bottomLeft);
geometryPath->ArcTo(leftBottomSize, leftBottomSize, 0.0f, -90.0f);
geometryPath->LineTo(leftTop);
geometryPath->ArcTo(leftTopSize, leftTopSize, 90.0f, -90.0f);
geometryPath->CloseFigure();
shape->SetGeometryPath(geometryPath);
presentation->Save(u"output.pptx", SaveFormat::Pptx);
Zjištění, zda je geometrie tvaru uzavřená
Následující pomocná funkce kontroluje, zda každý neprázdný geometrický cest končí uzavíracím segmentem. Čte IGeometryPath::get_PathData a porovnává poslední segmentů IPathSegment::get_PathCommand s PathCommandType::Close. Vrací false, když neexistují neprázdné cesty. Tato kontrola zkoumá poslední příkaz každé cesty; neprohledává každou podfiguru uvnitř cesty. Příklad vypisuje True pro obdélník.
#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IAutoShape.h>
#include <DOM/IGeometryShape.h>
#include <DOM/IGeometryPath.h>
#include <DOM/ShapeType.h>
#include <system/array.h>
#include <system/smart_ptr.h>
#include <system/console.h>
#include <DOM/IPathSegment.h>
#include <DOM/PathCommandType.h>
using namespace Aspose::Slides;
using namespace System;
auto isGeometryClosed = [](SharedPtr<IGeometryShape> geometryShape)
{
auto hasNonemptyPath = false;
for (auto&& geometryPath : geometryShape->GetGeometryPaths())
{
auto segments = geometryPath->get_PathData();
if (segments->get_Length() == 0)
{
continue;
}
hasNonemptyPath = true;
auto lastSegment = segments->idx_get(segments->get_Length() - 1);
if (lastSegment->get_PathCommand() != PathCommandType::Close)
{
return false;
}
}
return hasNonemptyPath;
};
auto presentation = MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 100, 100, 200, 100);
Console::WriteLine(isGeometryClosed(shape));
Extrahování a inspekce prvků tvaru
Použijte IGeometryShape::CreateShapeElements k inspekci existujícího tvaru jako prvků obsahujících body cesty a typy bodů. Přetypujte každý vrácený IShapeElement na ShapeElement a přečtěte pole vrácená metodami get_PathPoints a get_PathTypes. Toto znázornění je užitečné pro analýzu obrysu nebo předání geometrie nástrojům pro vlastní kreslení.
Příklad otevře prezentaci, najde první geometrický tvar přímo na první snímku a vypíše jeho segmenty cesty. Použijte prezentaci obsahující tvar s přímými i zakřivenými segmenty, abyste viděli oba typy výstupu. Nepřechází do skupin.
#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IAutoShape.h>
#include <DOM/IGeometryShape.h>
#include <DOM/IGeometryPath.h>
#include <DOM/ShapeType.h>
#include <system/array.h>
#include <system/smart_ptr.h>
#include <system/console.h>
#include <DOM/IShapeElement.h>
#include <DOM/ShapeElement.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = MakeObject<Presentation>(u"input.pptx");
auto slide = presentation->get_Slide(0);
SharedPtr<IGeometryShape> shape;
for (auto&& candidate : slide->get_Shapes())
{
shape = AsCast<IGeometryShape>(candidate);
if (shape != nullptr)
{
break;
}
}
if (shape == nullptr)
{
Console::WriteLine(u"No geometry shape found on the first slide.");
return;
}
for (auto&& element : shape->CreateShapeElements())
{
auto shapeElement = ExplicitCast<ShapeElement>(element);
auto points = shapeElement->get_PathPoints();
auto types = shapeElement->get_PathTypes();
Console::WriteLine(u"Shape element:");
for (auto i = 0; i < points->get_Length(); i++)
{
auto pointType = types[i] & 0x07; // Uchovat typ segmentu, vyjma příznaků.
switch (pointType)
{
case 0:
Console::WriteLine(u"Start figure at {0}", points[i]);
break;
case 1:
Console::WriteLine(u"Line to {0}", points[i]);
break;
case 3:
Console::WriteLine(u"Cubic Bezier: controls {0}, {1}; end {2}", points[i], points[i + 1], points[i + 2]);
i += 2; // Consume both control points and the endpoint.
break;
}
if ((types[i] & 0x80) != 0)
{
Console::WriteLine(u"Close subpath back to its starting point.");
}
}
}
Pole jsou podle indexu spárována: points[i] je bod a types[i] popisuje jeho roli. Typ 0 začíná figuru a typ 1 kreslí úsečku od předchozího bodu k aktuálnímu bodu. Kubický Bézierův segment začíná předchozím koncovým bodem a používá tři po sobě jdoucí položky typu 3: dva ovládací body a nový koncový bod. Smyčka konzumuje těchto tři položky najednou a kontroluje koncový bod pro uzavření.
Typy bodů také obsahují příznaky. Maskujte 0x07 pro určení typu segmentu a testujte 0x80 samostatně pro detekci uzavřené podcesty. Například 129 (0x81) znamená koncový bod úsečky, který uzavře podcestu, a 131 (0x83) znamená Bézierův koncový bod, který uzavře podcestu. Pouze porovnání surové hodnoty s 1 nebo 3 by tyto případy minulo. Další příznaky, jako pomlčka (0x10) a značka (0x20), nemění základní typ segmentu.
Souřadnice a transformace. Body jsou měřeny v bodech (1/72 palce), přičemž X roste doprava a Y dolů. Pro neztvořený tvar již extrahované souřadnice zahrnují pozici vrácenou metodami get_X a get_Y a odrážejí jeho aktuální šířku a výšku. Například neotočený obdélník v (100, 200) se šířkou 120 × 80 má obrysové limity (100, 200)–(220, 280). Nepřidávejte pozici tvaru znovu. Odečtěte jeho X a Y pro získání souřadnic relativních k jeho neotočenému rámci.
Extrahované body neaplikují rotaci nastavenou pomocí set_Rotation ani horizontální a vertikální převrácení. Pro reprodukci zobrazeného obrysu aplikujte tyto transformace kolem středu tvaru. Pro seskupené tvary také zohledněte mapování souřadnic skupiny a transformace; nepředpokládejte, že extrahované body jsou konečné vykreslené souřadnice snímku, ani neaplikujte posun nebo měřítko dvakrát, pokud už jsou zahrnuty ve rámci potomka.
Inspekce versus úprava. Extrahovaná pole popisují obrys; jejich změna neaktualizuje původní tvar. Zvolte tento přístup, když vaše analytické nebo kreslicí kódy vyžadují pole bodů/typů. Použijte GetGeometryPaths když potřebujete geometrické příkazy v lokálním souřadnicovém systému tvaru nebo chcete upravit jeho geometriku. Použijte upravené cesty prostřednictvím SetGeometryPath nebo SetGeometryPaths.
Převod GeometryPath na GraphicsPath
Veřejné API Aspose.Slides pro C++ aktuálně neumožňuje převody mezi geometrickými cestami a grafickými cestami. K inspekci obrysu použijte prvky tvaru, jak je popsáno výše. K úpravě tvaru použijte geometrické cesty a aplikujte aktualizované cesty na tvar.
Často kladené otázky
Co se stane s výplní a obrysem po nahrazení geometrie?
Styl zůstává u tvaru; mění se pouze obrys. Výplň a obrys jsou automaticky aplikovány na novou geometrii.
Jak správně otočit vlastní tvar spolu s jeho geometrií?
Použijte metodu set_Rotation tvaru; geometrie se otáčí spolu s tvarem, protože je svázána s lokálním souřadnicovým systémem tvaru.
Mohu převést vlastní tvar na obrázek, abych „uzamkl“ výsledek?
Ano. Exportujte požadovanou slide nebo samotný shape do rastrového formátu; to zjednoduší další práci s komplikovanými geometriemi.