Autor Beitrag
AXMD
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: Sa 20.08.05 15:26 
Hi!

Für alle, die komplexe Schaltungsberechnung mit Widerständen, Kondensatoren und Spulen in Delphi suchen: meine Bibliothek berechnet diese Schaltungen und bietet einige Zusatzfunktionen wie z.B. die Berechnung von Resonanzfrequenzen.
Grundlage des Ganzen ist meine Unit zur komplexen Rechnung:

ausblenden volle Höhe 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:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
//cmpxutil
//  Functions for complex calculation
//  (c) by Dust Signs Andreas Unterweger 2005
//  Last edited August 20, 2005

unit cmpxutil;

interface

uses Math; //Include Math unit for ArcTan2 function

const
  e = 2.71828182846//e [Exp(1)]

type
  TComplexNumber = record //Complex type
    Real, Imaginary: Double; //Comp
    AbsoluteV, Phase: Double; //Polar
    end;

  TComplexNumberArray = Array of TComplexNumber; //More complex numbers; p.e. used for solutions of ComplexSqrt

//Units (as complex type): j, -j, 1, -1, 0
const
  j: TComplexNumber = (Real: 0; Imaginary: 1; AbsoluteV: 1; Phase: Pi / 2); //Imaginary unit
  minus_j: TComplexNumber = (Real: 0; Imaginary: -1; AbsoluteV: 1; Phase: 3 * Pi / 2); //-j
  one: TComplexNumber = (Real: 1; Imaginary: 0; AbsoluteV: 1; Phase: 0); //1
  minus_one: TComplexNumber = (Real: -1; Imaginary: 0; AbsoluteV: 1; Phase: Pi); //-1
  zero: TComplexNumber = (Real: 0; Imaginary: 0; AbsoluteV: 0; Phase: 0); //0

//Various basic functions
procedure RealPhase(var ANumber: TComplexNumber);
function CreateComplexNumber_Comp(Real, Imaginary: Double): TComplexNumber;
function CreateComplexNumber_Polar(AbsoluteV, Phase: Double): TComplexNumber;
procedure SetReal(var ANumber: TComplexNumber; AValue: Double);
procedure SetImaginary(var ANumber: TComplexNumber; AValue: Double);
procedure SetAbsoluteV(var ANumber: TComplexNumber; AValue: Double);
procedure SetPhase(var ANumber: TComplexNumber; AValue: Double);
procedure Conjunct(var ANumber: TComplexNumber);
function Conjunct2(ANumber: TComplexNumber): TComplexNumber;
procedure Invert(var ANumber: TComplexNumber);
procedure InvertAll(var AnArray: TComplexNumberArray);

//Calculate other values (depending on form given)
function CompToPolar(var ANumber: TComplexNumber): Boolean;
function PolarToComp(var ANumber: TComplexNumber): Boolean;

//Basic arithmetical operations
function ComplexAdd(Number1, Number2: TComplexNumber): TComplexNumber;
function ComplexAdd2(Numbers: TComplexNumberArray): TComplexNumber;
function ComplexSub(Number1, Number2: TComplexNumber): TComplexNumber;
function ComplexMul(Number1, Number2: TComplexNumber): TComplexNumber;
function ComplexDiv(Number1, Number2: TComplexNumber): TComplexNumber;

//Extended complex operations
function ComplexPowerSimple(ANumber: TComplexNumber; APower: Double): TComplexNumber;
function ComplexSqrt(ANumber: TComplexNumber; ARoot: Double): TComplexNumber;
function ComplexSqrtEx(ANumber: TComplexNumber; ARoot: Integer): TComplexNumberArray;
function ComplexLn(ANumber: TComplexNumber; ABase: Double = e): TComplexNumber;
function ComplexExp(ANumber: TComplexNumber): TComplexNumber;
function ComplexPower(ANumber1, ANumber2: TComplexNumber): TComplexNumber;

