Elemente ausserhalb Kurve per VBA löschen
#1
Hallo zusammen,

ich habe auf einer Seite eine Menge kleiner Shapes. (lauter gleich große Ellipsen) Darüber lege ich eine geschlossene Kurve. Wie kann man das per VBA lösen, dass alle Elemente, die nicht innerhalb der selektierten Kontur liegen (wenn möglich auch die "angeschnittenen"), gelöscht werden?

Für Eure Hilfe wäre ich sehr dankbar, da ich im Moment noch alle Elemente von Hand löschen muss.

Liebe Grüsse,

Stefan
Zitieren
#2
Hallo,
eine Möglichkeit ohne VBA mit ein bisserl Arbeit.

Benütze deine geschlossene Kurve als Powerclip für deine Ellipsen. Anschließend musst du nur noch die angeschnittenen Ellipsen über "Powerclip bearbeiten" von Hand löschen.

Gruß
Norre

Ps.
etwas Netiquette:
Wenn man eine Lösung erhält sollte man zumindest dem Antworter ein Feedback geben Wink 
https://forum.juergens-workshops.de/show...#pid162140
Zitieren
#3
Hallo Stefan,

(24.09.2020, 10:03)Sfassbender schrieb: ...Wie kann man das per VBA lösen, dass alle Elemente, die nicht innerhalb der selektierten Kontur liegen (wenn möglich auch die "angeschnittenen"), gelöscht werden?...

z.B. indem Du alle Ellipsenmittelpunkte mit IsOnShape auf die Lage in der selektierten Kontur abklopfst, diese mit IntersectsWith auf Überschneidungen mit derselben prüfst, die entsprechenden Ellipsen einer Range zuordnest und diese löscht.

Gruß

Koter
Zitieren
#4
Hallo,

schon mal vielen Dank für die Antworten.

@norre
Manuell löse ich das ganze im Moment über die Formen - Schnittmenge. Ja, die angeschnittenen muss ich auch hier einzeln löschen.

@Koter
den Ansatz mit "isOnshape" habe ich gesucht. Leider funktioniert mein kleines Skript nur bei einer kleinen Musterdatei.

Code:
Sub Test1()
Dim spattern As Shape
Dim srhole As New ShapeRange
Dim x As Double, y As Double
Dim s As LongLong
'ActiveDocument.ReferencePoint = 9
Set spattern = ActivePage.Shapes(1)
spattern.ConvertToCurves
For s = ActivePage.Shapes.Count To 2 Step -1
ActivePage.Shapes(s).GetPosition x, y
    Select Case spattern.IsOnShape(x, y, 0.02)
        Case cdrOnMarginOfShape
        srhole.Add ActivePage.Shapes(s)
    End Select
        Select Case spattern.IsOnShape(x, y)
        Case cdrOutsideShape
        srhole.Add ActivePage.Shapes(s)
    End Select
Next
srhole.Delete
End Sub

Dabei ist die Kurve, ausserhalb der ich die anderen Elemente löschen will immer shape(1).


Teil 1 Case cdrOnMarginOfShape funktioniert eigentlich sehr gut.
Nur Case cdrOutsideShape bekomme ich nicht hin.

Ich hab ein bisschen mit ActiveDocument.ReferencePoint rumgespielt (da ich davon echt keine Ahnung hab) und erhalte unterschiedliche Ergebnisse. Leider nicht die richtigen. Hast du dazu einen Tipp für mich?

Liebe Grüsse,
Stefan
Zitieren
#5
Hallo Stefan,

ich dachte schon, Du liest die Antworten gar nicht.

(28.09.2020, 11:01)Sfassbender schrieb: den Ansatz mit "isOnshape" habe ich gesucht. Leider funktioniert mein kleines Skript nur bei einer kleinen Musterdatei.

Ich habe meine Antwort in ein Codebeispiel übersetzt, und als Kommentar eingefügt.
Vielleicht funktioniert das ja bei Deiner Datei. Die kenne ich nicht, also kann ich es nicht versprechen.

