rendern "unendlich vieler" linien

Status
Nicht offen für weitere Antworten.

smuRf

Mitglied
Hey erstmal!

ich arbeite an einer applikation, die die position von funktranspondern anzeigt. sprich jemand bekommt einen transponder umgeschnallt und meine anwendung stellt durch linien den weg da, den die entsprechende(n) person(en) zurücklegen.
die anzeige ist zomm/scroll und rotierbar.

je nachdem wie lange die applikation läuft, häufen sich natürlich die linien die gezeichnet werden müssen. im schnitt bewegt sich die anzahl derer bei ~600k - 800k und das pro transponder.

die momentane lösung ist, die linien (deren anfangs und endpunkt im einem vector gespeichert sind) auf ein transparentes buffered image zu zeichnen. pro transponder existiert ein eigenes bi. es werden immer nur die "neuen" linien gezeichnet, der rest bleibt erhalten. auf der niedrigesten zoomstufe verschiebe ich beim scrollen einfach entsprechend das BI (weil alle linien draufpassen). je weiter ich reinzoome umso größer müsste das BI werden um noch alle daten fassen zu können, was natürlich speichertechnisch ein horror wird und auch nicht mehr flüssig scrollbar ist.
weiters müsste ich beim ändern der zoomstufe die kompletten linien neu rendern, was nach ein paar minuten laufzeit einfach zu lange dauert.

meine frage jetzt also, wie kann ich das ding am effizientesten rendern, sodass zoom/scrolling und rotation (in 90° schritten) flüssig dargestellt werden kann? ich hänge diesbezüglich im moment ziemlich in der luft.
klar ist, dass ich immer nur die teile im speicher haben darf, die gerad tatsächlich angezeigt werden (bei 4bytes/pixel - bi mit alphachannel wohl kaum anders machbar).

wie ich das allerdings am besten mache ist mir im moment zumindest ein rätsel.

vllt schaffts von euch ja jemand mir diesbezüglich ein wenig auf die sprünge zu helfen.

MfG,
smuRf
 

Marco13

Top Contributor
Hm - ist schwierig, das aus der Ferne wirklich hilfreiche Tipps zu geben, aber ... ist es möglich, das BufferedImage für die höchste Zoomstufe zu erstellen, und bei niedrigeren zoomstufen dann einfach verkleinert zu zeichnen? (Ein verkleinertes BufferedImage geht schneller als 600000 Linien)
 

smuRf

Mitglied
naja in der höchsten zoomstufe würde ein buffered image das die komplette "bühne" fassen kann zu groß werden (einige tausend pixel höhe und breite).

meine idee wäre gewesen soviel bi zu verwalten, dass in summe alles dargestellt werden kann, wobei ein bi einem viertel des sichtbaren bereichs entspricht (400*300).
dabei aber immer nur 16 bis zu beschreiben (4 die sichtbar sind und 8 um den sichtbaren bereich herum). alles was außerhalb liegt könnte ich flushen und nur dann die punkte ins bi schreiben, wenn es in den rand um den sichtbaren bereich rutscht.
wobei ich immer noch ein problem beim zoom hätte, da nach wie vor alles nachgezeichnet werden müsste.
 

smuRf

Mitglied
hat sonst vllt noch jemand ideen, wie das problem vernünftig zu lösen wäre?
wie gesagt, außer oben genannte varianten fällt mir leider nix mehr ein, bzw. sind schon einige versuche an geschwindigkeitsproblemen gescheitert.
 
B

Beni

Gast
Musst du unbedingt alle Linien zeichnen. Oder sind die so genau, dass es auch reicht nur jeden 10. Messpunkt zu verbinden?
 
S

Spacerat

Gast
Linien zeichnen ist ja nicht das Problem. Ob dazu mehrere BIs benötigt werden, wage ich mal zu bezweifeln. Die Speicherart der Linienverläufe in einer Collection ist meines erachtens aber schon ein Designfehler.
Mein Vorschlag: GeneralPath. Zweckmässigerweise für jeden Transponder einen. Die einzelnen GPs können dann in einer Collection (alles andere, nur nicht Vector, am besten 'ne Map) gehalten werden und bei Bedarf in einem BI gezeichnet werden.
 

smuRf

Mitglied
punkte reduzieren tu ich schon, alles was näher als 5px beieinander is, wird gleich mal "eliminiert".

die sache mit den GP hört sich schonmal gut an. aber das ändert im prinzip ja nix am ursprünglichen problem, oder?

danke btw für die antworten
 
S

Spacerat

Gast
Zum Rotieren würde mir auf die Schnelle nur AffineTransform einfallen... Damit hab' ich allerdings bisher nur wenig bis gar nicht gearbeitet. zum Zoomen: siehe Beitrag von Marco13.
 

Steev

Bekanntes Mitglied
Ich habe schon mal so etwas ähnliches gemacht. Der Trick ist ja, dass man in der Regel nur einen Abschnitt der gesammten Kurve sieht. Diesen Abschnitt habe ich dann mit einem GeneralPath, der aus etwa 200 bis 400 Nodes besteht abgebildet. Umso höher die Zoomstufe ist, umso genauer kann mit dem zur Verfügung stehenden GeneralPath die Kurve abbilden. Man muss halt die Daten irgendwo verwalten, also entweder in einem Array, oder in einer DB...
Sollte dann einmmal die gesammte Kurve angezeigt werden, so wird durch die Daten iteriert und alle X Werte ein Durchschnittswert gebildet, der dann die Höhe des entsprechenden Punktes in dem Pfad bestimmt.

Vieleicht hilft dir dabei ja der Quellcode von Audacity weiter, immerhin werden da die ziemlich komplexe Sounds als Kurve abgebildet.

Audacity: Source Code
 

newcron

Aktives Mitglied
Eine weitere idee, um punkte zu reduzieren wäre folgende:
Für jedes Segment aus den Punkten A, B, C (wobei der transponder zunächst bei A, dann bei B und dann bei C war) überprüfst du, ob B auf einer Linie mit A und C liegt, bzw. wie groß die Abweichung ist. Unterschreitet sie einen gewissen wert (der ist abhängig von deiner Zoomstufe) ignorierst du den Punkt. Ist B beim aktuellen Zoom 0.2 Pixel von der Gerade AC entfernt, dann kannst du davon ausgehen, dass der Punkt nicht existiert. Das kannst du beliebig oft wiederholen und dabei sehr effizient die Linienanzahl reduzieren.

Zusätzlich könntest du einen SceneGraph verwenden, der alle Linien kennt und dafür sorgt, dass nur die, die sich am Bildschirm befinden völlig ignoriert werden. Das bringt dir bei stärkerem Zoom zusätzliche Performance.
Es gibt diverse fertige Lösungen hierfür, ich kann dir Piccolo2D - A Structured 2D Graphics Framework empfehlen, da ich im letzten halben jahr durchaus positive Erfahrungen damit gemacht habe.
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen


Oben