Java Ellipse aus Linien zeichnen - Fehler wegen nur ganzzahlig möglichen Winkeln?

5 Antworten

Hallo Willibergi,

ganz "schönes" Problem. Der Grund ist, wie Du ja selbst schon anmerkst, dass Du runden musst. Du bist schließlich an die Auflösung gebunden.

Beheben könntest Du das Problem indem Du auf einem wesentlich größeren Grafik-Kontext zeichnest und diesen dann, sobald er fertig gerendert ist runter-skalierst auf deine Auflösung. Da müsstest Du womöglich ausrechnen, wie groß der Grafikkontext sein muss, damit Du keine Lücken erzeugst.

Eine andere Möglichkeit wäre die Logik umzudrehen. Also nicht Linien zu zeichnen, sondern zu jeder Koordinate x,y die Farbe zu berechnen und dann genau den Punkt mit der Farbe zu zeichnen. So überspringst Du natürlich keine Punkte.

Gruß

Woher ich das weiß:Berufserfahrung
Willibergi 
Fragesteller
 25.11.2018, 20:27

Danke für Deine Antwort!

Aber ist das nicht dasselbe, wie als würde ich einfach größer zeichnen?

0
AldoradoXYZ  25.11.2018, 20:29
@Willibergi

Du würdest im zweiten Schritt ja verkleinern. Von außen nach innen zeichnen halte ich auch für interessant.

Ich probiere grad mal verschiedene Lösungen aus.

Gruß

0

So wie ich den Code verstehe iterierst Du über die falsche Größe.

Im Endeffekt möchtest Du über die Koordinaten, die Integralwerte sind, iterieren.

Willibergi 
Fragesteller
 26.11.2018, 00:40

Welche Schleife meinst Du?

0
KarlRanseierIII  26.11.2018, 01:36
@Willibergi

Ich meine die Logik, Du iterierst doch über die Farben und erzeugst eine Linie je Farbe, wobei Du je Linie einen Endpunkt auf der Ellipsenlinie berechnest.

Möchtest du aber eine vollständige Ellipse, dann mußt Du über die Koordinaten iterieren, also z.B. über x und den jeweiligen Endpunkt berechnen, sowie die richtige Farbe dazu bestimmen.

Noch besser wäre natürlich der Polygonzug (Kreisausschnitt), oder gleich eine Füllroutine, die die Ellipse füllt und bei der Bestimmung der jeweiligen Pixelfarbe auch Interpolationen berücksichtigt, statt übereinander zu zeichnen.

1
Willibergi 
Fragesteller
 26.11.2018, 14:12
@KarlRanseierIII

Ja. Andersherum iterieren ist wohl tatsächlich die beste Lösung. Ein Polygonzug oder eine Füllroutine beißen sich leider mit dem zweiten Schritt meines Projektes, bei dem ich die Linien anders sortiere (nicht farblich).

0

Der Effekt ähnelt einem Problem, dass ich mal beim "händischen" Drehen von Bildern hatte, ohne AffineTransform zu nutzen.

Ich habe dabei fälschlicherweise die Koordinaten eines Pixels des Quellbildes, um das Zentrum gedreht, und den Pixel an den Zielkoordinaten auf die Farbe des ursprünglichen Pixels gesetzt. Klingt naheliegend, oder? Funktioniert aber nicht und ergibt viele leere Stellen, die entfernt an die leeren Bereiche deiner Ellipse erinnern.

Die Lösung war, den Pixel aus dem Zielbild entgegengesetzt (!) zu drehen, und falls diese Koordinaten innerhalb des Quellbildes lagen, die entsprechende Pixelfarbe von dort zu übernehmen.

Statt also das Quellbild im Uhrzeigersinn zu drehen, wird das Zielbild entgegen gesetzt dem Urzeigersinn gedreht.

Die Lösung war also - wie so oft in der Mathematik - das Ganze von hinten anzugehen!