Code:
Sub Ellipsenkiller()
   Dim s As Shape, spattern As Shape
   Dim srhole As New ShapeRange
   Dim x As Integer
   Set spattern = ActivePage.Shapes(1)
   
   For Each s In ActivePage.Shapes.AllExcluding(Array(1))
       'indem Du alle Ellipsenmittelpunkte mit IsOnShape auf die Lage in der selektierten Kontur abklopfst:
       x = spattern.IsOnShape(s.CenterX, s.CenterY)
       If x > 0 Then
           'diese mit IntersectsWith auf Überschneidungen mit derselben prüfst:
           If s.DisplayCurve.IntersectsWith(spattern.DisplayCurve) Then
               srhole.Add s 'die entsprechenden Ellipsen einer Range zuordnest
           End If
       Else
           srhole.Add s 'die entsprechenden Ellipsen einer Range zuordnest
       End If
   Next
   srhole.Delete 'und diese löschst,
   
End Sub


(28.09.2020, 11:01)Sfassbender schrieb: ...Ich hab ein bisschen mit ActiveDocument.ReferencePoint rumgespielt (da ich davon echt keine Ahnung hab) und erhalte unterschiedliche Ergebnisse. Leider nicht die richtigen. Hast du dazu einen Tipp für mich?
Der ReferencePoint entspricht dem Objektursprung, den Du ganz links auf der Eigenschaftsleiste findest.
Ich glaube nicht, das der uns bei Deiner Aufgabe helfen kann.

Gruß

Koter
Zitieren
#6
(28.09.2020, 20:06)koter schrieb: Hallo Stefan,

ich dachte schon, Du liest die Antworten gar nicht.
Guten Morgen,

doch, doch. Ich habs direkt gelesen. Ich bin nur kein Fan von Antworten wie "Danke, ich werds später mal versuchen."

Ich hab das am Freitag probiert und dann kam das heilige Wochenende dazwischen.

Danke aber nochmal für Deine Hilfe. Funktioniert super und schnell, mit einer Einschränkung.
Ich denke ich habe zu wenig Arbeitsspeicher für diese Aufgabe. Da es sehr viele Ellipsen sind, bekomme ich leider nicht das richtige Ergebnis. Reduziere ich die Anzahl der Ellipsen, funktionierts prima.

Ich glaube, ich werde das ganze mal andersherum probieren. Das ursprüngliche Shape mit den Ellipsen füllen....

Vielen Dank!

Stefan
Zitieren
#7
Hallo Stefan,

(29.09.2020, 07:06)Sfassbender schrieb: ...und dann kam das heilige Wochenende dazwischen...

Ich meinte eigentlich diesen Beitrag,  aber das war ja auch vor 225 Wochenenden, ist also schon lange her!  Wink

(29.09.2020, 07:06)Sfassbender schrieb: ...Ich denke ich habe zu wenig Arbeitsspeicher für diese Aufgabe. Da es sehr viele Ellipsen sind, bekomme ich leider nicht das richtige Ergebnis. Reduziere ich die Anzahl der Ellipsen, funktionierts prima...

Mich würde sehr interessieren, unter welchen Umständen das Makro versagt!
Kannst Du das näher beschreiben oder vielleicht sogar die Datei anhängen? Das wäre super!

Ich habe es mit bis zu 40.000 Ellipsen getestet und nicht einmal hat das Makro versagt.
Hier ein Test mit 22.500 Ellipsen:

[Bild: ellikillr5k0n.gif]

Der Rechner hat nur 4 GB Arbeitsspeicher, mit eingeschalteter Optimierung (Optimization = true) ging es aber doch recht flott.

Ich würde gerne wissen ob ich einen Denkfehler in das Makro gepackt habe oder sich ein anderer Grund findet, warum es bei Dir versagt hat.

Gruß

Koter
Zitieren
#8
Guten Morgen Koter,

an der Anzahl der Kurven liegt es offensichtlich nicht.
Wenn ich die Ellipsen neu erstelle, eine Kontur drüber zeichne und das Makro laufen lasse, funktioniert es.
Kopiere ich die Ellipsen aus einer anderen Datei und zeichen die Kontur (freihand) drüber, löscht er abwechselnd falsche Kurven. Hängt scheinbar auch davon ab, wohin ich die Kontur verschiebe.

Selbst wenn ich die Kontur aus einer anderen datei via copy paste über die erstellen Ellipsen einfüge gibts nur Gewurschtel.

