komponent a tablica

0

Witam!
Mam taki problem:musze napisać komponent do obliczeń numerycznych na macierzach rzadkich. Najpierw dokonuje dyskretyzacji metada MES i tworze macierze A,Y i szukana X. Chce stworzyc komponent ktory bedzie mial możliwość podania z zewnatrz tablicy do funkcji np:
function oblicz_CG(var A:array of double):array of double;
begin
//kod
end;

i chce to umiescic w komponencie do ktorego podam

komponent.A:=jakas macierz ktora stworzylem(nie moze byc kopiowana tylko dzialania na istniejacej wewnatrz komponentu).
komponent.metodaliczenia:=CG i wtedy wywola funkcje oblicz_CG i uzyje tablicy np moja_tab w miejsce A.

Z gory dzieki za pomoc [diabel]

0

Tak na prawdę to nie zdałeś pytania. Jedyne co wywnioskowałem, to to że nie wiesz jak zacząć cokolwiek. Postaw konkretne pytanie o fragment który Cię zatrzymał wówczas dostaniesz odpowiedź. Jeżeli chcesz pomocy to poszukaj na forum podstaw tworzenia komponentów.

0

Ja proponuje napisać klase TMacierz do podstawowej obsługi macierzy. Metodami tej klasy były by: wczytywanie z jakiegoś źródła, jakieś operacje typu odwracanie, transponowanie, dodawanie/usuwanie wierszy/kolumn itp. itd.

Do tego napisz zestaw funkcji przyjmujących jako argumenty TMacierz, np.

  function Wyznacznik(Macierz: TMacierz): Real;
  function Suma(MacierzL, MacierzP: TMacierz): TMacierz;

Jeśli masz delphi .NET, to możesz zdefiniować operatory dla TMacierz (przypisanie, dodawanie etc.).

Wszystko wpakuj w jakiś unit, użycie komponentu nie pasuje do tego problemu.

0

własnie chodzi o to ze musi to byc komponent. Mam problem z wlasciwoscia property. Tzn czy da sie zrobic tak ze:
nterface

uses
SysUtils, Classes;

type
TNumericalMethods = class(TComponent)
private
FA_matrix : array of double;
protected

public
{ Public declarations }
published
property A_matrix:array of double read FA_matrix write FA_matrix;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Standard', [TNumericalMethods]);
end;

end.

nie moge zamiescic w wlasciwosci property tablicy a musza ja zczytac do komponentu i dalej juz mam funkcje ktore bazyja na tej macierzy. Kłade na forme komponent tworze w programie macierze i dalej korzystam z komponentu aby rozwiazac rownanie liniowe macierzowo. Jak wlasnie poslugiwac sie macierza, ale nie chodzi mi o zkopiowanie np macierzy

for i:=low(mac_z_programu) to high(mac_z_programu) do komponent.zmienna:= mac_z_programu[i];

wewnatrz komponentu musze dzialac na macierzy juz istniejacej, a nie stworzyc nowa i przypisac do niej elementy.

0
type
 TMyMatrix: array of Double;
type
  TNumericalMethods = class(TComponent)
  private
   FA_matrix : TMyMatrix;
  protected

  public
    { Public declarations }
  published
   property A_matrix:TMyMatrix read FA_matrix write FA_matrix;
  end;

i powinno grać

0

akurat do tego juz sam doSZEDŁem:

unit NumericalMethods;

interface

uses
SysUtils, Classes, Math;

type
TVector = array of double;

TNumericalMethods=class(TComponent)
private
{ Private declarations }
Fmatrix :TVector;
FText :String;
protected
{ Protected declarations }
public
{ Public declarations }
published
{ Published declarations }
property A_matrix : TVector read Fmatrix write Fmatrix;
property Text: String read FText write FText;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Standard', [TNumericalMethods]);
end;

end.

W object inspectorze widzi Text i wszystko sie poprawnie odbywa w projekcie do ktorego wrzucilem komponent numericalmethods. Robie sobie przypisanie Numericalmethod1.text:='aaa' potem po nacisnieciu buttona form1.caption:=numericalmethod1.text i wszystko gra.
Zdefiniowalem typ w programie

private
{ Private declarations }
public
{ Public declarations }
end;
type
TMatrix=array of array of double;
TVector=array of double;

potem klikam na buttona:

procedure TForm1.Button1Click(Sender: TObject);
begin
SetLength(matrix,8); //matrix jest Tvector
for i:=low(matrix) to high(matrix) do matrix[i]:=i+0.01;
end;

i probuje przypisac do komponentu Numericalmethods1 wlasnie tablice matrix

Numericalmethods1.A_matrix:=matrix; i wyskakuje incompatible types

czemu?? [???]

wewnatrz komponentu chce operowac na tej macierzy przypisanej do numericalmethods.A_matrix i np tworzyc jej wyznacznik