Zu deinem Problem mit der Ellipse: Das kannst du lösen, indem du keine Linien mehr zeichnest, sondern Dreiecke, bei denen zwei Punkte benachbarte Linienenden am Rand sind, und der dritte Punkte im Mittelpunkt der Ellipse liegt.

Wie du den tollen Effekt mit der Rot- / Blau-Separation hinbekommen hast, weiß ich aber nicht. Sieht aber interessant aus! :)

Woher ich das weiß:eigene Erfahrung
Willibergi 
Fragesteller
 26.11.2018, 18:04

Danke für die Antwort!

Zu deinem Problem mit der Ellipse: Das kannst du lösen, indem du keine Linien mehr zeichnest, sondern Dreiecke, bei denen zwei Punkte benachbarte Linienenden am Rand sind, und der dritte Punkte im Mittelpunkt der Ellipse liegt.

Wäre eine mögliche Lösung, aber keine für mein Projekt - ich brauche definitiv Linien.

Wie du den tollen Effekt mit der Rot- / Blau-Separation hinbekommen hast, weiß ich aber nicht. Sieht aber interessant aus! :)

Das habe ich mittlerweile herausgefunden - ich Depp habe mit Degree statt Radian gerechnet.

0

Hallo Willibergi,

ich möchte mich jetzt nicht in den Code vertiefen, aber folgendes:

wahrscheinlich liegt die unschöne Darstellung daran, dass du vom Zentrum aus die Linien Richtung Ellipsenrand zeichnest und von einer Linie zur nächsten den Winkel vergrößerst.

Je weiter zwei benachbarte Linien vom Zentrum entfernt sind, umso weiter sind zwei benachbarte Punkte P(linie_1) und P(linie_2) entfernt. Dadurch entstehen "Löcher", also Pixel, auf die nicht gezeichnet wird.

Ich würde es umgekehrt versuchen: die Linien von der Ellipse ins Zentrum zeichnen. Dabei rechnest du nicht mit Winkeln, um von einer Linie zur nächsten zu gelangen, sondern du verbindest ein Pixel, das auf der Ellipse liegt, mit dem Zentrum durch eine Linie. Dann nimmst du das nächste Pixel der Ellipse und verbindest es mit dem Zentrum usw.

Dabei werden zwar einige Pixel mehrfach überzeichnet, aber es wird keine Lücken geben. Verstehst du, wie ich das meine?

Dadurch wärst du auch unabhängig von der Auflösung.

Gruß

AldoradoXYZ  25.11.2018, 20:27

Das würde auch funktionieren. Müsste man mal probieren bei welcher Lösung das Ergebnis am "schönsten" ist.

1
eddiefox  25.11.2018, 20:31
@AldoradoXYZ

Genau, wobei ich nicht weiß, welchen Farbvorstellung Willibergi hat.

Soll die Farbe auf einer Linie konstant sein, oder soll sie ein gewisses Farbspektrum durchlaufen - in Abhängigkeit von der Länge der Linie, oder...

1
AldoradoXYZ  25.11.2018, 20:32
@eddiefox

Die einzelne Linie besitzt genau eine Farbe. Genau wie im Dreieck.

Gruß

1
Willibergi 
Fragesteller
 25.11.2018, 20:33
@eddiefox

Jede Linie hat eine Farbe und die Linien nebeneinander ergeben dann die "Farbkreisellipse" mit den weich wirkenden Übergängen. Genau so wie das Dreieck oben auch, das besteht auch nur aus Linien. Nur möchte ich es eben elliptisch.

0
Willibergi 
Fragesteller
 25.11.2018, 20:31

Danke für Deine Antwort!

Oh ja, das ist kein schlechter Ansatz. Klingt nur trivialer, als er ist, einfach umgekehrt zeichnen würde ja nichts ändern. Mir erschließt sich nur gerade nicht ganz, wie ich alle Pixel der Ellipse systematisch durchgehen kann - der mathematische Ansatz, den ich verwende, dürfte ja nicht großartig anders sein... entweder stehe ich gerade selbst gewaltig auf dem Schlauch oder ich müsste die Berechnung grundsätzlich nochmal umdenken... aber der Ansatz ist top - danke!