Um das ganze noch verwirrender zu machen, hab ich Dir drei Bilder angehängt.
Bild 04 = Ausgangsposition
Bild 05 = Zoom mit F3 geändert - Makro laufen lassen
Bild 06 = Zoom mit F4 auf alle Elemente - Makro laufen lassen


Ich hatte gestern in einer andern Angelegenheit das Problem, das ein Makro, dass eine Range über die x- bzw. y-Koordinaten erstellt seltsame Ergebnisse lieferte. Hier hatte allerdings jemand den Ursprung des Lineals verstellt.

Jetzt frage ich mich, ob das in diesem Fall eine ähnliche Ursache haben könnte. Von wegen Ursprung der xy Koordinaten, Layer, ...

Hättest du dazu noch eine Idee?


Angehängte Dateien Thumbnail(s)
           

.cdr   kleiner test.cdr (Größe: 493,84 KB / Downloads: 1)
[-] 1 Benutzer bedankt sich bei Sfassbender für diesen Beitrag:
  • koter
Zitieren
#9
Hallo Stefan,

vielen Dank für die ausführliche Antwort und den Dateianhang!

beim Testen hatte ich die Kontur immer auf einer eigenen Ebene, deshalb wurde sie bei mir nicht gelöscht.
Ich habe das Makro so angepasst, dass die Kontur nicht mehr ausgewählt wird (wenn sie ganz oben liegt).

Die Genauigkeit von „IsOnShape“ hängt seltsamerweise vom Zoom ab. je höher der Zoom desto genauer arbeitet die Methode. Ich habe das Makro so angepasst, dass der Zoom hochgesetzt, die Methode ausgeführt und der Zoom dann zurückgesetzt wird. Wenn die Optimierung eingeschaltet ist, bekommt der User nichts davon mit.

Code:
Sub Ellipsenkiller()
   Dim S As Shape, spattern As Shape
   Dim srhole As New ShapeRange
   Dim x As Integer
   Dim z As Double, oX As Double, oY As Double, oW As Double, oH As Double
   On Error GoTo Ende
   Set spattern = ActivePage.Shapes(1)
   ActiveDocument.BeginCommandGroup "Ellipsenkiller"
   Application.Optimization = True
   Call ActiveWindow.ActiveView.GetViewArea(oX, oY, oW, oH)
   ActiveWindow.ActiveView.Zoom = 1600
   
   For Each S In ActiveLayer.Shapes.AllExcluding(1)
       x = spattern.IsOnShape(S.CenterX, S.CenterY)
       If x > 0 Then
           If S.DisplayCurve.IntersectsWith(spattern.DisplayCurve) Then
               srhole.Add S
           End If
       Else
           srhole.Add S
       End If
   Next
   
   srhole.Shapes.All.Delete
Ende:
   Call ActiveWindow.ActiveView.SetViewArea(oX, oY, oW, oH)
   Application.Optimization = False
   Application.Windows.Refresh
   ActiveDocument.EndCommandGroup
End Sub

Leider hat Corel die Methode in der Hilfe nicht ausreichend Dokumentiert. Da sie aber im Hilfe-Beispiel zusammen mit „GetUserClick“ verwendet wird, könnte das die Erklärung sein. Je höher der User den Zoom einstellt, desto genauer muss die Methode arbeiten.

Mann kann Natürlich auch andere Methoden verwenden, wenn man den Zoom nicht antasten will.

Beispiel:
Code:
Sub Ellipsenkiller2()
   Dim s1 As Shape
   On Error GoTo Ende
   ActiveDocument.BeginCommandGroup "Ellipsenkiller2"
   Application.Optimization = True
   
   Set s1 = ActiveLayer.Shapes.AllExcluding(1).Combine.Trim(ActiveLayer.Shapes(1), False, True)
   s1.Curve.SubPaths(1).Delete
   s1.BreakApart
   
Ende:
   Application.Optimization = False
   Application.Windows.Refresh
   ActiveDocument.EndCommandGroup
End Sub

Das Makro verwendet die  Methode „Trim“.
Man braucht weniger Codezeilen, es dauert aber länger und es können nur geschlossene Konturen verwendet werden.
Die Ellipsen werden in Kurven gewandelt. Wenn es Ellipsen bleiben müssen, kannst Du die Methode also nicht verwenden.

