Hallo zusammen,
ich habe ein Programm erstellt, mit dem ich auf automatisierte Weise prüfen kann, ob- und wenn ja wo sich ein bestimmtes Bauteil mit einem Sauggreifer aufnehmen läßt. Dabei erstelle ich grafisch das Bauteil, auch den Greifer und setze die beiden Grafiken dann übereinander. Anhand der Überschneidungen zwischen Bauteil, Bohrungen und Sauger erkenne ich dann, ob an dieser bestimmten Position nun gegriffen werden kann oder nicht.
Das Bauteil selbst wird als Region, erzeugt aus verschiedenen graphicsPath Objekten, dargestellt. Gleiches gilt für den Sauger.
Da jetzt ein Bild mehr als 1000 Worte sagt, hier mal eine Abbiildung des Iststandes:
Der rote Ring in der Abbildung stellt das Bauteil dar, die restlichen Kreise die Sauger. Die vollen grünen Kreise sind Sauger, welche gerade im angesaugten Zustand sind. die "leeren Kreise" sind nicht-angesaugte Sauger.
Die Abbildung zeigt auch gleich mein Problem:
Im roten Ring ist der Sauger auf ca. 3 Uhr über einer Bohrung. Wenn ich den Sauger jetzt so verschiebe, dass die Bohrung innerhalb der Außenkante des Saugers ist, dann meint das Programm "alles OK" und saugt an. Das ist es aber natürlich nicht.
Woher das Problem kommt ist mir klar, allerdings fehlt mir die Lösung dafür noch.... Desshalb meine Bitte an die Wissenden hier im Forum nach guten Tips...
Ein paar Informationen noch zur Berechnung, also was ich hier mache und wie ich zu den jeweiligen Werten komme:
Wie erwähnt besteht das Bauteil aus einer Region. Diese wird erzeugt indem ich zuerst die Region mit der Außenkontur erstelle, und davon dann mittels region.exclude(graphicsPath) die jeweiligen Bohrungen ausschließe.
Spoiler anzeigen
Die Sauger werden prinzipiell genauso erstellt, für die eigentliche Berechnung sind aber nur die Pfade interessant, nicht die Regionen. Die Überprüfung erfolgt dann folgendermaßen:
Spoiler anzeigen
Ich erzeuge also eine "Polylinie" aus der Kreisbahn, und prüfe dann jeden einzelnen Punkt dieser Linie auf region.isVisible. Und genau da "liegt der Hase im Pfeffer..." Denn in der oben beschriebenen Situation, also wenn ein Sauger eine Bohrung vollständig überdeckt, also die Außenkontur des Saugers keine Überschneidung mit der Bohrung hat, dann wird angesaugt. Was natürlich nicht sein darf. Er darf nur ansaugen, wenn sich der Sauger vollständig über der Bauteil - Region befindet.
Zur Kollisionserkennung hab ich schon ein paar Sachen gefunden, nur eine richtige Kollision erkenne ich ja, eine vollständige Überdeckung leider nicht. Bei meiner Suche bin ich dann noch über eine pixelgenaue- Kollisionserkennung gestolpert, wäre vermutlich eine Möglichkeit - aber doch recht aufwändig denke ich.
Hat dazu noch jemand eine Idee?
Vielleicht noch als erklärung wesshalb ich den ganzen Aufwand treibe:
In der obigen Abbildung wäre dies ja alles nicht nötig, denn da ließe sich das auch einfach rechnen (Abstand zwischen Mittelpunkten<Summe der Radien = Überschneidung) aber leider kann mir als "Bohrung" auch sowas passieren:
Auch das würde sich ja grundsätzlich rechnen lassen, aber da wird der Aufwand dann schon ganz ordentlich denke ich...
Im Prinzip gehts einzig und alleine darum, ob mein "Kreiserl" (also der Sauger) vollständig auf der Fläche des Bauteils ist oder nicht....
Mit der Bitte und Hoffnung auf gute Tips,
LG aus Wien
Günther
ich habe ein Programm erstellt, mit dem ich auf automatisierte Weise prüfen kann, ob- und wenn ja wo sich ein bestimmtes Bauteil mit einem Sauggreifer aufnehmen läßt. Dabei erstelle ich grafisch das Bauteil, auch den Greifer und setze die beiden Grafiken dann übereinander. Anhand der Überschneidungen zwischen Bauteil, Bohrungen und Sauger erkenne ich dann, ob an dieser bestimmten Position nun gegriffen werden kann oder nicht.
Das Bauteil selbst wird als Region, erzeugt aus verschiedenen graphicsPath Objekten, dargestellt. Gleiches gilt für den Sauger.
Da jetzt ein Bild mehr als 1000 Worte sagt, hier mal eine Abbiildung des Iststandes:
Der rote Ring in der Abbildung stellt das Bauteil dar, die restlichen Kreise die Sauger. Die vollen grünen Kreise sind Sauger, welche gerade im angesaugten Zustand sind. die "leeren Kreise" sind nicht-angesaugte Sauger.
Die Abbildung zeigt auch gleich mein Problem:
Im roten Ring ist der Sauger auf ca. 3 Uhr über einer Bohrung. Wenn ich den Sauger jetzt so verschiebe, dass die Bohrung innerhalb der Außenkante des Saugers ist, dann meint das Programm "alles OK" und saugt an. Das ist es aber natürlich nicht.
Woher das Problem kommt ist mir klar, allerdings fehlt mir die Lösung dafür noch.... Desshalb meine Bitte an die Wissenden hier im Forum nach guten Tips...
Ein paar Informationen noch zur Berechnung, also was ich hier mache und wie ich zu den jeweiligen Werten komme:
Wie erwähnt besteht das Bauteil aus einer Region. Diese wird erzeugt indem ich zuerst die Region mit der Außenkontur erstelle, und davon dann mittels region.exclude(graphicsPath) die jeweiligen Bohrungen ausschließe.
VB.NET-Quellcode
- Public Sub CreateRegions()
- Dim i As Integer
- Dim iMin As Integer
- Dim iMax As Integer
- iMin = PartsInProgrammGeoList.Min(Function(x) x.GeoLfdNr)
- iMax = PartsInProgrammGeoList.Max(Function(x) x.GeoLfdNr)
- For i = iMin To iMax
- partRegion.Add(i, New clsRegionen)
- partRegion.Item(i).BauteilNummer = i
- partRegion.Item(i).PartBrush = BauteilBrushNotSelected
- For Each ge In PartsInProgrammGeoList.Where(Function(y) y.GeoLfdNr = i)
- 'Abweichung der errechneten Abbildung zu PARTS_IN_PROGRAM_POS errechnen und über die Matrix angleichen
- Dim dx, dy As Single
- Dim BohrungsPath As New Drawing2D.GraphicsPath
- Dim PathRect As RectangleF = ge.GpAussenkante.GetBounds(ge.GCodeMatrix)
- Dim MofPathRect As PointF = RectMiddle(PathRect)
- Dim MofPartPos As PointF = RectMiddle(New RectangleF(ge.PosX, ge.PosY, ge.AbInX, ge.AbInY))
- dx = MofPartPos.X - MofPathRect.X
- dy = MofPartPos.Y - MofPathRect.Y
- ge.GCodeMatrix.Translate(dx, dy, MatrixOrder.Append)
- 'Grundfläche erzeugen
- ge.GpAussenkante.Transform(ge.GCodeMatrix)
- partRegion.Item(i).PartRegion = New Region(ge.GpAussenkante)
- 'Innenfläche von Region entfernen
- ge.GpInnenkante.Transform(ge.GCodeMatrix)
- partRegion.Item(i).PartRegion.Exclude(ge.GpInnenkante)
- 'Mitnehmerbohrungen einzeichnen
- ge.GpMitnehmer.Transform(ge.GCodeMatrix)
- partRegion.Item(i).PartRegion.Exclude(ge.GpMitnehmer)
- 'Invertierte Flächen speichern --> Zur Prüfung auf Überschneidung Sauger/Bohrung
- If ge.GpInnenkante.PointCount > 0 Then
- BohrungsPath.AddPath(ge.GpInnenkante, False)
- End If
- If ge.GpMitnehmer.PointCount > 0 Then
- BohrungsPath.AddPath(ge.GpMitnehmer, False)
- End If
- If BohrungsPath.PointCount > 0 Then
- partRegion.Item(i).BohrungsRegion = New Region(BohrungsPath)
- End If
- Next
- Next
- End Sub
Die Sauger werden prinzipiell genauso erstellt, für die eigentliche Berechnung sind aber nur die Pfade interessant, nicht die Regionen. Die Überprüfung erfolgt dann folgendermaßen:
VB.NET-Quellcode
- Public Function getAktSaugerState(SaugerPath As Drawing2D.GraphicsPath) As SaugerState
- 'Dim part As PARTS_IN_PROGRAM_POS_CLS = PartsInProgrammGeoList.Item(AktPart)
- Dim part As clsRegionen = partRegion.Item(AktPart + 1)
- Dim tempPath As Drawing2D.GraphicsPath = TryCast(SaugerPath.Clone, Drawing2D.GraphicsPath)
- Dim aktState As SaugerState
- tempPath.Flatten()
- For Each pt As PointF In tempPath.PathPoints
- If part.PartRegion.IsVisible(pt) Then
- If Not part.BohrungsRegion.IsVisible(pt) Then
- aktState = SaugerState.angesaugt
- Else
- aktState = SaugerState.entspannt
- Exit For
- End If
- Else
- aktState = SaugerState.entspannt
- Exit For
- End If
- Next
- Return aktState
- End Function
Ich erzeuge also eine "Polylinie" aus der Kreisbahn, und prüfe dann jeden einzelnen Punkt dieser Linie auf region.isVisible. Und genau da "liegt der Hase im Pfeffer..." Denn in der oben beschriebenen Situation, also wenn ein Sauger eine Bohrung vollständig überdeckt, also die Außenkontur des Saugers keine Überschneidung mit der Bohrung hat, dann wird angesaugt. Was natürlich nicht sein darf. Er darf nur ansaugen, wenn sich der Sauger vollständig über der Bauteil - Region befindet.
Zur Kollisionserkennung hab ich schon ein paar Sachen gefunden, nur eine richtige Kollision erkenne ich ja, eine vollständige Überdeckung leider nicht. Bei meiner Suche bin ich dann noch über eine pixelgenaue- Kollisionserkennung gestolpert, wäre vermutlich eine Möglichkeit - aber doch recht aufwändig denke ich.
Hat dazu noch jemand eine Idee?
Vielleicht noch als erklärung wesshalb ich den ganzen Aufwand treibe:
In der obigen Abbildung wäre dies ja alles nicht nötig, denn da ließe sich das auch einfach rechnen (Abstand zwischen Mittelpunkten<Summe der Radien = Überschneidung) aber leider kann mir als "Bohrung" auch sowas passieren:
Auch das würde sich ja grundsätzlich rechnen lassen, aber da wird der Aufwand dann schon ganz ordentlich denke ich...
Im Prinzip gehts einzig und alleine darum, ob mein "Kreiserl" (also der Sauger) vollständig auf der Fläche des Bauteils ist oder nicht....
Mit der Bitte und Hoffnung auf gute Tips,
LG aus Wien
Günther