0
AldoradoXYZ  25.11.2018, 20:36
@Willibergi

Ja, das stimmt schon mit dem "Von außen nach innen zeichnen". Das würde erstmal nichts ändern. Man sieht auf deinem Bild ja schon, dass du nicht alle Punkte des Randes "erwischt". Das muss auf jeden Fall gegeben sein, auch wenn Du die Skalierungsmethode verwendet.

Gurß

0
AldoradoXYZ  25.11.2018, 20:41
@AldoradoXYZ

Ein Problem dabei ist, dass die Anzahl der Linien bereits konstant ist (3*255). Du benötigst für größere Ellipsen mehr Linien. Das siehst Du auch daran, dass eine Ellipse (30,15) gar nicht mehr so schlimm aussieht.

Gruß

0
Willibergi 
Fragesteller
 25.11.2018, 20:41
@AldoradoXYZ

Die einzige Möglichkeit, die ich momentan sehe, ist, mit der Definition meiner Ellipse als Kurve zu rechnen und dann vom Pixel (x | k(x)) auf den Punkt (x+1 | k(x+1)) zu schließen. Dann müsste ich auf jeden Fall jeden Pixel erwischen.

0
Willibergi 
Fragesteller
 25.11.2018, 20:47
@AldoradoXYZ

Tatsache. Aber mehr Farben bekomme ich nicht, weil ich ja schon den gesamten RGB-Farbraum ausgeschöpft habe. Ich habe gerade mal versucht, den Stroke der Linien zu ändern, um zumindest einen Ansatz der Zeichnung zu sehen, aber irgendwie funktioniert auch das nicht: https://i.ibb.co/1ZBfr47/image.png

Kann es sein, dass das nicht das einzige Problem ist? Ich habe ein bisschen das Gefühl, als würden gleiche Farben nicht nebeneinander, sondern in einem bestimmten Winkelabstand in der Ellipse gezeichnet werden - zumindest sieht es auf dem Bild so aus.

0
eddiefox  25.11.2018, 20:47
@Willibergi
Klingt nur trivialer, als er ist, einfach umgekehrt zeichnen würde ja nichts ändern.

Jetzt verstehe ich.

Stimmt, das ändert nichts, wenn du weiterhin mit Winkeln rechnest.

Wenn du aber mit Pixelkoordinaten rechnest, dann verbindest du das Zentrum mit jedem Pixel der Ellipse. In der Tat ist dann egal, ob von innen nach außen oder umgekehrt. Halt "nur" den Winkel fallenlassen und nur mit den Koordinaten der Pixel, die auf der Ellipse liegen, rechnen.

0
Willibergi 
Fragesteller
 25.11.2018, 20:52
@eddiefox

Ja, das stimmt, das ist wohl die technisch bessere Lösung. Ich werde mich mal dranmachen, die Berechnung so umzuschreiben.

0

Ic bin zwar kein Java-Programmierer, es gibt jedoch in jeder grafikfähigen Programmiersprache eine PieSlice() oder PieChart funktion etc. .

Verwendest du statt Linien "Kuchenstücke" klappt es mit dem Nachbarn... auch ohne weiße Lücken.

https://stackoverflow.com/questions/15167276/drawing-slices-of-a-circle-in-java

https://docs.oracle.com/javase/tutorial/2d/overview/index.html

http://www.java2s.com/Tutorial/Java/0261__2D-Graphics/DrawingaPieChart.htm

Willibergi 
Fragesteller
 26.11.2018, 14:09

Kreisteile zu zeichnen, ist zwar grundsätzlich keine schlechte Idee, kommt aber für mein Projekt leider nicht infrage, weil ich definitiv Linien benötige. Aber trotzdem danke für die Antwort!

0