0

To dziwne, bo u mnie wszystko OK. Ale przecież nie musisz tworzyć matrix, możesz bezpośrednio operować na A_matrix

SetLength(Numericalmethods1.A_matrix, 8); ...

A tak w ogóle to dleczeogo A_matrix i matrix to array of double a nie array of array of double ???????????

0

jeśli chcesz się do property'a odwoływać przez index to go trzeba inaczej zdefiniować

type
  TVector = array of double;

  TNumericalMethods=class(TComponent)
  private
    { Private declarations }
    Fmatrix :TVector;
    FText    :String;
    function GetA_matrix(Index: Word): Double;
    procedure SetA_matrix(Index: Word; const Value: Double);
  protected
    { Protected declarations }
  public
    { Public declarations }
  published
    { Published declarations }
    property A_matrix[Index: Word]: Double read GetA_matrix write SetA_matrix;
    property Text: String read FText write FText;
  end;

function TNumericalMethods.GetA_matrix(Index: Word): Double;
begin
  { sprawdzenie zakresu }
  if (Index >= Length(Fmatrix)) then
    raise Exception.Create('Index out of bounds.');
  { pobranie wartosci }
  Result := Fmatrix[Index];
end;

procedure TNumericalMethods.SetA_matrix(Index: Word; const Value: Double);
begin
  { sprawdzenie zakresu }
  if (Index >= Length(Fmatrix)) then
    raise Exception.Create('Index out of bounds.');
  { dodanie wartości }
  Fmatrix[Index] := Value;
end;

jesli się gdzieś w nazewnictwie nie walnąłem to będzie działać. Oczywiście pozostaje kwestia ustalania rozmiaru tablicy - można np. w konstruktorze przekazywać rozmiar, można dodatkową właściwość dodać, można w SetA_matrix zamiast wywalać wyjątek zwiększać rozmiar tablicy - to już jak chcesz

EDIT: adf88 po to pakuje to w klasę żeby nie grzabać wprost na właściwościach (mówię o SetLength(NumericalMethods.A_matrix, xx);)

0

ale ja dostaje macierz w wyniku dyskretyzacji czyli mam juz jakas i musze ta macierz dodac tak zeby byla widoczna dla funkcji wewnatrz komponentu.Czyli informuje komponent ze matrix typu Tvector(tak ma byc -z macierzy sa zapisywane tylko elementy niezerowe do wektora)to ta ktora ma byc uzyta w komponenci np w funkcji dodawanie(A:Tvector):Tvector;
czyli komponent.A_matrix:=matrix_dyskretyzowanie
potem wywoluje sobie komponent.dodawanie;

i do np X:Tvector zczytanego takze w komponencie wypisuje wynik tej funkcji.

Czy w object inspectorze widzisz wlasciwosc A_matrix?? bo ja nie-nie wiem czemu bo text jest widoczne

Ten komponent ma ulatwic ludzia obliczenia numeryczne w Metodzie Elementów Skonczonych.
Czyli koles sobie tworzy te swoje macierze i najlepiej instrukcja NumericalMethods1.A_matrix:=macierz_kolesia przypisuje ja do komponentu(w identyczny sposob przypisuje wektory X oraz B) potem wybiera metode NumericalMethods.MetodaLiczeni:=mlGauss;

i to mu liczy samo oraz wrzuca wynik do X(operuje przez rekurencje na tablicy X);

0
crowa napisał(a)

Czy w object inspectorze widzisz wlasciwosc A_matrix?? bo ja nie-nie wiem czemu bo text jest widoczne
Musisz napisać TPropertyEditor

Dlaczego to ciągle wektory a nie macierze ? Proponuje konstrukcje taką: macierz tylko do odczytu (tablica, nie jej pola) + funkcja ustalająca rozmiar:

  TMatrix = array of array of double;

  TNumericalMethods=class(TComponent)
  private
    Fmatrix  :TMatrix;
    FText    :string;
    FWidth   :Integer;
    FHeight  :Integer;
  public
    procedure SetAMatrixSize(Width, Height: Integer);
  published
    property A_matrix : TMatrix read Fmatrix;
    property Text: String read FText write FText;
  end;


procedure TNumericalMethods.SetAMatrixSize(Width, Height: Integer);
var i: Integer;
begin
  FWidth := Width;
  FHeight := Height;
  SetLength(Fmatrix, Height);
  for i := 0 to Height - 1 do SetLength(FMatrix[i], Width);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i, j: integer;
  methods: TNumericalMethods;
begin
  methods := TNumericalMethods.Create(Form1);
  methods.SetAMatrixSize(8, 8);
  for i := 0 to 7 do
    for j := 0 to 7 do
      methods.A_matrix[i, j] := i*8+j;
end;

