Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   [Mathematik] Suche Vektoren für Körper (https://www.delphipraxis.net/168035-%5Bmathematik%5D-suche-vektoren-fuer-koerper.html)

Codewalker 1. Mai 2012 20:56

[Mathematik] Suche Vektoren für Körper
 
Hallo zusammen.

Ich muss etwas mit räumlichen Körpern programmieren. Das eigentliche Problem ist soweit gelöst, aber ich bin dabei über ein mathematisches Problem gestoßen, wo ich nicht weiterkomme und auch Tante Google nichts brauchbares ausspuckt. Ich hoffe, hier finden sich einige mit passenden Mathekenntnissen.

Es geht um folgendes: Wie komme ich bei räumlichen Körpern (Pyramide, 8-Flächenkörper (Oktaeder), 10-Flächenkörper (??), 12-Flächenkörper (Dodekaeder), 20-Flächenkörper (Ikosaeder)) auf die Vektoren, die vom Körpermittelpunkt jeweils in Richtung der Mittelpunkte der Flächen zeigen?
Beispiel: Ich suche bei Ikosaeder nach genau 20 Vektoren, von denen jeder die Richtung beschreibt, vom Körpermittelpunkt zum Mittelpunkt jeweils einer der Flächen.

Namenloser 1. Mai 2012 21:06

AW: [Mathematik] Suche Vektoren für Körper
 
Hast du denn die Punkte zu einer Fläche gegeben? Falls ja, dann kannst du einfach koordinatenweise den „Mittelwert“ berechnen (m.x = (p_1.x + p_2.x + ... + p_n.x)/n; m.y = (p_1.y + p_2.y + ... + p_n.y)/n), um den Mittelpunkt der Fläche zu bekommen und dann die Differenz zum Mittelpunkt des Körpers berechnen. Sorry falls das am Thema vorbeigeht...

Codewalker 1. Mai 2012 21:07

AW: [Mathematik] Suche Vektoren für Körper
 
Nein, ich weiß nur was es für ein Körper ist, wo der Mittelpunkte ist und theoretisch die Skalierung

Namenloser 1. Mai 2012 21:15

AW: [Mathematik] Suche Vektoren für Körper
 
Vielleicht hilft dir dieses PDF.

Codewalker 1. Mai 2012 21:19

AW: [Mathematik] Suche Vektoren für Körper
 
Danke für den Link. Da steht schon mal eine Menge drin, aber das einzige ähnliche sind die Vektoren für die Vertices. Evtl. kann ich mir daraus was stricken und von den Ecken jeweils auf die Flächen schließen.

Ich wäre trotzdem interessiert, wenn jemand für sowas Formeln oder Lösungen zur Hand hat :thumb:

Aphton 1. Mai 2012 21:28

AW: [Mathematik] Suche Vektoren für Körper
 
Willst du den Richtungsvektor jeweils vom Ursprung zu den einzelnen Flächen des Körpers ermittelnt oder den Vektor mit korrektem Abstand (also normaler Vektor vom Ursprung bis zum Mittelpunkt einer Fläche)?

Fürs erstere gibts bestimmt schon ne Lösung.. ich würd mir dann gedanken darüber machen, aber erst mal warte ich auf deine Antwort.

Codewalker 1. Mai 2012 21:30

AW: [Mathematik] Suche Vektoren für Körper
 
Die Länge des Vektors ist für mich erstmal irrelevant, mir reicht also lediglich die Richtung. Ich wollte mit einem Vektor der Länge 1 arbeiten, den kann ich bei Bedarf dann entsprechend skalieren, falls nötig

Aphton 1. Mai 2012 21:44

AW: [Mathematik] Suche Vektoren für Körper
 
Ok, mein erster Gedanke dazu ist/war:
mit der Kugelformel rumspielen und die einzelnen Eckpunkte ermitteln (diese sind dann auch die gewollten Richtungsvektoren)

Bin mir aber noch nicht sicher, ob das so klappen würde. Weiß nicht, ob man damit wirklich all diese Körper darstellen lassen kann.

[Edit] Ein anderer sollte vorher das klarstellen, bevor du das einsetzt [/Edit]

Formel (Wiki)

[Edit]
Ach, man kann die Formel nicht lesen.
x = sin(w1) * cos(w2)
y = sin(w1) * sin(w2)
z = cos(w1)
[/Edit]

Du müsstest hier bei die Kugel horizontal und vertikal jeweils in Slices (bei der Skizze mit Stacks und Slices versehen) unterteilen (dementsprechende Winkel verwenden, sofern das noch verständlich ist)
Skizze (Quelle)

jfheins 1. Mai 2012 22:26

AW: [Mathematik] Suche Vektoren für Körper
 
Also ich fürchte, das musst du "per Hand" einprogrammieren als Konstante.

Bei einem Ikosaeder (als Bsp.) habe ich die Formel für die Eckpunkte gefunden ( http://www.matheboard.de/thread.php?...1817#post61817 )
Daraus kannst du dann die Vektoren zu den Flächenmittelpunkten errechnen. (Der Mittelwert aus Eckpunkten einer Fläche ist der Vektor zum Flächenmittelpunkt)

Eine einfache Lösung wie "Dodekaeder" rein, Koordinaten raus wird's wohl nicht geben. Das wird vermutlich auf große, konstante Arrays im Code hinauslaufen ;-)
(Vielleicht lässt sich da noch was sparen, weil die Teile alle zwei Symmetrieebenen oder so haben, aber ob's das dann bringt weiß ich nicht)

Codewalker 2. Mai 2012 08:11

AW: [Mathematik] Suche Vektoren für Körper
 
Zitat:

Zitat von jfheins (Beitrag 1164471)
Also ich fürchte, das musst du "per Hand" einprogrammieren als Konstante.
Eine einfache Lösung wie "Dodekaeder" rein, Koordinaten raus wird's wohl nicht geben. Das wird vermutlich auf große, konstante Arrays im Code hinauslaufen ;-)

So groß werden die Arrays nicht, halt beim Dodekaeder 12 Einträge, beim Ikosaeder halt 20, etc.
Und ich würde vom Grundkörper ausgehen, d.h. ohne Rotationen, Verschiebungen oder Skalierungen. Damit dürfte die Lösung meines Erachtens eindeutig bleiben, wenn ich von normierten Vektoren ausgehe.

Bjoerk 2. Mai 2012 12:26

AW: [Mathematik] Suche Vektoren für Körper
 
Zuerst ermittelst du dir mit einer Polyeder-Routine den Mittelpunkt M des räumlichen Körpers. Danach für jede Begrenzungsfläche den Mittelpunkt S2(i) am ebenen Ersatzsystem (N-Eck). Da der Schwerpunkt der Flächen in den jeweiligen Ebenen liegt, sollte die Transformation in die wirkliche räumliche Lage S3(i) nicht so schwierig sein. Deine Vektoren sind dann M, S3(i).

// Edit: Muss suchen.. Wenn ich was finde, poste ich was.

Bjoerk 3. Mai 2012 14:58

AW: [Mathematik] Suche Vektoren für Körper
 
Ich hab' bezüglich der Transformation nichts gefunden, nur eine alte Studienarbeit (Polyeder). Interessiert dich das?

Codewalker 3. Mai 2012 16:36

AW: [Mathematik] Suche Vektoren für Körper
 
Da ich in meinen Berechnungen die Tranformation, Rotation und Skalierung ignorieren kann .... JA, Interesse ist da

Bjoerk 3. Mai 2012 17:59

AW: [Mathematik] Suche Vektoren für Körper
 
Exklusiv für die DP von DOS Basic nach Delphi gestern umgeschrieben. :)

Nicht groß getestet, sollte aber funktionieren.

Delphi-Quellcode:
unit uPolyeder; // (c) 28.04.1985, 2.05.2012 Thomas Abel, Edgar Zocher

interface

uses
  SysUtils, Dialogs;

const
  MaxPoints = 500; // NEck (Sprich N-Eck), Polyeder
  MaxBegrenzungsEbenen = 50; // Polyeder
  MaxPointsJeBegrenzungsEbene = 20; // Polyeder

type
  TD2Point = record
    X, Y: double;
  end;
  TD2Points = array [0..MaxPoints] of TD2Point; // Siehe auch CloseNEck

  TNEck = class
  private
    FCount: integer; // Anzahl der Punkte
    FPoints: TD2Points;
    function Determinante(const I: integer): double;
    procedure CloseNEck;
    function GetPoint(Index: integer): TD2Point;
    procedure SetPoint(const Index: integer; const X, Y: double);
    procedure PutPoint(Index: integer; const Value: TD2Point);
  public
    property Points[Index: integer]: TD2Point read GetPoint write PutPoint;
    property Count: integer read FCount;
    procedure Clear;
    procedure AddPoint(const X, Y: double); overload;
    procedure AddPoint(const Index: integer); overload;
    procedure DelPoint(const Index: integer);
    procedure InsPoint(const Index: integer; const X, Y: double);
    function Schwerpunkt: TD2Point;
    function Flaeche: double;
    constructor Create;
  end;

  TD3Point = record
    X, Y, Z: double;
    Exist: boolean;
  end;
  TD3Points = array [0..MaxPoints - 1] of TD3Point;

  TBegrenzungsEbene = record
    Count: integer;
    PointNumbers: array [0..MaxPointsJeBegrenzungsEbene - 1] of integer;
    procedure AddPointNumber(const Value: integer);
    procedure DelPointNumber(const Index: integer);
    procedure InsPointNumber(const Index, Value: integer);
    procedure Clear;
  end;
  TBegrenzungsEbenen = array [0..MaxBegrenzungsEbenen - 1] of TBegrenzungsEbene;
  TPolyederPoints = array [1..3, 1..3] of double;

  TPolyeder = class
  private
    FN: integer; // Anzahl der BegrenzungsEbenen
    FCount: integer; // Anzahl der Punkte
    FPoints: TD3Points;
    FEbenen: TBegrenzungsEbenen;
    function Determinante(const U, V, W: integer): double;
    function PolyederPoints(const U, V, W: integer): TPolyederPoints;
    function GetBegrenzungsEbene(Index: integer): TBegrenzungsEbene;
    function GetPoint(Index: integer): TD3Point;
    procedure SetPoint(const Index: integer;
      const X, Y, Z: double; const Exist: boolean);
    procedure PutPoint(Index: integer; const Value: TD3Point);
    procedure PutBegrenzungsEbene(Index: integer;
      const Value: TBegrenzungsEbene);
  public
    property Points[Index: integer]: TD3Point read GetPoint write PutPoint;
    property Ebenen[Index: integer]: TBegrenzungsEbene
      read GetBegrenzungsEbene write PutBegrenzungsEbene;
    property Count: integer read FCount;
    property N: integer read FN;
    procedure Clear;
    procedure AddPoint(const X, Y, Z: double);
    procedure DelPoint(const Index: integer);
    procedure InsPoint(const Index: integer; const X, Y, Z: double);
    procedure AddBegrenzungsEbene(const PointNumbers: array of integer);
    procedure DelBegrenzungsEbene(const Index: integer);
    procedure InsBegrenzungsEbene(const Index: integer;
      const PointNumbers: array of integer);
    function Schwerpunkt: TD3Point;
    function Volumen: double;
    constructor Create;
  end;

implementation

{ NEck }

function TNEck.GetPoint(Index: integer): TD2Point;
begin
  Result:= FPoints[Index];
end;

procedure TNEck.PutPoint(Index: integer; const Value: TD2Point);
begin
  FPoints[Index]:= Value;
end;

procedure TNEck.SetPoint(const Index: integer; const X, Y: double);
begin
  FPoints[Index].X:= X;
  FPoints[Index].Y:= Y;
end;

procedure TNEck.AddPoint(const X, Y: double);
begin
  Inc(FCount);
  SetPoint(FCount - 1, X, Y);
end;

procedure TNEck.AddPoint(const Index: integer);
begin
  AddPoint(FPoints[Index].X, FPoints[Index].Y);
end;

procedure TNEck.DelPoint(const Index: integer);
var
  I: integer;
begin
  for I:= Index to FCount - 2 do
    FPoints[I]:= FPoints[I + 1];
  Dec(FCount);
end;

procedure TNEck.InsPoint(const Index: integer; const X, Y: double);
var
  I: integer;
begin
  Inc(FCount);
  for I:= FCount - 1 downto Index + 1 do
    FPoints[I]:= FPoints[I - 1];
  SetPoint(Index, X, Y)
end;

function TNEck.Determinante(const I: integer): double;
begin
  Result:= FPoints[I].X * FPoints[I + 1].Y - FPoints[I].Y * FPoints[I + 1].X;
end;

procedure TNEck.CloseNEck;
begin
  FPoints[FCount].X:= FPoints[0].X;
  FPoints[FCount].Y:= FPoints[0].Y;
end;

function TNEck.Flaeche: double;
var
  I: integer;
begin
  Result:= 0;
  CloseNEck;
  for I:= 0 to FCount - 1 do
    Result:= Result + Determinante(I) / 2;
end;

function TNEck.Schwerpunkt: TD2Point;
var
  I: integer;
begin
  Result.X:= 0;
  Result.Y:= 0;
  CloseNEck;
  for I:= 0 to FCount - 1 do
  begin
    Result.X:= Result.X + (FPoints[I].X + FPoints[I + 1].X) * Determinante(I) / 6;
    Result.Y:= Result.Y + (FPoints[I].Y + FPoints[I + 1].Y) * Determinante(I) / 6;
  end;
  Result.X:= Result.X / Flaeche;
  Result.Y:= Result.Y / Flaeche;
end;

procedure TNEck.Clear;
begin
  FCount:= 0;
end;

constructor TNEck.Create;
begin
  inherited Create;
  Clear;
end;

{ TBegrenzungsEbene }

procedure TBegrenzungsEbene.Clear;
begin
  Count:= 0;
end;

procedure TBegrenzungsEbene.AddPointNumber(const Value: integer);
begin
  Inc(Count);
  PointNumbers[Count - 1]:= Value;
end;

procedure TBegrenzungsEbene.DelPointNumber(const Index: integer);
var
  I: integer;
begin
  for I:= Index to Count - 2 do
    PointNumbers[I]:= PointNumbers[I + 1];
  Dec(Count);
end;

procedure TBegrenzungsEbene.InsPointNumber(const Index, Value: integer);
var
  I: integer;
begin
  Inc(Count);
  for I:= Count - 1 downto Index + 1 do
    PointNumbers[I]:= PointNumbers[I - 1];
  PointNumbers[Index]:= Value;
end;

{ TPolyeder }

function TPolyeder.GetPoint(Index: integer): TD3Point;
begin
  Result:= FPoints[Index];
end;

procedure TPolyeder.PutPoint(Index: integer; const Value: TD3Point);
begin
  FPoints[Index]:= Value;
end;

procedure TPolyeder.SetPoint(const Index: integer;
  const X, Y, Z: double; const Exist: boolean);
begin
  FPoints[Index].X:= X;
  FPoints[Index].Y:= Y;
  FPoints[Index].Z:= Z;
  FPoints[Index].Exist:= Exist;
end;

procedure TPolyeder.AddPoint(const X, Y, Z: double);
begin
  Inc(FCount);
  SetPoint(FCount - 1, X, Y, Z, true);
end;

procedure TPolyeder.DelPoint(const Index: integer);
var
  I: integer;
begin
  for I:= Index to FCount - 2 do
    FPoints[I]:= FPoints[I + 1];
  FPoints[FCount - 1].Exist:= false;
  Dec(FCount);
end;

procedure TPolyeder.InsPoint(const Index: integer; const X, Y, Z: double);
var
  I: integer;
begin
  Inc(FCount);
  for I:= FCount - 1 downto Index + 1 do
    FPoints[I]:= FPoints[I - 1];
  SetPoint(Index, X, Y, Z, true);
end;

function TPolyeder.GetBegrenzungsEbene(Index: integer): TBegrenzungsEbene;
begin
  Result:= FEbenen[Index];
end;

procedure TPolyeder.PutBegrenzungsEbene(Index: integer;
  const Value: TBegrenzungsEbene);
begin
  FEbenen[Index]:= Value;
end;

procedure TPolyeder.AddBegrenzungsEbene(const PointNumbers: array of integer);
var
  I: integer;
begin
  Inc(FN);
  for I:= 0 to Length(PointNumbers) - 1 do
    FEbenen[FN - 1].AddPointNumber(PointNumbers[I]);
end;

procedure TPolyeder.DelBegrenzungsEbene(const Index: integer);
var
  I: integer;
begin
  for I:= Index to FN - 2 do
    FEbenen[I]:= FEbenen[I + 1];
  Dec(FN);
end;

procedure TPolyeder.InsBegrenzungsEbene(const Index: integer;
  const PointNumbers: array of integer);
var
  I: integer;
  Value: TBegrenzungsEbene;
begin
  Value.Clear;
  for I:= 0 to Length(PointNumbers) - 1 do
    Value.AddPointNumber(PointNumbers[I]);
  Inc(FN);
  for I:= FN - 1 downto Index + 1 do
    FEbenen[I]:= FEbenen[I - 1];
  FEbenen[Index]:= Value;
end;

function TPolyeder.PolyederPoints(const U, V, W: integer): TPolyederPoints;
begin
  if not FPoints[U].Exist then
    raise Exception.Create('Punkt '+IntToStr(U) + ' existiert nicht.');
  if not FPoints[V].Exist then
    raise Exception.Create('Punkt '+IntToStr(V) + ' existiert nicht.');
  if not FPoints[W].Exist then
    raise Exception.Create('Punkt '+IntToStr(W) + ' existiert nicht.');
  Result[1, 1]:= FPoints[U].X;
  Result[2, 1]:= FPoints[U].Y;
  Result[3, 1]:= FPoints[U].Z;
  Result[1, 2]:= FPoints[V].X;
  Result[2, 2]:= FPoints[V].Y;
  Result[3, 2]:= FPoints[V].Z;
  Result[1, 3]:= FPoints[W].X;
  Result[2, 3]:= FPoints[W].Y;
  Result[3, 3]:= FPoints[W].Z;
end;

function TPolyeder.Determinante(const U, V, W: integer): double;
var
  P: TPolyederPoints;
begin
  P:= PolyederPoints(U, V, W);
  Result:= P[1, 1] * (P[2, 2] * P[3, 3] - P[3, 2] * P[2, 3])
    - P[2, 1] * (P[1, 2] * P[3, 3] - P[3, 2] * P[1, 3])
    + P[3, 1] * (P[1, 2] * P[2, 3] - P[2, 2] * P[1, 3]);
end;

function TPolyeder.Volumen: double;
var
  I, J, U, V, W: integer;
  E: TBegrenzungsEbene;
begin
  Result:= 0;
  for I:= 0 to FN - 1 do
  begin
    E:= FEbenen[I];
    U:= E.PointNumbers[0];
    V:= E.PointNumbers[1];
    for J:= 2 to E.Count - 1 do
    begin
      W:= E.PointNumbers[J];
      Result:= Result + Determinante(U, V, W) / 6;
      V:= W;
    end;
  end;
end;

function TPolyeder.Schwerpunkt: TD3Point;
var
  I, J, U, V, W, k1, k2: integer;
  E: TBegrenzungsEbene;
  M: array [1..3] of double;
  T: double;
  P: TPolyederPoints;
begin
  for k1:= 1 to 3 do
    M[k1]:= 0;
  for I:= 0 to FN - 1 do
  begin
    E:= FEbenen[I];
    U:= E.PointNumbers[0];
    V:= E.PointNumbers[1];
    for J:= 2 to E.Count - 1 do
    begin
      W:= E.PointNumbers[J];
      P:= PolyederPoints(U, V, W);
      for k1:= 1 to 3 do
      begin
        T:= 0;
        for k2:= 1 to 3 do
          T:= T + P[k1, k2];
        M[k1]:= M[k1] + Determinante(U, V, W) / 24 * T;
      end;
      V:= W;
    end;
  end;
  Result.X:= M[1] / Volumen;
  Result.Y:= M[2] / Volumen;
  Result.Z:= M[3] / Volumen;
end;

procedure TPolyeder.Clear;
var
  I: integer;
begin
  FCount:= 0;
  FN:= 0;
  for I:= 0 to MaxBegrenzungsEbenen - 1 do
    FEbenen[I].Clear;
  for I:= 0 to MaxPoints - 1 do
    FPoints[I].Exist:= false;
end;

constructor TPolyeder.Create;
begin
  inherited Create;
  Clear;
end;

end.
Delphi-Quellcode:
unit PolyederUnit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, uPolyeder;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  ANEck: TNEck;
begin
  ANEck:= TNEck.Create;
  try
    // Vorhandene Flächen mathematisch positiv umfahren
    ANEck.AddPoint(0, 0);
    ANEck.AddPoint(10, 0);
    ANEck.AddPoint(10, 5);
    ANEck.AddPoint(0, 5); // Nr. 3

    // Aussparungen mathematisch negativ umfahren
    ANEck.AddPoint(1, 4); // Nr. 4
    ANEck.AddPoint(9, 4);
    ANEck.AddPoint(9, 1);
    ANEck.AddPoint(1, 1);
    ANEck.AddPoint(4); // Teilfläche schließen
    ANEck.AddPoint(3); // Aussparung schließen

    ShowMessage(FloatToStr(ANEck.Flaeche));

    ShowMessage(FloatToStr(ANEck.Schwerpunkt.X));
    ShowMessage(FloatToStr(ANEck.Schwerpunkt.Y));
  finally
    ANEck.Free;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  APolyeder: TPolyeder;
begin
  APolyeder:= TPolyeder.Create;
  try
    APolyeder.AddPoint(0, 0, 0);
    APolyeder.AddPoint(10, 0, 0);
    APolyeder.AddPoint(10, 5, 0);
    APolyeder.AddPoint(0, 5, 0);
    APolyeder.AddPoint(10, 5, 20);

    // Begrenzungsflächen mathematisch positiv umfahren
    APolyeder.AddBegrenzungsEbene([0, 1, 4]);
    APolyeder.AddBegrenzungsEbene([1, 2, 4]);
    APolyeder.AddBegrenzungsEbene([2, 3, 4]);
    APolyeder.AddBegrenzungsEbene([3, 0, 4]);
    APolyeder.AddBegrenzungsEbene([0, 3, 2, 1]);

    ShowMessage(FloatToStr(APolyeder.Volumen));

    ShowMessage(FloatToStr(APolyeder.Schwerpunkt.X));
    ShowMessage(FloatToStr(APolyeder.Schwerpunkt.Y));
    ShowMessage(FloatToStr(APolyeder.Schwerpunkt.Z));
  finally
    APolyeder.Free;
  end;
end;

end.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:44 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz