Mehrdimensionale Arrays?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Mehrdimensionale Arrays?

    Hi.

    Ich habe mal eine Frage.

    Ich bräuchte zur leichten 3D-Objekt-Beschreibung ein dynamisches, dreidimensionales Array welcher dann NSNumber aufnimmt.

    Kennt jemand ein Tutorial dazu wie es dann mit hinzufügen, löschen, abrufen funktioniert, oder kann mir direkt helfen?

    Danke :)
  • Du kannst dir deine drei Dimensionen aus verschachtelten NSArray-Objekten zusammenkleistern.
    Damit du nicht per

    Quellcode

    1. [[[[array objectAtIndex:3] objectAtIndex:5] objectAtIndex:5] intValue]
    zugreifen musst, kannst dir ja eine Hilfsfunktion schreiben.
    -- Hell! I've lost my adrenalin pills!
  • RE: Mehrdimensionale Arrays?

    DIe Frage wäre hier sicherlich, wie viel Daten es sind, wie sinnvoll das hier ist und ob man nicht lieber ein C-Array anlegen sollte. Denn drei Aufrufe von objectAtIndex: sind eher weniger zu empfehlen, als schnell mal ein objects[1][2][3]. Diese Typen von arrays sind dann aber eher weniger dynamisch. Man könnte es dann mit listen lösen.

    -> oder einfach das machen, was ponder vorgeschlagen hat ;)

    Max
  • RE: Mehrdimensionale Arrays?

    schon mal überlegt, für Deine 3D-Punkte einen eigen Typ anzulegen?

    Ich würde wahrscheinlich folgendes machen (ohne jetzt die Anforderungen Deines Programms zu kennen):

    Quellcode

    1. typedef struct _3dpoint {
    2. float x;
    3. float y;
    4. float z;
    5. } 3DPoint;


    Diesen Datentyp kann man dann in einfachen C-Arrays speichern und auch bequem als MethodenParameter verwenden.

    t.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • Hi.

    Danke schonmal.

    Dieses 3D-Array speichert nur den "Bauplan" des Objektes. Die Koordinaten liegen wo anders. Ich benötige nur Integer-Werte.

    Aufbau:

    Quellcode

    1. Baugruppe1->Teil1->Koord1
    2. ->Koord2
    3. ->Koord3
    4. ->Koord4
    5. ->Teil2->Koord1
    6. ->Koord2
    7. ->Koord3
    8. ->Teil3->Koord1
    9. ->Koord2
    10. ->Koord3
    11. ->Koord4
    12. ->Koord5
    13. Baugruppe2->Teil1->...
    Alles anzeigen


    Ich brauche dieses Array nur beim "Laden" des Objektes. Dort wird der Array aufgebaut. Nach dem Bau des Objektes in OpenGL wird der Array wieder gelöscht.

    Ich habe schon so etwas in C++ gemacht. Da waren es dann 3 verschachtelte vector. Finde ich nicht gerade "praktisch" oder generell übersichtlich.

    Ich wollte des dewegen mal in Objective-C probieren, wie sich das da so verhält. Ist also kein "muss".

    Gibt es denn irgendwelche Nachteile durch ein NSMutableArray, im Gegensatz zu einem vector in C++?

    Danke :)

    edit:

    Achja. Die anfallende Datenmenge. Also es können sehr viele werden. Je nach komplexität des Objektes. Als Wert sage ich mal ca. 50 000 Koordinaten können es schon sein in einem Test-Fall. Im Normalfall aber eher so bei 2000-10 000.
  • NSMutableArray dürften schlchter performen, weil die Aufrufe dynamisch gebunden werden. Wenn du das nur beim Laden brauchst, dann ist es aber nicht schlimm. Ansonsten bietet sich ein eigener Typ oder eine eigene Klasse schon an. Ich hatte früher mit so etwas auch Probleme, mache jetzt aber ganz häufig auch "Miniobjekte", da die schlechtere Performance eben letztlich durch die bessere Möglichkeit der Implementierung wieder wettgemacht wird.

    Elegenat wäre natürlich eine Subclass von NSValue, die einen initWithCVektor3 kennt. Dort könntest du dann gleich auch das Archiving unterbringen. Das dürfte allerdings nicht einfach sein. Ich habe es noch nie probiert.

    Wenn du affine Transformationen auf die Vektoren implementieren möchtes, dann bedenke bitte, dass der Vektor 4D sein muss.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • also deine Beschreibung folgend würde ich es dir so vorschlagen:

    Quellcode

    1. typedef struct _Group {
    2. Part *parts;
    3. } Group;
    4. typedef struct _Part {
    5. Point *points;
    6. } Part;
    7. typedef struct _Point {
    8. float x;
    9. float y;
    10. float z;
    11. } Point;
    Alles anzeigen

    So viel zum Modell. Du brächtest dann nur ein Array der Gruppen anlegen, z.B. so:

    Quellcode

    1. Group *groups;
    2. groups = (Group *) malloc(sizeof(Group) * count);

    Und genau so kannst du dann auch die Teile und die Punkte anlegen. Count ist hier ne einfache Int. Und vergiss nicht das free am Ende. In C gibts keinen ARP...

    Wenn du es lieber in Objective-C machen willst, dann geht das ganau so gut. Aber bei 50000 Vertices würde ich mir das nochmal überlegen. Der C-Zugriff ist denkbar einfach und extrem performant:

    Quellcode

    1. groups[a].parts[b].points[code=c].x // X- Koordinate

    in Obj-C könnte das dnan so aussehen:

    Quellcode

    1. [[[[[[groups objectAtIndex: a] parts] objectAtIndex: b] points] objectAtIndex: c] xCoordinate];

    man könnte es auch kürzer machen:

    Quellcode

    1. [[[[groups objectAtIndex: a] partAtIndex: b] pointAtIndex: c] xCoordinate];

    Aber langsamer ist es trotzdem...

    HTH

    Max
  • Die Groups und parts, also das Dynamische, würde ich auf keinen Fall mittels C-Typen machen. Dann muss man das alles selbst nachhalten. Wenn das mal nicht fehlerträchtig ist. Außerdem wird ein realloc letztlich auch nicht performanter. Ganz im Gegenteil: Was an Logik in den Cocoa-Container steckt, um gute Mem- und Speed-Perfromance zu bekommen (Kachelung, Hashing usw) dürfte man kaum ebenso nachprogrammieren können.

    Wenn es statisch bleibt, kann man es so machen. Das ist dann Tatfrage.

    Die Koordinaten, statisch, klein, übersichtlich, deuten allerdings geradezu auf ein C-Struct hin. Noch besser: C-Array. Im letzteren Falle kann man auch gleich eine for-Schleife drauflegen und gegebenenfalls die Größe (statisch) verändern.

    (Wie gesagt: Im 3D-Bereich braucht man häufig 4D-Matrizen, wenn man affine Transformationen durchführen will.)
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Tom9811
    Die Groups und parts, also das Dynamische, würde ich auf keinen Fall mittels C-Typen machen. Dann muss man das alles selbst nachhalten. Wenn das mal nicht fehlerträchtig ist.

    Ich weiß nicht, was du immer gegen C hast. Wenn man sich eine funktion add und eine remove schreibt, dann kann da nicht allzu viel passieren. Und wofür gibt es einen debugger?

    Dass es komfortablere lösungen gibt, ist mir schon klar. Aber dass obj-C da schneller ist halt ich für n gerücht.
  • Ich habe nichts gegen C. Ich programmiere ständig in C, wenn ich etwa ein "for( i = 0; i < 10; i++ )" mache.

    Aber Pointer nachhalten, dynamisch neu setzen, Reallocs, Arrays usw sind Klassiker für Bugs in C. Das kann man sich sparen. Übrigens hat man deshalb ja in C verkettete Listen genommen, weil es eben unperformant ist, wenn man realloziert. Aber sich verkettete Listen programmieren mit indiziertem Zugriff drauf, muss man doch nun wirklich nicht machen. Und das programmiert sich performant dann eben doch nicht an einem Nachmittag.

    BTW: Im Debugger findest du nur Fehler die du entweder ahnst oder die gleich auftreten. Leider ist es aber gerade bei den obigen Dingen häufig so, dass man erst viel später an einer anderen Stelle im Programm bemerkt, dass etwas schief gelaufen ist. Und dann hilft dir der Debugger wenig. Denk nur daran, dass er versehentlich über das Array hinausläuft (bemerkt man in C nicht) und sich etwas zerbritzelt. Dann wundert er sich später, warum ein Textfeld grün angezeigt wird statt schwarz.

    Fröhliche Fehlersuche!
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Schon. Hast schon recht.

    Aber hast du es denn wirklich schonmal gemacht? Hast du wirklich schonmal eine Pointerorgie gefeiert und ne doppelt verkettete Liste mit Accessoren usw. in C geschrieben? Wenn ja will ich nichts gesagt haben, wenn nein dann solltest du nicht so schnell über Fehler urteilen. Ich hab sowas schon öfters gemacht und hatte noch nie ne stundenlange suche nach problemen. Was bei Cocoa ganz anders ist. Irgendwo tritt da plötzlich ein Speicherloch oder ein Crash auf und jetzt fragt man sich natürlich, wo es herkommt. So eine Suche dauert bei mir immer wesentlich länger als nach Fehlern in meiner C-Syntax.

    Aber ich will mich nicht schon wieder darüber streiten. Du magst es halt lieber high-level, ich mach es aber auch gerne mal low-level.

    Max
  • Vorallem im 3D-Bereich ziehe ich oft reines C der objektorientierten Ansatz vor. Da ist viel an Performance rauszuholen und die Zeit, welche man mit Debuggen und Fehlersuchen verbringt macht das bei langem wett. Klar ist es sinnvoll die Klassen von Apple zu benutzen, wenn es um kleine Tools geht, welche nicht riesige verschachtelte Algorithmen verwenden. Trotzdem ist es auch schön, nach erfolgreicher Programmierung von effizientem Code sich zurücklehnen zu können und einfach zuzusehen, wie es flutscht. :)
    -- Hell! I've lost my adrenalin pills!
  • [Polemik]
    Ja? Wie groß ist denn der Performanceunterschied bei dem einfügen eines weiteren Elementes in ein C-Array bzw. ein NSMutableArray? Ich meine, wieviel schlechter schneidet denn da das C-Array mit seinem realloc ab? mal ganz abgesehen davon, dass das ganze Programm bei der Speicherzerstückelung langsamer wird. (Mehr Lücken -> mehr Auslagerung). Bei statischen Sachen stimmt das. Bei dynamischen wage ich schwer zu bezweifeln, dass ein C-Array beim Einfügen schneller ist. Beim Abholen wird es so sein.

    Ich meine jedoch, dass man bei dynamischen Angelgenheiten in C kein Array nimmt. Ich habe es jedenfalls nie so gemacht, weil das schlecht performiert und die Software sich dann vor allem als Festplatte ndauertest eignet. Bei einer verketteten Liste wird wieder das Abholen langsamer, weshalb man Hashes verwendet. Außerdem zerbritzelt auch das den Speicher, weshalb ich jedenfalls verkettete Listen in Array-Kacheln untergebracht habe, was auch wiederum das Abholen beschleunigte, da ich nur durch eine einzelne Kachel iterieren musste. So war jedenfalls mein Stand der C-Technik, als ich mich damit noch herumgeplagt habe. Und bei Apps mit einigen 100.000 LOC war das eine Plage mit biblischen Ausmaßen.

    Nun, nachdem du endlich nach Wochen eine solch performantes C-Array implementiert hast, wirst du etwas Schreckliches bemerken. Alle diese Dinge sind bereits in NSMutableArray implementiert ...

    Natürlich hat ein C-Array etwas Mutiges, so dass man stolz sein kann es gebändigt zu haben. Bei mir läuft das allerdings eher in der Kategorie "Ich freue mich immer, wenn der Schmerz nachlässt." ;)
    [/Polemik]
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Tom9811
    Ja? Wie groß ist denn der Performanceunterschied bei dem einfügen eines weiteren Elementes in ein C-Array bzw. ein NSMutableArray? Ich meine, wieviel schlechter schneidet denn da das C-Array mit seinem realloc ab? mal ganz abgesehen davon, dass das ganze Programm bei der Speicherzerstückelung langsamer wird. (Mehr Lücken -> mehr Auslagerung)

    Natürlich hat ein C-Array etwas Mutiges, so dass man stolz sein kann es gebändigt zu haben. Bei mir läuft das allerdings eher in der Kategorie "Ich freue mich immer, wenn der Schmerz nachlässt." ;-)


    Speicherzerstückelung, wie Du es nennst, trifft eher auf den Cocoa-Fall mit NSMutableArray zu.

    Du vergißt anscheinend, daß jedes Objekt, daß einem NSMutableArray hinzugefügt wird, selbst einmal im Heap alloziert werden muß. Ich sehe da vom Prinzip kaum einen Unterschied zu einer LinkedList in C. Und wenn ich die Capacity eines NSMutableArray zu klein wähle, dann muß auch dessen Speicherpool realloziert werden.

    Die Zwei Fälle im Vergleich:

    1.) Ein C-struct für 3D-Punkte (wie oben gepostet):
    man alloziert 1-mal ein array für 3dpunkte.

    Quellcode

    1. Punkt *punktarray = malloc(sizeof(Punkt) * 10000);

    Eine Speicherallozierung; die einzelnen Werte können dann ganz einfach und kostengünstig mit

    Quellcode

    1. punktarray[0].x = 10.5; // etc
    belegt werden.
    Für den letzten Index und die Kapazität brauche ich dann noch jeweils einen int.
    Wenn die Grenze bekannt ist, kann man das sogar auf dem Stack machen.

    2.) Eine NSObject-subclass für 3d-punkte und ein Mutable Array:
    JEDER einzelne Punkt muß mit alloc init erzeugt werden. Das läuft auf 10001 malloc-Aufrufen raus.
    Statt einfachen Wertzuweisungen, 10000 mal x Funktionsaufrufe.

    Wenn Variante 1 einmal realloziert werden muß, ist das immer noch um ein saftiges Stück schneller als 2 ohne realloc.

    Für jemanden, der Halbwegs C beherrscht, besteht zwischen Variante 1 und 2 auch kein Unterschied im Programmieraufwand. Beides ist genau so schnell ausprogrammiert. Variante 1 hat absolut nichts mit Mut zu tun. Das ist simples basic C in ganz einfach überschaubarer Form.

    Einen Aspekt habe ich hierbei noch außer Acht gelassen, da zweischneidig. Für eine NSObject-Klasse wird noch etwas mehr Speicher benötigt; Zumindest kommt der isa-Pointer hinzu (= 16 byte in toto). für ein struct, bestehend aus drei float werden nur 12 byte benötigt. Die Differenz _kann_ sich summieren. Ein Auffüllen auf 16 byte beim struct kann allerdings wegen besseren Alignments wiederum auch sinnvoll sein...

    t.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • Ich sehe das auch so, dass ein NSMutableArray in etwa vom Verhalten einer verketteten Liste in C entspricht. Deshalb habe ich das ja auch geschrieben:

    Weggekürtzter Teil meines Beitrages im Original:
    Ich meine jedoch, dass man bei dynamischen Angelgenheiten in C kein Array nimmt. Ich habe es jedenfalls nie so gemacht, weil das schlecht performiert und die Software sich dann vor allem als Festplatte ndauertest eignet. Bei einer verketteten Liste wird wieder das Abholen langsamer, weshalb man Hashes verwendet. Außerdem zerbritzelt auch das den Speicher, weshalb ich jedenfalls verkettete Listen in Array-Kacheln untergebracht habe, was auch wiederum das Abholen beschleunigte, da ich nur durch eine einzelne Kachel iterieren musste. So war jedenfalls mein Stand der C-Technik, als ich mich damit noch herumgeplagt habe. Und bei Apps mit einigen 100.000 LOC war das eine Plage mit biblischen Ausmaßen.

    Nun, nachdem du endlich nach Wochen eine solch performantes C-Array implementiert hast, wirst du etwas Schreckliches bemerken. Alle diese Dinge sind bereits in NSMutableArray implementiert ...


    Ferner habe ich bereits geschrieben, dass bei statischen Angelegenheiten C-Arrays besser sind. 3D-Punkte sind statisch, da keine Dimensionen hinzugefügt werden:

    Weggekürtzter Teil meines Beitrages
    Bei statischen Sachen stimmt das.


    und vorher schonmal:
    Die Koordinaten, statisch, klein, übersichtlich, deuten allerdings geradezu auf ein C-Struct hin. Noch besser: C-Array. Im letzteren Falle kann man auch gleich eine for-Schleife drauflegen und gegebenenfalls die Größe (statisch) verändern.


    BTW: Ich finde es nicht ok, wenn du meine Beiträge kürzt und das nicht zumindest kenntlich machst.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Tom9811

    Ferner habe ich bereits geschrieben, dass bei statischen Angelegenheiten C-Arrays besser sind. 3D-Punkte sind statisch, da keine Dimensionen hinzugefügt werden:

    Weggekürtzter Teil meines Beitrages
    Bei statischen Sachen stimmt das.



    Frage: Was meinst Du mit statisch? Und was mit 'Dimensionen hinzufügen'?

    BTW: Ich finde es nicht ok, wenn du meine Beiträge kürzt und das nicht zumindest kenntlich machst.


    Ich kürze Zitate i.d.R. gewissenhaft (allerdings normalerweise ohne Auslassungszeichen). Und zwar so, daß der Sinn nicht entstellt wird, aber kurz und prägnant der Statz, auf den ich Bezug nehmen will, noch einmal ercheint, um mir und anderen den Einstieg in meine Antwort zu erleichtern.
    Hier ist jetzt ein spezialgelagerter Sonderfall eingetreten. Ich habe etwas zitiert, was jetzt so nicht mehr in Deinem Text steht.
    Ich habe Deinen Text gelesen und per Zitat auf diesen geantwortet. Während ich meine Antwort geschrieben habe, hast Du offensichtlich Deinen Text noch einmal ediert und verändert. Das, was ich zitiert habe, ist das, was ich gelesen habe, und zwar, wenn ich mich recht erinnere, sogar ungekürzt. Die Unterschiede Zwischen dem Zitat und Deinem Text sind ein Zufallsprodukt von Zeit und Technik.
    Mir ist das nach dem Erstellen meiner Antwort auch selbst schon aufgefallen und ich hätte noch in einem Edit darauf hingewiesen. Ich habe das hiermit getan.

    t.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • Ah, wenn das ein Zugriffsproblem war, entschuldige ich mich für den Vorwurf. Sorry 4 that!

    Ich hatte mich auch etwas bei dir gewundert, weil du eigentlich hier oofensichtlich zu denjenigen gehörst, die das wegen Sachkunde nicht nötig haben. Nochmal: Sorry 4 that!

    Ich meine mit dynamisch, dass sich die Größe des Containers nicht mehr ändert. Bei einem Vektor in einer 3D-Welt habe ich fix 3 (eigentlich 4) Komponenten. Das ist statisch. Dann brauche ich keinen Overhead, keine Kontrolle, keine Optimierung.

    Bei den Parts und Groups gehe ich alelrdings davon aus, dass diese sich dynamisch verhalten. Da komme ich mit C-Arrays nicht wirklich weiter. In der Tat macht das auch keiner so, sondern nimmt gekachelte verkettete Listen. Das macht auch NSMutableArray, wenn ich das richtig sehe. Letztlich lande ich also da, wo ich bei einer guten C-Implementierung auch wäre.

    Richtig, es bleibt noch Overhead übrig für die eigentlich Klassenstruktur. Das ist dann aber im Vergleich gering. Oder anders gesagt: Wenn man ein NSMutableArray mit einem einfachen statischen C-Array vergleicht, performiert letzteres natürlich besser. Eionfach deshalb, weil es weniger kann.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Hi.

    Ähm, ja.... neee.... oder doch? OK... oder? Neee... ja...doch...nein...

    ;)
    Ich weiß gerade wirklich nicht worauf ihr hinaus wollt...

    Also wie ich bereits sagte, speichere ich in diesem 3D-Array nicht die Koordinaten, sondern NUR den Bauplan (int Werte). Also die Index-Werte eines anderen Arrays, welcher die Koordinaten enthält.

    Aus diesem Array bastel ich mir dann die OpenGL-Objekte und dann kann das Array auch wieder aus dem Speicher verschwinden...
  • Original von -Nuke-
    Ähm, ja.... neee.... oder doch? OK... oder? Neee... ja...doch...nein...

    ;)
    Ich weiß gerade wirklich nicht worauf ihr hinaus wollt...


    Mußt Du auch nicht. Ist nur das übliche OffTopic-Prinzipiengeplänkel zwischen alten Bekannten ;)

    Aus diesem Array bastel ich mir dann die OpenGL-Objekte und dann kann das Array auch wieder aus dem Speicher verschwinden...


    Wozu der Zwischenschritt? Hat der einen bes. Grund?

    t.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?