Entwickler-Ecke
Algorithmen, Optimierung und Assembler - Algorithmus Traffpunkte Strahl durch 3D-Gitter => Optimie
Noop - So 20.02.05 17:24
Titel: Algorithmus Traffpunkte Strahl durch 3D-Gitter => Optimie
Erstmal zum Mathematischen "Problem":
Man stelle sich ein
3D-Gitter vor (Link zum Bild: hier klicken!) [
http://srv02623.gu2.info/bilder/3d-grid.jpg], wo ein Strahl durchgeschossen wird.
Der Strahl wird durch den Anfangspunkt
"Start" und den Endpunkt
"Stop" definiert durch der Prozedur
CalculateCollision(Start, Stop, output); berechnet und ermittelt, durch
welche gedachte Wand im 3D-Gitter und
wo in der gedachten Wand der Strahl überall auftrifft auf dem Weg von
Start nach
Stop.
Mathematisch heißt das, wann immer auf der Reise vom X-Wert, der Y-Wert oder der Z-Wert der Restwert (hinterm Komma)
0 ist, wird der Wert zur Liste der Treffpunkte hinzugefüht.
Ich habe das mit folgendem Code gelöst:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136:
| type float=extended;
PPoint3DF=^TPoint3DF; TPoint3DF=record x, y, z: single; end;
PPointCL=^TPointCL; TPointCL=record x, y, z: extended; ck:byte; end; TPointCLArray=array of TPointCL;
...
function QFrac(q:extended):extended; begin if q>=0then result:=Frac(q)else result:=1-Frac(-q); end;
function QInt(q:extended):extended; begin result:=abs(floor(q)); if q<0then result:=floor(-1-result); end;
function QSgn(q:extended):shortint; begin result:=0; if q<0then result:=-1; if q>0then result:=1; end;
function ESgn(q:extended):shortint; begin result:=0; if q>=0then result:=1; end;
function EqSgn(q,r:extended):shortint; begin result:=0; if q>=0then result:=1-result; if r>=0then result:=1-result; end;
function CalculateCollision(start,stop:TPoint3DF;var output:TPointCLArray): integer; var i:integer;r:byte; xs,ys,zs,q:extended; xp,yp,zp:extended; qx,qy,qz:extended; qd:extended; p:TPointCL; begin if (Length(output)=0) then begin result:=0; exit; end; i:=0; xs:=stop.x - start.x; ys:=stop.y - start.y; zs:=stop.z - start.z; q:=0; qd:=((Abs(xs)+Abs(ys)+Abs(zs))*1000); if qd=0 then qd:=1 else qd:=1/qd; while i<length(output) do begin q:=q+qd; xp:=start.x+xs*q; yp:=start.y+ys*q; zp:=start.z+zs*q; if xs=0then qx:=high(integer)else qx:=(QInt(xp)+1*ESgn(xs)-start.x)/xs; if ys=0then qy:=high(integer)else qy:=(QInt(yp)+1*ESgn(ys)-start.y)/ys; if zs=0then qz:=high(integer)else qz:=(QInt(zp)+1*ESgn(zs)-start.z)/zs; if(qx<=qy)and(qx<=qz)then begin q:=qx;r:=1; if q>1 then break; p.x:=start.x+xs*q; p.y:=start.y+ys*q; p.z:=start.z+zs*q; p.ck:=r;output[i]:=p;Inc(i); if i>=length(output) then Continue; if (Frac(p.y)=0) and (ys<>0) then begin p.ck:=2;output[i]:=p;Inc(i); if i>=length(output) then Continue; end; if (Frac(p.z)=0) and (zs<>0) then begin p.ck:=3;output[i]:=p;Inc(i); if i>=length(output) then Continue; end; Continue; end; if(qy<=qx)and(qy<=qz)then begin q:=qy;r:=2; if q>1 then break; p.x:=start.x+xs*q; p.y:=start.y+ys*q; p.z:=start.z+zs*q; p.ck:=r;output[i]:=p;Inc(i); if i>=length(output) then Continue; if (Frac(p.x)=0) and (xs<>0) then begin p.ck:=1;output[i]:=p;Inc(i); if i>=length(output) then Continue; end; if (Frac(p.z)=0) and (zs<>0) then begin p.ck:=3;output[i]:=p;Inc(i); if i>=length(output) then Continue; end; Continue; end; if(qz<=qx)and(qz<=qy)then begin q:=qz;r:=3; if q>1 then break; p.x:=start.x+xs*q; p.y:=start.y+ys*q; p.z:=start.z+zs*q; p.ck:=r;output[i]:=p;Inc(i); if i>=length(output) then Continue; if (Frac(p.x)=0) and (xs<>0) then begin p.ck:=1;output[i]:=p;Inc(i); if i>=length(output) then Continue; end; if (Frac(p.y)=0) and (ys<>0) then begin p.ck:=2;output[i]:=p;Inc(i); if i>=length(output) then Continue; end; Continue; end; end; result:=i; |
(
PS Sollte ich irgendeine Unterfunktion vergessen habe, meldet es
PPS Die Arraylänge von
output muss
vorher mit SetLength gesetzt werden. Diese Länge ist dann das Maximum.
)
Wie kann ich die Berechnung beschleunigen? Die scheint leider etwas langsam zu sein :(
Was könnte ich verbessern? Oder gibt welche andere (hochoptimierte) Funktion oder hochentwickeltes Prinzip soll ich verfolgen?
UGrohne - So 20.02.05 17:25
Hallo,
der Titel Deines Beitrages ist nicht aussagekräftigt genug. Man weiß nicht genau, um was es geht. Bitte ändere ihn entsprechend!
Dies kannst Du tun, indem Du in Deinem ersten Beitrag auf "Edit" klickst und den Titel dort änderst.
Dazu hier auch noch der Auszug aus den Richtlinien:
Richtlinien hat folgendes geschrieben: |
1.2 Beiträge
Bitte formuliere den Betreff Deiner Beiträge so, dass andere Mitglieder anhand dieser bereits das eigentliche Thema festmachen können. Beiträge wie etwa "Eine Anfängerfrage" oder "Weiß jemand, wie das geht?" lassen den Leser im Unklaren darüber, was das Thema der Diskussion ist. Eine Pseudocodezeile oder die Nennung des Objektes, um welches es sich in dem Beitrag handelt, helfen da schon mehr weiter. Wenn Du beispielsweise wissen möchtest, wie es möglich ist, eine Integer-Variable in das String-Format zu konvertieren, würde ein Beitrag wie etwa "Integer zu String" oder "Integerkonvertierung" anderen Forenmitgliedern einen kurzen Überblick über die eigentliche Fragestellung verschaffen. So ist es möglich gezielter Lösungen für Probleme zu finden. Zudem solltest du immer daran denken: Der Fragesteller möchte etwas von den anderen Usern - nicht umgekehrt. |
Vielen Dank
Gruß,
uwe
Spaceguide - So 20.02.05 18:24
Ich hab jetzt nicht wirklich verssucht deinen Quellcode zu analysieren (kannst du auch nicht von uns erwarten), aber wenn du einen Strahl mit einem regulären Gitter schneiden willst, kannst du wohl auch irgendeinen Linien-Algorithmus nehmen und ihn auf 3D erweitern.
Double statt Extended nehmen bringt auch ein paar Prozent ;-)
sourcehunter - So 20.02.05 18:30
So wie ich das beim Überfliegen verstanden hab, gehst du auf dem Strahl entlang, oder? Wenn du schonmal Vektorrechnug gehabt hattest(z.B. in der Schule), dann sollte dir dieses Stichwort das Problem Schnitt von Gerade und Ebene in die Gedanken rufen. Falls du daimt nichts anfangen kannst, dann frag nochmal naah, ich hab grad keine Zeit ins Detail zu gehn.
Noop - So 20.02.05 18:50
Ich hatte noch keine Vektoralgebra, aber ich weiß aber trotzdem das man Formeln zB in so einer Richtung wie diese
(Fläche)
x = x1*t + x2*s( + x3)
y = y1*t + y2*s( + y3)
z = z1*t + z2*s( + z3)
(Strahl)
x = x4 + xf*f
y = y4 + yf*f
z = z4 + zf*f
verwenden könnte.
Aber ich habe keine Idee, wie ich so eine Formel für die Suche
aller Schnittpunkte einsetzen könnte. :( (also das er nur die Punkte ausgibt, wo X, Y oder/und Z eine
ganze Zahl ist (also Int(A)=A), das sind nämlich die Punkte, die auf einer Wand im Gitter liegt)
PS was ich möchte, hab ich
als Bild [
http://srv02623.gu2.info/bilder/3d-grid.jpg] visualisiert, die bunten Flächen, also die Wände, dessen Koordinaten bin ich interessiert - nicht nur eine Wand, sondern
alle Wände, die der Strahl durchbricht von Start nach Stop
Ich Bins - So 20.02.05 20:19
Ich seh das genauso wie sourcehunter, du nimmst einfach nacheinander jede Ebene des Gitters, und guckst, ob und wenn ja in welchem Punkt, der Strahl diese Ebene schneidet. Muss man halt (denk ich mal) für jede Ebene machen, aber dürfte nicht so aufwändig sein.
BenBE - So 20.02.05 20:31
Folgende Units sollten Dir für die Schnittpunktberechnung weiterhelfen:
cvs.sourceforge.net/viewcvs.py/omorphia/omorphia/maths/OMathVector.pas
cvs.sourceforge.net/viewcvs.py/omorphia/omorphia/maths/OMathGeometry.pas
Bei Fragen zu diesen Units einfach ne PN an mich. (Und stör dich nicht an dem ASM dort ^^)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!