Albo
property Width: Integer read FWidth write SetWidth;
property Height: Integer read FHeight write SetHeight;

do tego dopisac procedury SetWidth, SetHeight

Można dorzucić jeszcze metode
procedure CopyToAMatrix(Macierz: TMacierz);
która skopiuje zawartość Macierz do Fmacierz

0

ok juz tlumacze czemu matrix jest array of double.
W wyniku dyskretyzacji dostajemy macierz nxn elementów w ktorych ok 10% to elementy niezerowe, wiec tworzymy matrix:Tvector gdzie sa zachowane elementy niezerowe i jeszcze Validate:Tval gdzie Tval to pakiet rekordowy col:integer i row:integer;
Nazwa matrix jest tylko i wylacznie w celu zachowania konsekwencji nazewnictwa w metodzie MES.
Odpadaja metody tworzenia Setlength(NumericalMethod1.A_matrix,8) do to jest dla ludzi ktorzy nie umieja programowac. Wrzuca sobie ten komponent na forme, przypisuje mu
NumericalMethod1.A_matrix:=A_dyskretyzacjia;
NumericalMethod1.X_vector:=X_dyskretyzacjia;
NumericalMethod1.B_vector:=B_dyskretyzacjia; //wymuszenia

mamy A_dyskretyzacja,B_dyskretyzacja,X_dyskretyzacja, i musimy je przypisac do komponentu.
Wewnatrz komponentu sa funkcjie np function Gauss(var A,B:Tvector;):Tvector

czyli X_dyskretyzacja:=Gauss(A_dyskretyzacja,B_dyskretyzacja);

operujemy na wektorach nie macierzach.(matrix to tylko nazwa)

0

ok wiec sprawa ma sie tak:

dołozyłem rekorda do komponentu

type
 TMyMatrix= array of Double;
 TVal=record   //declaration of record package that define position of element in sparse matrix A
  col:integer;
  row:integer;
 end;

type
  TNumericalMethods=class(TComponent)
  private
    { Private declarations }
    FA_matrix : TMyMatrix;
    FText     :String;
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner : TComponent); override;
    destructor Destroy; override;
    procedure dodaj(var A,B,X:array of double;validate:Tval);

  published
    { Published declarations }
    property A_matrix:TMyMatrix read FA_matrix write FA_matrix;
    property Text: String read FText write FText;
  end;



procedure Register;

implementation

procedure TNumericalMethods.dodaj(var A,B,X:array of double;validate:TVal);
var i:integer;
begin
 for i:=low(A) to high(A) do X[i]:=A[i]+B[i];
end;

i w formie na ktorej jest komponent dolozony tworze tez rekor
Tval=record
col:integer;
row:integer;
end;

var Z:Tval;

ale wyskakuje blad jezeli robie:

procedure TForm1.Button3Click(Sender: TObject);
var
    i:integer;
    Z:TVal;
    Y:TMymatrix;
    methods:TNumericalMethods;
begin
 methods := TNumericalMethods.Create(Form1);
 for i:=low(A) to high(A) do
  begin
   A[i]:=A[i]+i;
   B[i]:=i;
  end;
 methods.dodaj(A,B,X,Z);
 for i:=low(X) to high(X) do Memo1.Lines.Add(floattostr(X[i]));
end;

wyswietla blad:

Incompatible types: 'NumericalMethods.TVal' and 'Unit1.TVal'

Chodzi o to ze chyba musze w komponencie zarejestrowac klase taka jak np Tstring, ktora bedzie widoczna juz w kazdym nastepnym unicie.
Ktos ma pomysl jak??
Programowac potrafie nie najgorzej ale komponentów nie pisalem-ten jest 1.

0

masz dwa razy zadeklarowany typ TVal - wywal ten z Form1

0
Misiekd napisał(a)

masz dwa razy zadeklarowany typ TVal - wywal ten z Form1

tylko jak wywale to jak mam wstawic do funkcji dodaj np tablice Z bez wczesniejszej jej deklaracji,ze jest typu Tval. Jak mozesz to daj mi kod tego bo nie za bardzo wiem o co chodzi. To tak jak np z MaxValue(array of integer) to tablica np A musi byc aaray of integer zadeklarowana wczesniej MaxValue(A).

0

bez wczesniejszej jej deklaracji
no właśnie deklaracja z pliku z komponentem jest tą wcześniejszą, możesz ją używać w innych plikach.

0

ok dzienx dokładnie o to chodziło. A tworzyliście kiedyś komponent dziedziczacy po klasie Tgraphic a dokładniej po TpageControl tylko taki zeby pagecontrol wygladal jak np taby w IE7
http://www.microsoft.com/windows/ie/ie7/tour/tabs/how.html</url>

1 użytkowników online, w tym zalogowanych: 0, gości: 1