.Netto-Gegenteil von GraphicsPath.Erweitern()

Ich brauche das Gegenteil von der GraphicsPath.Widen() Methode .Net:

public GraphicsPath Widen()

Den Widen() Methode nicht akzeptieren, ein negativer parameter, also ich brauche das entspricht einer Inset Methode:

public GraphicsPath Inset()

Dazu können Sie in der open-source-Inkscape (www.Inkscape.org), indem Sie auf Menü und wählen Sie "Pfad /Inset" (der eingesetzte Betrag ist gespeichert in der Inkscape-Eigenschaften-dialog). Da Inkscape ist open source, es sollte möglich sein, dies zu tun C#.Net aber ich kann nicht Folgen die Inkscape-C++ - Quelldatei, die für das Leben von mir (und ich brauche nur diese eine Funktion, so kann ich es nicht rechtfertigen, Lern C++, um diese abzuschließen).

Im Grunde, ich brauche ein GraphicsPath-Erweiterung-Methode mit der folgenden Signatur:

public static GraphicsPath Inset(this GraphicsPath original, float amount)
{
   //implementation
}

Wie die Signatur-Staaten, es wird ein GraphicsPath Objekt und .Inset() den Weg durch eine übergebene Menge... genauso wie Inkscape heute tut. Wenn es vereinfacht die ganze Angelegenheit jeder, der GraphicsPaths in Frage, die sind alle aus der .PolyBezier Methode (und sonst nichts), so gibt es keine Notwendigkeit zu berücksichtigen, für rects, Ellipsen oder anderen Formen, es sei denn, Sie wollen es der Vollständigkeit halber.

Leider habe ich keine Erfahrung mit C++ - code, so dass seine fast unmöglich für mich zu Folgen die C++ - Logik enthalten in Inkscape.

.

[EDIT:]
Wie gewünscht, hier der "MakeOffset" Inkscape-code. Der zweite parameter (Doppel-Dez) wird negativ sein für ein Einschub, und der absolute Wert dieses Parameters ist die Menge zu bringen, in die Form.

Ich weiß, dass es eine Menge von Abhängigkeiten hier. Wenn Sie brauchen, um mehr zu sehen von der Inkscape-Quellcode-Dateien, Sie sind hier: http://sourceforge.net/projects/inkscape/files/inkscape/0.48/