//Other comlex operations (circle- and hyp. functions)
function ComplexSin(ANumber: TComplexNumber): TComplexNumber;
function ComplexCos(ANumber: TComplexNumber): TComplexNumber;
function ComplexSinh(ANumber: TComplexNumber): TComplexNumber;
function ComplexCosh(ANumber: TComplexNumber): TComplexNumber;

//Max operation for cmpxgrph
function MaxReal(Numbers: TComplexNumberArray): Double;
function MaxImg(Numbers: TComplexNumberArray): Double;
function MaxAbs(Numbers: TComplexNumberArray): Double;

implementation

procedure RealPhase(var ANumber: TComplexNumber);
begin
  ANumber.Phase := Frac(ANumber.Phase / (2 * Pi)) * 2 * Pi; //Correct angle...
  while ANumber.Phase < 0 do //While negative
    ANumber.Phase := ANumber.Phase + 2 * Pi; //...to be between 0 and 2 * Pi
end;

function CompToPolar(var ANumber: TComplexNumber): Boolean;
begin
  Result := true; //Successful
  try
    with ANumber do begin
      AbsoluteV := Sqrt(Sqr(Real) + Sqr(Imaginary)); //Real² + Imaginary²
      Phase := ArcTan2(Imaginary, Real); //ArcTan Imaginary / Real
      RealPhase(ANumber); //Correct angle
      end;
  except
    Result := false; //Error occured
    end;
end;

function PolarToComp(var ANumber: TComplexNumber): Boolean;
begin
  Result := true; //Successful
  try
    RealPhase(ANumber); //Correct angle
    with ANumber do begin
      Real := AbsoluteV * Cos(Phase); //Absolute * cosine phase
      Imaginary := AbsoluteV * Sin(Phase); //Absolute * sine phase
      end;
  except
    Result := false; //Error occured
    end;
end;

function ComplexAdd(Number1, Number2: TComplexNumber): TComplexNumber;
begin
  Result.Real := Number1.Real + Number2.Real;
  Result.Imaginary := Number1.Imaginary + Number2.Imaginary;
  CompToPolar(Result); //Refresh other values
end;

function ComplexAdd2(Numbers: TComplexNumberArray): TComplexNumber;
var
  i: Integer;
begin
  Result := zero;
  for i := Low(Numbers) to High(numbers) do
    Result := ComplexAdd(Result, numbers[i]);
end;

function ComplexSub(Number1, Number2: TComplexNumber): TComplexNumber;
begin
  Result.Real := Number1.Real - Number2.Real;
  Result.Imaginary := Number1.Imaginary - Number2.Imaginary;
  CompToPolar(Result); //Refresh other values
end;

function ComplexMul(Number1, Number2: TComplexNumber): TComplexNumber;
begin
  Result.AbsoluteV := Number1.AbsoluteV * Number2.AbsoluteV;
  Result.Phase := Number1.Phase + Number2.Phase;
  PolarToComp(Result); //Refresh other values
end;

function ComplexDiv(Number1, Number2: TComplexNumber): TComplexNumber;
begin
  Result.AbsoluteV := Number1.AbsoluteV / Number2.AbsoluteV;
  Result.Phase := Number1.Phase - Number2.Phase;
  PolarToComp(Result); //Refresh other values
end;

function ComplexPowerSimple(ANumber: TComplexNumber; APower: Double): TComplexNumber;
begin
  Result.AbsoluteV := Power(ANumber.AbsoluteV, APower);
  Result.Phase := ANumber.Phase * APower;
  PolarToComp(Result); //Refresh other values
end;

function ComplexSqrt(ANumber: TComplexNumber; ARoot: Double): TComplexNumber;
begin
  Result.AbsoluteV := Power(ANumber.AbsoluteV, 1 / ARoot);
  Result.Phase := ANumber.Phase / ARoot;
  PolarToComp(Result); //Refresh other values
end;

function ComplexSqrtEx(ANumber: TComplexNumber; ARoot: Integer): TComplexNumberArray;
var
  i: Integer;
