Desenarea graficelor vectoriale pe o pagină PDF
Desenarea graficelor vectoriale pe o pagină PDF
Aspose.PDF FOSS pentru C++ include un mic API de grafică vectorială pentru desenarea formelor direct pe o pagină PDF în timpul construcției unui document. Punctul de intrare este Graph, un container amplasat pe pagină care deține o colecție de obiecte Shape; trei forme concrete — Circle, Ellipse și Line — derivă din Shape și fiecare își exprimă geometria în mod diferit. Stilizarea conturului și umplerii per-formă provine din GraphInfo, iar containerul Graph însuși conține un BorderInfo pentru încadrament. Aceasta nu are legătură cu rasterizarea paginii (BmpDevice, JpegDevice, TiffDevice), care convertește conținutul existent al paginii în formate de imagini raster în loc să deseneze geometrie nouă.
Containerul grafic și adăugarea formelor într-o pagină
Graph își stabilește poziția și dimensiunile în pagină prin Left(), Top(), Width() și Height(), iar indicatorul său IsChangePosition() controlează dacă acea poziție poate fi mutată în raport cu alte conținuturi de pe pagină. Formele pe care le desenează sunt stocate în vectorul returnat de Shapes() — std::vector<std::unique_ptr<Shape>> — care se populează prin construirea unei forme, configurarea acesteia și mutarea ei în acel vector. După ce este creat, Graph este inserat în pagină prin Page.Paragraphs().Add(), aceeași colecție utilizată pentru alte elemente la nivel de pagină.
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/drawing/graph.hpp>
#include <aspose/pdf/drawing/circle.hpp>
using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Drawing;
Document doc;
Page page = doc.Pages().Add();
auto graph = std::make_shared<Graph>();
graph->Left(36.0);
graph->Top(36.0);
graph->Width(500.0);
graph->Height(300.0);
auto marker = std::make_unique<Circle>();
marker->PosX(60.0);
marker->PosY(60.0);
marker->Radius(30.0);
graph->Shapes().push_back(std::move(marker));
page.Paragraphs().Add(graph);
doc.Save("shapes.pdf");Desenarea cercurilor și elipselor
Circle și Ellipse exprimă geometria ca proprietăți numerice simple, în loc de un tip comun de punct sau dreptunghi. Circle reprezintă punctul central și raza — PosX(), PosY(), Radius() — în timp ce Ellipse este o cutie delimitatoare — Left(), Bottom(), Width(), Height(). Ambele moștenesc CheckBounds(containerWidth, containerHeight) de la Shape, care raportează dacă geometria curentă a formei încape într-un container de dimensiunea dată fără a modifica forma însăși.
#include <aspose/pdf/drawing/circle.hpp>
#include <aspose/pdf/drawing/ellipse.hpp>
using namespace Aspose::Pdf::Drawing;
Circle circle;
circle.PosX(120.0);
circle.PosY(120.0);
circle.Radius(60.0);
bool circleFits = circle.CheckBounds(500.0, 300.0);
Ellipse ellipse;
ellipse.Left(220.0);
ellipse.Bottom(20.0);
ellipse.Width(250.0);
ellipse.Height(100.0);
bool ellipseFits = ellipse.CheckBounds(500.0, 300.0);Desenarea liniilor cu PositionArray
Line își stochează geometria diferit față de Circle și Ellipse: PositionArray() returnează un std::vector<float> plat care conține o pereche x, y pentru fiecare punct prin care trece linia, în loc de un set fix de proprietăţi denumite. Două puncte (patru valori) trasează un segment drept; perechi suplimentare trasează un traseu cu mai multe segmente prin acele puncte în ordine. Ca și celelalte forme, Line suprascrie CheckBounds(containerWidth, containerHeight) din Shape.
#include <aspose/pdf/drawing/line.hpp>
using namespace Aspose::Pdf::Drawing;
Line path;
path.PositionArray({0.0f, 0.0f, 250.0f, 0.0f, 125.0f, 200.0f});
bool pathFits = path.CheckBounds(500.0, 300.0);Stilizarea formelor cu GraphInfo și BorderInfo
Fiecare formă citeşte şi scrie stilul de contur şi umplere prin Shape.GraphInfo() / GraphInfo(value). GraphInfo are ca valoare implicită un LineWidth() de 1.0f cu un DashArray() gol, şi expune, de asemenea, Color(), FillColor(), DashArray()/DashPhase() pentru contururi întrerupte, IsDoubled() pentru o linie dublă, şi SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY(), şi RotationAngle() pentru transformarea conturului. Graph conţine la rândul său un BorderInfo, setat prin Border(), care grupează un GraphInfo pentru fiecare muchie — Left(), Right(), Top(), Bottom() — plus un RoundedBorderRadius(), şi poate fi construit specificând care muchii să fie stilizate cu un indicator BorderSide (BorderSide::Left | BorderSide::Right, sau BorderSide::All pentru fiecare muchie).
#include <aspose/pdf/graph_info.hpp>
#include <aspose/pdf/border_info.hpp>
#include <aspose/pdf/border_side.hpp>
#include <aspose/pdf/color.hpp>
using namespace Aspose::Pdf;
GraphInfo stroke;
stroke.LineWidth(2.5f);
stroke.Color(Color::FromRgb(1.0, 0.0, 0.0));
stroke.DashArray({3, 2});
stroke.DashPhase(1);
stroke.IsDoubled(true);
// Style only the left and right edges of the container border.
BorderInfo border{BorderSide::Left | BorderSide::Right, 3.0f};
border.RoundedBorderRadius(4.0);
graph->GraphInfo(stroke);
graph->Border(border);Sfaturi şi bune practici
- Apelaţi
CheckBoundspe proprietateaWidth()/Height()aGraphdeţinută, nu pe caseta media completă a paginii — verificarea validează geometria unei forme în raport cu dimensiunea containerului pe care o furnizaţi, nu examinează automat pagina. - Adăugaţi formele la
Shapes()înainte de a adăugaGraphlaPage.Paragraphs()— construirea unuiCircle,EllipsesauLinenu are niciun efect vizibil până când este ataşată atât laGraphdeţinătoare, cât şiGrapheste adăugată pe o pagină. - Grupează formele aferente sub un singur
Graphîn loc de unGraphpentru fiecare formă;Left()/Top()/Width()/Height()poziţionează întregul container o singură dată, iar fiecare formă dinShapes()este desenată relativ la acesta. - Setaţi
Shape.GraphInfo()explicit pentru formele care necesită o umplere vizibilă sau un contur non-implicit —GraphInfoimplicit are o lăţime de linie1.0f, fără umplere şi unDashArray()gol. - Construiți
Line.PositionArray()ca perechix0, y0, x1, y1, …în ordinea în care trebuie trasată calea — un vector de lungime impară descrie un punct incomplet.
Probleme comune
| Problemă | Cauză | Remediere |
|---|---|---|
Un Circle, Ellipse sau Line nu apare pe pagina salvată | Forma a fost construită, dar nu a fost niciodată adăugată la Graph’s Shapes(), sau Graph nu a fost niciodată adăugată pe pagină | Împinge forma pe graph->Shapes() și apelează page.Paragraphs().Add(graph) |
| Forma se desenează cu un contur subțire negru implicit | Shape.GraphInfo() nu a fost niciodată setat | Apelă shape->GraphInfo(customGraphInfo) înainte de a adăuga forma la Shapes() |
Line lipsește sau arată ca un punct unic | PositionArray() are mai puțin de două perechi (x, y) sau un număr impar de valori | Furnizează cel puțin patru valori ca x0, y0, x1, y1 |
| Doar unele margini ale bordului containerului sunt stilizate | BorderInfo a fost construit cu o mască BorderSide care exclude unele margini | Folosește BorderSide::All, sau combină cu OR fiecare flag BorderSide necesar |
CheckBounds returnează neașteptat false | Dimensiunile transmise la CheckBounds nu corespund containerului în care forma este de fapt desenată | Pasați Width()/Height() curent al Graph |
FAQ
Care este diferența dintre Circle și AnnotationType::Circle?
Circle (acest ghid) este o formă de desen care desenează direct în conținutul paginii printr-un Graph. AnnotationType::Circle și CircleAnnotation aparțin unui API separat de adnotări și reprezintă o adnotare de marcaj în formă de cerc — cele două nu sunt legate, în ciuda numelui comun.
Poate un singur Graph să conțină mai mult de o formă?
Da. Graph.Shapes() returnează întregul std::vector<std::unique_ptr<Shape>> pentru acel container, iar orice combinație de instanțe Circle, Ellipse și Line poate fi adăugată la acesta înainte ca Graph să fie adăugat pe pagină.
Împărtășesc Circle și Ellipse același tip de geometrie?
Nu. Circle este un punct central și o rază (PosX, PosY, Radius); Ellipse este o cutie delimitatoare (Left, Bottom, Width, Height). Ambele derivă din Shape, dar niciuna nu are un punct comun sau un tip de dreptunghi cu cealaltă.
Este desenarea formelor cu Graph aceeași cu redarea unei pagini într-o imagine?
Nu. Graph, Shape, Circle, Ellipse și Line construiesc geometrie vectorială nouă în conținutul unei pagini în timpul generării documentului. Convertirea unei pagini existente într-o imagine raster este o funcționalitate separată, gestionată de BmpDevice, JpegDevice și TiffDevice.
Ce face GraphInfo.IsDoubled()?
Marchează linia ca fiind dublă, în loc să modifice alte proprietăți ale liniei. Este un semnal boolean citit și setat prin IsDoubled() / IsDoubled(value) alături de celelalte proprietăți ale liniei GraphInfo.
API Reference Rezumat
| Clasă/Metodă | Descriere: |
|---|---|
Graph | Containerul de formă plasat pe o pagină; își poziționează cu Left(), Top(), Width(), Height() |
Graph.Shapes() | Returnează std::vector<std::unique_ptr<Shape>> desenat de acest container |
Graph.GraphInfo() / GraphInfo(value) | Obține/setează stilul de contur și umplere al containerului propriu |
Graph.Border() / Border(value) | Obține/setează BorderInfo care încadrează containerul |
Shape | Bază abstractă pentru Circle, Ellipse și Line; expune GraphInfo() și CheckBounds() |
Shape.CheckBounds(w, h) | Raportează dacă geometria formei se potrivește într-un container cu lățimea/înălțimea specificate |
Circle | Formă de cerc: PosX(), PosY(), Radius() |
Ellipse | Formă de elipsă: cutie delimitatoare prin Left(), Bottom(), Width(), Height() |
Line | Formă linie/traseu: PositionArray(), un std::vector<float> plat de coordonate x, y |
GraphInfo | Stilizare contur/umplere: LineWidth(), Color(), FillColor(), DashArray(), DashPhase(), IsDoubled(), RotationAngle(), SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY() |
BorderInfo | Margine container pe muchie: Left(), Right(), Top(), Bottom() (fiecare un GraphInfo), plus RoundedBorderRadius() |
BorderSide | Enum care selectează muchiile la construirea unui BorderInfo: None, Left, Top, Right, Bottom, All, Box |