int
Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_profile, double cx, double cy, double radius, Geom::Matrix *i2doc)
{
  Reset (0, 0);
  MakeBackData(a->_has_back_data);

    bool done_something = false;

  if (dec == 0)
  {
    _pts = a->_pts;
    if (numberOfPoints() > maxPt)
    {
      maxPt = numberOfPoints();
      if (_has_points_data) {
        pData.resize(maxPt);
        _point_data_initialised = false;
        _bbox_up_to_date = false;
        }
    }

    _aretes = a->_aretes;
    if (numberOfEdges() > maxAr)
    {
      maxAr = numberOfEdges();
      if (_has_edges_data)
    eData.resize(maxAr);
      if (_has_sweep_src_data)
        swsData.resize(maxAr);
      if (_has_sweep_dest_data)
        swdData.resize(maxAr);
      if (_has_raster_data)
        swrData.resize(maxAr);
      if (_has_back_data)
        ebData.resize(maxAr);
    }
    return 0;
  }
  if (a->numberOfPoints() <= 1 || a->numberOfEdges() <= 1 || a->type != shape_polygon)
    return shape_input_err;

  a->SortEdges ();

  a->MakeSweepDestData (true);
  a->MakeSweepSrcData (true);

  for (int i = 0; i < a->numberOfEdges(); i++)
  {
    //             int    stP=a->swsData[i].stPt/*,enP=a->swsData[i].enPt*/;
    int stB = -1, enB = -1;
    if (dec > 0)
    {
      stB = a->CycleNextAt (a->getEdge(i).st, i);
      enB = a->CyclePrevAt (a->getEdge(i).en, i);
    }
    else
    {
      stB = a->CyclePrevAt (a->getEdge(i).st, i);
      enB = a->CycleNextAt (a->getEdge(i).en, i);
    }

    Geom::Point stD, seD, enD;
    double stL, seL, enL;
    stD = a->getEdge(stB).dx;
    seD = a->getEdge(i).dx;
    enD = a->getEdge(enB).dx;

    stL = sqrt (dot(stD,stD));
    seL = sqrt (dot(seD,seD));
    enL = sqrt (dot(enD,enD));
    MiscNormalize (stD);
    MiscNormalize (enD);
    MiscNormalize (seD);

    Geom::Point ptP;
    int stNo, enNo;
    ptP = a->getPoint(a->getEdge(i).st).x;

        double this_dec;
        if (do_profile && i2doc) {
            double alpha = 1;
            double x = (Geom::L2(ptP * (*i2doc) - Geom::Point(cx,cy))/radius);
            if (x > 1) {
                this_dec = 0;
            } else if (x <= 0) {
                this_dec = dec;
            } else {
                this_dec = dec * (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5);
            }
        } else {
            this_dec = dec;
        }

        if (this_dec != 0)
            done_something = true;

    int   usePathID=-1;
    int   usePieceID=0;
    double useT=0.0;
    if ( a->_has_back_data ) {
      if ( a->ebData[i].pathID >= 0 && a->ebData[stB].pathID == a->ebData[i].pathID && a->ebData[stB].pieceID == a->ebData[i].pieceID
           && a->ebData[stB].tEn == a->ebData[i].tSt ) {
        usePathID=a->ebData[i].pathID;
        usePieceID=a->ebData[i].pieceID;
        useT=a->ebData[i].tSt;
      } else {
        usePathID=a->ebData[i].pathID;
        usePieceID=0;
        useT=0;
      }
    }
    if (dec > 0)
    {
      Path::DoRightJoin (this, this_dec, join, ptP, stD, seD, miter, stL, seL,
                         stNo, enNo,usePathID,usePieceID,useT);
      a->swsData[i].stPt = enNo;
      a->swsData[stB].enPt = stNo;
    }
    else
    {
      Path::DoLeftJoin (this, -this_dec, join, ptP, stD, seD, miter, stL, seL,
                        stNo, enNo,usePathID,usePieceID,useT);
      a->swsData[i].stPt = enNo;
      a->swsData[stB].enPt = stNo;
    }
  }

  if (dec < 0)
  {
    for (int i = 0; i < numberOfEdges(); i++)
      Inverse (i);
  }

  if ( _has_back_data ) {
    for (int i = 0; i < a->numberOfEdges(); i++)
    {
      int nEd=AddEdge (a->swsData[i].stPt, a->swsData[i].enPt);
      ebData[nEd]=a->ebData[i];
    }
  } else {
    for (int i = 0; i < a->numberOfEdges(); i++)
    {
      AddEdge (a->swsData[i].stPt, a->swsData[i].enPt);
    }
  }

  a->MakeSweepSrcData (false);
  a->MakeSweepDestData (false);

  return (done_something? 0 : shape_nothing_to_do);
}

.

[BEARBEITUNGEN]

@Simon Mourier - Tolle Arbeit. Der code war auch sauber und lesbar! Schöne Arbeit, sir. Ich habe ein paar Fragen für Sie, obwohl.

Erstens, was bedeutet eine positive Zahl für die Höhe dar? Ich dachte, dass es für die Offset-Methode, positiv sein würde "Anfang" und negativ wäre, "inset", aber dein Beispiel scheint das Gegenteil tun.

Zweiten, habe ich ein paar grundlegende Tests (nur die Erweiterung Ihrer Probe), und fand einige Merkwürdigkeiten.

Hier ist, was passiert mit dem "l" in cool, wenn der offset wächst (für solche einfachen Brief, sicher, es mag zu Problemen führen!).

.Netto-Gegenteil von GraphicsPath.Erweitern()