begin
  SetLength(Result, ARoot); //Length = number of solutions = ARoot
  ComplexSqrt(Result[0], ARoot); //Calculate main solution
  PolarToComp(Result[0]); //Refresh other values
  for i := 1 to ARoot - 1 do begin //Calculate other solutions
    Result[i].Phase := Result[0].Phase +  2 * Pi * i / ARoot;
    PolarToComp(Result[i]); //Refresh other values
    end;
end;

function ComplexLn(ANumber: TComplexNumber; ABase: Double = e): TComplexNumber;
begin
  Result.Real := Ln(ANumber.AbsoluteV);
  Result.Imaginary := ANumber.Phase;
  CompToPolar(Result); //Refresh other values
  if not IsZero(ABase - e) then begin //If ABase is not e...
    Result.AbsoluteV := Result.AbsoluteV / Ln(ABase); //...correct absolute value...
    PolarToComp(Result); //...and refresh other values
    end;
end;

function ComplexExp(ANumber: TComplexNumber): TComplexNumber;
begin
  Result.AbsoluteV := Exp(ANumber.Real);
  Result.Phase := ANumber.Imaginary;
  CompToPolar(Result); //Refresh other values
end;

function ComplexPower(ANumber1, ANumber2: TComplexNumber): TComplexNumber;
begin
  Result := ComplexExp(ComplexMul(ANumber2, ComplexLn(ANumber1)));
end;

function ComplexSin(ANumber: TComplexNumber): TComplexNumber;
begin
  Result.Real := Sin(ANumber.Real) * Cosh(ANumber.Imaginary);
  Result.Imaginary := Cos(ANumber.Real) * Sinh(ANumber.Imaginary);
  CompToPolar(Result); //Refresh other values
end;

function ComplexCos(ANumber: TComplexNumber): TComplexNumber;
begin
  Result.Real := Cos(ANumber.Real) * Cosh(ANumber.Imaginary);
  Result.Imaginary := -Sin(ANumber.Real) * Sinh(ANumber.Imaginary);
  CompToPolar(Result); //Refresh other values
end;

function ComplexSinh(ANumber: TComplexNumber): TComplexNumber;
begin
  Result.Real := Sinh(ANumber.Real) * Cos(ANumber.Imaginary);
  Result.Imaginary := Cosh(ANumber.Real) * Sin(ANumber.Imaginary);
  CompToPolar(Result); //Refresh other values
end;

function ComplexCosh(ANumber: TComplexNumber): TComplexNumber;
begin
  Result.Real := Cosh(ANumber.Real) * Cos(ANumber.Imaginary);
  Result.Imaginary := Sinh(ANumber.Real) * Sin(ANumber.Imaginary);
  CompToPolar(Result); //Refresh other values
end;

function MaxReal(Numbers: TComplexNumberArray): Double;
var
  i: Integer;
begin
  Result := 0//Initialize
  for i := Low(Numbers) to High(Numbers) do begin
    if Abs(Numbers[i].Real) > Result then //If number bigger than current max. (result) found...
      Result := Abs(Numbers[i].Real); //...make this number the new result
    end;
end;

function MaxImg(Numbers: TComplexNumberArray): Double;
var
  i: Integer;
begin
  Result := 0//Initialize
  for i := Low(Numbers) to High(Numbers) do begin
    if Abs(Numbers[i].Imaginary) > Result then //If number bigger than current max. (result) found...
      Result := Abs(Numbers[i].Imaginary); //...make this number the new result
    end;
end;

function MaxAbs(Numbers: TComplexNumberArray): Double;
var
  i: Integer;
begin
  Result := 0//Initialize
  for i := Low(Numbers) to High(Numbers) do begin
    if Abs(Numbers[i].AbsoluteV) > Result then //If number bigger than current max. (result) found...
      Result := Abs(Numbers[i].AbsoluteV); //...make this number the new result
    end;
end;

function CreateComplexNumber_Comp(Real, Imaginary: Double): TComplexNumber;
begin
  Result.Real := Real;
  Result.Imaginary := Imaginary;
  CompToPolar(Result); //Refresh other values