Ich weiß nicht, wo Du das Makro einbauen willst, und wozu es genau dient. Aber vielleicht findet sich ja eine Maßgeschneiderte Lösung für Deinen Zweck.

(30.09.2020, 06:31)Sfassbender schrieb: ...Ich hatte gestern in einer andern Angelegenheit das Problem, das ein Makro, dass eine Range über die x- bzw. y-Koordinaten erstellt seltsame Ergebnisse lieferte. Hier hatte allerdings jemand den Ursprung des Lineals verstellt...
Jetzt frage ich mich, ob das in diesem Fall eine ähnliche Ursache haben könnte. Von wegen Ursprung der xy Koordinaten, Layer, ...
Hättest du dazu noch eine Idee?

Dass bei diesem Makro der Koordinatenursprung eine Rolle spielt, halte ich für unwahrscheinlich weil keine absoluten Koordinaten verwendet werden.
Wenn Du annimmst, dass ein Benutzer den Ursprung umstellt, kannst Du Deine Koordinaten ja auf einen Referenzpunkt (z.B den Seitenrand) beziehen, oder den Ursprung mit „DrawingOriginX“ und „DrawingOriginY“ zurücksetzen.

Nachtrag:
Den Ursprung sollte man nach der Bearbeitung wieder auf die Werte des Benutzers zurückstellen. Der Benutzer wird (wahrscheinlich) einen Grund für sein Handeln gehabt haben.
Außerdem wäre es unhöflich Benutzereinstellungen ungefragt zu ändern.

Gruß

Koter
[-] 1 Benutzer bedankt sich bei koter für diesen Beitrag:
  • Sfassbender
Zitieren
#10
Hallo Koter,

vielen, vielen Dank! Genau das was ich brauche. Funktioniert einwandfrei und da mir der Zoom gleichgültig ist, läuft Dein erster Code auch angenehm schnell. (Das ist natürlich relativ bei ca. 100.000 Ellipsen)

Diese Teile werden die Vorlage für perforierte Textilien. Die Ellipsen sollen die Bohrlöcher im Stoff darstellen. Auf diese Weise kann ich auch evtl. Schriften oder Muster innerhalb der Kontur erstellen.

Ich habe da zwar noch ein Problem mit der "nachgeordneten" Stelle. Dabei gebe ich die cdr als dxf aus. Es gibt wohl scheinbar noch das Problem, die kleinen Ellipsen oder Kurven beim Import in Autocad als Kreise darzustellen.
Da ich weder Autocad anwende noch kenne, kann ich dazu auch noch nix sagen.

Also dann nochmal vielen Dank!

Stefan
Zitieren



Möglicherweise verwandte Themen...
Thema Verfasser Antworten Ansichten Letzter Beitrag
  Mini-Objekte innerhalb einer Gruppe fassen und löschen migo 10 1.128 27.03.2024, 09:35
Letzter Beitrag: Boerni
  Elemente außerhalb Zeichenfläche weg hansknall 2 388 04.07.2023, 19:31
Letzter Beitrag: hansknall
  Fonts löschen Reserl 11 3.007 05.12.2020, 16:14
Letzter Beitrag: Reserl
  Vektorgrafik nach virtuellen Segmente löschen nicht brauchbar zum plotten Mecky 3 1.613 25.08.2020, 11:05
Letzter Beitrag: Mecky
  Erstellte Zweifarbenmuster löschen LuGa 7 2.395 22.05.2020, 00:28
Letzter Beitrag: Unkraut
  2018: mehrere Seiten löschen mtemp 3 1.852 09.10.2019, 15:09
Letzter Beitrag: mtemp
  Objektstile löschen wdreinheim 9 3.443 13.03.2019, 22:06
Letzter Beitrag: koter
  Doppelte Konturen erkenn und löschen view2lord 25 10.015 15.01.2019, 12:32
Letzter Beitrag: Unkraut
  Aus mehreren gestückelten Linien eine Kurve erstellen bengchui 1 1.850 08.10.2018, 11:54
Letzter Beitrag: norre
  Kurve aus Koordinaten erstellen nowa 9 3.004 25.12.2016, 12:11
Letzter Beitrag: nowa