...und der code zum reproduzieren eines:

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
            GraphicsPath path = new GraphicsPath();

            path.AddString("cool", new FontFamily("Arial"), 0, 200, new PointF(), StringFormat.GenericDefault);

            GraphicsPath offset1 = path.Offset(32);

            e.Graphics.DrawPath(new Pen(Color.Black, 1), path);
            e.Graphics.DrawPath(new Pen(Color.Red, 1), offset1);
    }

Schließlich, etwas ein wenig anders. Hier ist der "S" - Zeichen aus Wingdings (erscheint wie eine Träne):

.Netto-Gegenteil von GraphicsPath.Erweitern()

Hier ist der code:

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        GraphicsPath path = new GraphicsPath();
        path.AddString("S", new FontFamily("Wingdings"), 0, 200, new PointF(), StringFormat.GenericDefault);
        GraphicsPath offset1 = path.Offset(20);

        e.Graphics.DrawPath(new Pen(Color.Black, 1), path);
        e.Graphics.DrawPath(new Pen(Color.Red, 1), offset1);
    }

Mann, das ist so nah, es macht mich wollen, zu Weinen. Es funktioniert immer noch nicht, obwohl.

Denke ich, was würde es zu beheben ist, um zu sehen, wenn der eingesetzte Vektoren schneiden, und stoppen insetting über diesen Punkt. Wenn der eingesetzte Betrag ist so groß (oder der Pfad so klein), dass nichts übrig geblieben ist, der Pfad sollte verschwinden (zu null), anstelle der Umkehrung auf sich selbst und re-erweitern.

Wieder, ich bin nicht klopfen, was Sie getan haben, in irgendeiner Weise, aber ich Frage mich, ob Sie wissen, was könnte Los sein mit diesen Beispielen.

(PS - habe ich das "this" Schlüsselwort, um es eine extension-Methode, so dass Sie möglicherweise benötigen, rufen Sie den code mit der Methode(Parameter) notation dieser Proben laufen)

.

@RAN
Ran kommen mit einem ähnlichen Ausgang, durch die erneute Nutzung der GraphicsPath-native Methoden. Mann, das ist hart. Beide sind so nah.

Hier ist ein Screenshot der beiden Beispiele, die Benutzung des Zeichens "S" aus Wingdings:

.Netto-Gegenteil von GraphicsPath.Erweitern()

@Simon ist auf der linken Seite, @Lief auf der rechten Seite.

Hier ist die gleiche tear drop "S" - Zeichen nach einem "Einschub" in Inkscape. Der Einschub ist sauber:

.Netto-Gegenteil von GraphicsPath.Erweitern()

Übrigens, hier ist der code für die @Rans-test:

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        GraphicsPath path = new GraphicsPath();
        path.AddString("S", new FontFamily("Wingdings"), 0, 200, new PointF(), StringFormat.GenericDefault);
        e.Graphics.DrawPath(new Pen(Color.Black, 1), path);

        GraphicsPath offset1 = path.Shrink(20);
        e.Graphics.DrawPath(new Pen(Color.Red, 1), offset1);
    }
  • Vielleicht könnten Sie schreiben Inkscape-C++ - code und jemand, der weiß, C++ wird in der Lage sein zu helfen.
  • Sicher. Ich werde nach den "core" - Funktion von Inkscape, aber es kann durchaus ein paar Abhängigkeiten.
  • Möchten Sie diese arbeiten auf Pfaden im Allgemeinen, oder nur Wege, die vorher verbreitert worden? Ich glaube nicht, dass es möglich sein wird, um "rückgängig", eine Erweiterung der transformation und bekomme wieder den ursprünglichen Weg, da ein Teil der widen Verhalten ist die approximation von Kurven durch eine Serie von Liniensegmenten.
  • Hallo Ben - gute Frage. Nein, das sind Pfade, die vorher nicht "verbreitert", und keine ähnlichkeit mit die .Widen-Methode erforderlich ist.
InformationsquelleAutor Flipster | 2010-12-29
Schreibe einen Kommentar