end;

function CreateComplexNumber_Polar(AbsoluteV, Phase: Double): TComplexNumber;
begin
  Result.AbsoluteV := AbsoluteV;
  Result.Phase := Phase;
  PolarToComp(Result); //Refresh other values
end;

procedure SetReal(var ANumber: TComplexNumber; AValue: Double);
begin
  ANumber.Real := AValue;
  CompToPolar(ANumber); //Refresh other values
end;

procedure SetImaginary(var ANumber: TComplexNumber; AValue: Double);
begin
  ANumber.Imaginary := AValue;
  CompToPolar(ANumber); //Refresh other values
end;

procedure SetAbsoluteV(var ANumber: TComplexNumber; AValue: Double);
begin
  ANumber.AbsoluteV := AValue;
  PolarToComp(ANumber); //Refresh other values
end;

procedure SetPhase(var ANumber: TComplexNumber; AValue: Double);
begin
  ANumber.Phase := AValue;
  PolarToComp(ANumber); //Refresh other values
end;

procedure Conjunct(var ANumber: TComplexNumber);
begin
  ANumber.Phase := -ANumber.Phase;
  PolarToComp(ANumber); //Refresh other values
end;

function Conjunct2(ANumber: TComplexNumber): TComplexNumber;
begin
  Conjunct(ANumber);
  Result := ANumber;
end;

procedure Invert(var ANumber: TComplexNumber);
begin
  ANumber := ComplexDiv(one, ANumber);
end;

procedure InvertAll(var AnArray: TComplexNumberArray);
var
  i: Integer;
begin
  for i := Low(AnArray) to High(AnArray) do
    Invert(AnArray[i]);
end;

end.


Dazu eine Unit, die der eigentlichen Schaltungsberechnungsunit bei der Berechnung etwas unter die Arme greift:

ausblenden volle Höhe 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:
//circutil
//  Utilities for circuit calculation
//  (c) by Dust Signs Andreas Unterweger 2005
//  Last edited August 20, 2005

unit circutil;

interface

uses cmpxutil;

function GetAngularFrequency(AFrequency: Double): Double;
function GetFrequency(AnAngularFrequency: Double): Double;

function Get_R(U, I: TComplexNumber): TComplexNumber;
function Get_U(R, I: TComplexNumber): TComplexNumber;
function Get_I(U, R: TComplexNumber): TComplexNumber;

function GetAppearentValue(AValue: TComplexNumber): Double;
function GetReactiveValue(AValue: TComplexNumber): Double;
function GetEffectiveValue(AValue: TComplexNumber): Double;
function GetPhase(AValue: TComplexNumber): Double;
function GetAppearentPower(U, I: TComplexNumber): TComplexNumber;

function GetResonantCircuitResonanceFrequency(L, C: Double): Double;
function GetHighLowPassResonanceFrequency(R, C: Double): Double;

implementation

function GetAngularFrequency(AFrequency: Double): Double;
begin
  Result := 2 * Pi * AFrequency;
end;

function GetFrequency(AnAngularFrequency: Double): Double;
begin
  Result := AnAngularFrequency / (2 * Pi);
end;

function Get_R(U, I: TComplexNumber): TComplexNumber;
begin
  Result := ComplexDiv(U, I); //U / I
end;

function Get_U(R, I: TComplexNumber): TComplexNumber;
begin
  Result := ComplexMul(R, I); //R * I
end;

function Get_I(U, R: TComplexNumber): TComplexNumber;
begin
  Result := ComplexDiv(U, R); //U / R
end;

function GetAppearentValue(AValue: TComplexNumber): Double;
begin
  Result := AValue.AbsoluteV;
end;

function GetReactiveValue(AValue: TComplexNumber): Double;
begin
  Result := AValue.Imaginary;
end;

function GetEffectiveValue(AValue: TComplexNumber): Double;
begin
  Result := AValue.Real;
end;

function GetPhase(AValue: TComplexNumber): Double;
begin
  Result := AValue.Phase;
end;

function GetAppearentPower(U, I: TComplexNumber): TComplexNumber;
begin
  Result := ComplexMul(U, Conjunct2(I)); //S = U * I*
end;

function GetResonantCircuitResonanceFrequency(L, C: Double): Double;
begin
  Result := GetFrequency(1 / Sqrt(L * C)); //wR = 1 / Sqrt(L * C)
end;

function GetHighLowPassResonanceFrequency(R, C: Double): Double;
begin
  Result := GetFrequency(1 / (R * C)); //wR = 1 / (R * C)
end;

end.


Zwischenbemerkung: die englischen Wörter klingen leider hin und wieder sehr seltsam - dict.leo.org schafft Abhilfe ;).

So, nun zur eigentlichen Unit:

ausblenden volle Höhe 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:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
//circcalc
//  Classes for circuit calculation
//  (c) by Dust Signs Andreas Unterweger 2005
//  Last edited August 20, 2005

unit circcalc;

interface

uses cmpxutil, circutil;

type
  TCustomCircuitElement = class
    private
      FElementValue: Double;
    public
      function GetImpedance: TComplexNumber; virtualabstract;
      constructor Create(AnElementValue: Double);
    published
      property ElementValue: Double read FElementValue write FElementValue;
      property Impedance: TComplexNumber read GetImpedance; //Read-only!
    end;

  TCustomCircuitElementArray = Array of TCustomCircuitElement;

  TResistor = class (TCustomCircuitElement)
    public
      function GetImpedance: TComplexNumber; override;
    end;

  TCapacitor = class (TCustomCircuitElement)
    public
      function GetImpedance: TComplexNumber; override;
    end;

  TCoil = class (TCustomCircuitElement)
    public
      function GetImpedance: TComplexNumber; override;
    end;

  TCircuitElementGroup = class (TCustomCircuitElement)
    private
      FElements: TCustomCircuitElementArray;
      FParallel: Boolean;
      function GetElement(Index: Integer): TCustomCircuitElement;
      procedure SetElement(Index: Integer; AValue: TCustomCircuitElement);
    public
      function GetImpedance: TComplexNumber; override;
      constructor Create;
      destructor Destroy; override;
      property Items[Index: Integer]: TCustomCircuitElement read GetElement write SetElement;
      procedure AddElement(AnElement: TCustomCircuitElement);
      procedure DeleteElement(Index: Integer);
    published
      property Parallel: Boolean read FParallel write FParallel;
    end;

function GetImpedanceAsComplexNumbers(Elements: TCustomCircuitElementArray): TComplexNumberArray;

var
  GlobalCircularFrequency: Double = 2 * Pi * 50//50 Hz

implementation

constructor TCustomCircuitElement.Create(AnElementValue: Double);
begin
  inherited Create;
  FElementValue := AnElementValue;
end;

function TResistor.GetImpedance: TComplexNumber;
begin
  Result := CreateComplexNumber_Comp(ElementValue, 0); //Nothing imaginary
end;

function TCapacitor.GetImpedance: TComplexNumber;
var
  x: Double;
begin
  x := 1 / (GlobalCircularFrequency * ElementValue); //XC = 1/wC
  Result := ComplexMul(minus_j, CreateComplexNumber_Comp(x, 0)); //-jXC
end;

function TCoil.GetImpedance: TComplexNumber;
var
  x: Double;
begin
  x := GlobalCircularFrequency * ElementValue; //XL = wL
  Result := ComplexMul(j, CreateComplexNumber_Comp(x, 0)); //jXL
end;

constructor TCircuitElementGroup.Create;
begin
  inherited Create(0); //No value!
  SetLength(FElements, 0);
  FParallel := false;
end;

destructor TCircuitElementGroup.Destroy;
var
  i: Integer;
begin
  for i := Low(FElements) to High(FElements) do //Free all elements
    FElements[i].Free;
  SetLength(FElements, 0);
  inherited;
end;

function TCircuitElementGroup.GetElement(Index: Integer): TCustomCircuitElement;
begin
  Result := FElements[Index];
end;

procedure TCircuitElementGroup.SetElement(Index: Integer; AValue: TCustomCircuitElement);
begin
  FElements[Index] := AValue;
end;

procedure TCircuitElementGroup.AddElement(AnElement: TCustomCircuitElement);
begin
  SetLength(FElements, Length(FElements) + 1);
  FElements[High(FElements)] := AnElement;
end;

procedure TCircuitElementGroup.DeleteElement(Index: Integer);
var
  i: Integer;
begin
  FElements[Index].Free; //Free object
  for i := Index to High(FElements) - 1 do
    FElements[i] := FElements[i + 1];
  SetLength(FElements, Length(FElements) - 1);
end;

function TCircuitElementGroup.GetImpedance: TComplexNumber;
var
  impedancearray: TComplexNumberArray;
begin
  impedancearray := GetImpedanceAsComplexNumbers(FElements);
  if not FParallel then //Serial
    Result := ComplexAdd2(impedancearray)
  else begin //Parallel
    InvertAll(impedancearray); //1 / Z
    Result := ComplexAdd2(impedancearray); //1 / Z1 + 1 / Z2 ...
    Invert(Result); // 1 / (1 / Z1 + 1 / Z2 ...)
    end;
end;

function GetImpedanceAsComplexNumbers(Elements: TCustomCircuitElementArray): TComplexNumberArray;
var
  i: Integer;
begin
  SetLength(Result, Length(Elements));
  for i := Low(Elements) to High(Elements) do
    Result[i] := Elements[i].Impedance;
end;

end.


Zu guter letzt noch etwas Beispielcode. Der ist leider nicht sehr schön, erfüllt aber seinen Zweck. Einige Bemerkungen gleich dazu:

1.) Es muss nur die äußerste Schaltungsgruppe freigegeben werden - das Freigeben der Schaltungselemente, die sich in der jeweiligen Gruppe befinden, übernimmt ein modifizierter Destruktor
2.) Schaltungsgruppen können beliebig ineinander verschachtelt sein
3.) Die Eigenschaft Impedance liefert die Impedanz des Bauelements/der Schaltungsgruppe
4.) ElementValue eines Kondensators darf nicht 0 sein; ebenso wie eine Parallelschaltung aus mindestens einem Element bestehen muss bevor ihre Impedanz aufgerufen wird.
5.) Die Wechselspannungsfrequenz kann über die globale Variable GlobalCircularFrequency eingestellt werden
6.) Ströme und Spannungen können mit den Routinen Get_U bzw. Get_I in circutil.pas berechnet werden

ausblenden 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:
procedure TCircuitCalculationForm.FormCreate(Sender: TObject);
var
  g: TCircuitElementGroup;
begin //Dummy-Prozedur um Funktionalität zu testen!
  g := TCircuitElementGroup.Create;
  with g do begin
    Parallel := true;
    AddElement(TResistor.Create(2200));
    AddElement(TCoil.Create(0.3));
    AddElement(TCapacitor.Create(8E-6));
    end;
  with TCircuitElementGroup.Create do begin
    Parallel := false;
    AddElement(TCoil.Create(0.4));
    AddElement(g);
    with ComplexEditorFrame1 do begin
      Initialize;
      SetReadOnly(true);
      SetPhasor(Impedance); //Ergebnis sollte 6,9113 + j248,7774 sein
      end;
    Free;
    end;
end;


Lizenz: Open Source; solange mein Name im Header bleibt (als ursprünglicher Autor o.ä.) kann der Code modifiziert werden. Wird der Code in einem Programm verwendet bitte in der About-Box und der Readme (falls es eine gibt) einen entsprechenden Hinweis. Verwendung in Shareware oder anderen kommerziellen Projekten ist nicht gestattet.

Der Code ist noch etwas Beta, da nicht alles getestet ist. Freue mich über Anregungen aller Art :)

AXMD

PS.: Hin und wieder treten Memoryleaks auf - falls jemand die Ursache findet bitte Bescheid sagen :)