Connaissez-vous des méthodes de calcul de câbles porteurs de téléphériques ?
Pour ma part, j'ai développé deux logiciels de calcul:
- Une version pour les téléphériques dont les câbles sont tirés par contrepoids: GHTyro sur le site Remontées Mécaniques
- Une autre version pour les TPH à cables fixes, tenant compte de l'allongement des câbles. Avis aux programmeurs:
Pour le moment, je ne mets que le programme en langage Pascal (unités de code seulement) (logiciel libre) car je ne sais pas insérer une image ici.
Le programme est développé dans le cadre du projet Vertaco Traverse (sur Google: Vertaco Traverse), une tyrolienne en corde spéléo dépassant le kilomètre de portée.
Code principal
unit Calculs;
interface
uses
SysUtils, Classes, Math,
GPFunctions,
Forms;
// constantes physiques
const
TAB = #9;
DTR = PI/180;
RTD = 180/PI;
// caractéristiques générales de l'ouvrage
type TGeneralCaracteristiques = record
// position des ancrages
Lo: double;
Ho: Double;
// nombre d'éléments de câble
NbElements : integer;
// longueur du câble par défaut
LongueurInitialeCable: double;
// chargement réparti
ChargeRepartie: double;
// chargement concentré
ValeurQ : double;
// caractéristiques des câbles
DiametreCables: double;
MasseLineique : double; // masse linéique de chaque câble
NbCables : integer;
ForceRepartie : double; // force répartie: w = g.m.b *
// élasticité du cable en Elasticite% par TensionCaracteristique (ex: 2%/80 daN)
Elasticite : double;
TensionCaracteristique: double; // tension caractéristique
// barre sur laquelle est appliqué l'effort concentré
NoBarreEffortConcentre: integer;
// paramètres de départ
TensionInitiale : double;
AngleInitial : double;
// incréments
IncrEffort : double;
IncrAngle : double;
// tolérance de distance
DistanceMax : double;
// précision des calculs
PrecisionCalcul: double;
end;
// valeurs calculées (=colonnes du tableau)
type TValeursCalculeesTroncon = record
// chargement total sur le tronçon:
// charge répartie + charge concentrée
Charge : double;
// longueur déformée du tronçon
B_Prime : double;
// effort normal à droite
Effort : double;
// angle du tronçon
Angle : double;
// composantes
dx, dy : double;
// coordonnées du point droit
Xd, Yd : double;
end;
// tableau de résultats
type TConfigCable = record
// efforts normaux
No : double; // effort extrémité gauche
Nq : double; // effort au niveau de l'équipage
N1 : double; // effort extrémité droite
// angles
Alpha0 : double; // angle extrémité gauche
AlphaQg : double; // angle à gauche de l'équipage
AlphaQd : double; // angle à droite de l'équipage
// longueur d'un élément de câble: b
LongueurB : double;
// longueur du câble
LongCable : double;
// numéro de la barre sur laquelle est appliqué le chargement
NoBarreChargee: integer;
// longueur totale du câble
LongueurCable : double;
// coordonnées de la charge roulante
Xq, Yq : double;
// coordonnées de l'ancrage (calculées)
X1, Y1 : double;
// distance calculée
Distance : double;
// tableau détaillé
ResultatsTroncons: array of TValeursCalculeesTroncon;
end;
// classe Tyrolienne
type TTyrolienne = class
function Init(const GC: TGeneralCaracteristiques): Boolean;
function GetGeneralCaracteristiques: TGeneralCaracteristiques;
procedure SetGeneralCaracteristiques(const GC: TGeneralCaracteristiques);
// calcul de la configuration du câble
function CalculerConfigurationCable(const NoTableau: integer; // tableau de résultats considéré
const NoBarre : integer; // numéro de la barre chargée
const N_Initial: double; // effort normal initial
const Alpha_0 : double; // Angle initial
const LongueurBarre: double; // longueur d'un élément de câble
out LongueurDuCable: double;
out XAtteint, YAtteint: double; // longueur développée du câble
out Angle_1: double; // angle de sortie
out N_Final : double // effort en sortie
): double; // distance par rapport à l'ancrage d'arrivée
// détermination d'une configuration
function DeterminerConfigurationCable(const Application: TApplication; // pour ProcessMessages
const NoTableau: integer; // tableau de résultats considéré
const NoBarre : integer; // numéro de la barre chargée
const N_Dep, N_Arr: double; // effort normal initial
const A_Dep, A_Arr: double; // Angle initial
const Inc_N, Inc_A: double; // Incréments
const Tolerance: double // tolérance
): int64;
// détermination de la cote mini et maxi du câble
procedure SetCableCotesMinMax(const NoTableau: integer);
// résultats éléments de câble
function GetTronconCalcule(const NoTableau, Idx: integer): TValeursCalculeesTroncon;
// calculer l'angle initial câble déchargé par la méthode de Jippé
function GetAlphaInitial(const EffortPrecontrainte: double): double;
// numéro de barre en fonction de X
function GetNumeroBarre(const NoTableau: integer; const X: double): integer;
// position du câble par rapport à l'ancrage
function GetDeltaZCable(const NoTableau: integer; const X: double): double;
private
// flag pour arrêter le calcul
FCancelled: boolean;
// flag pour les représentations graphiques
FCanDraw : boolean;
// caractéristiques de l'ouvrage
FGeneralCaracteristiques: TGeneralCaracteristiques;
// tableaux de résultats
FConfigurationsCables : array[0..0] of TConfigCable;
// Cote maxi et mini du câble (encombrement du câble)
FCoteMiniCable, FCoteMaxiCable: double;
public
property Cancelled: boolean read FCancelled write FCancelled;
property CanDraw : boolean read FCanDraw write FCanDraw;
property GeneralCaracteristiques: TGeneralCaracteristiques read FGeneralCaracteristiques
write FGeneralCaracteristiques;
property CoteMiniCable: double read FCoteMiniCable write FCoteMiniCable;
property CoteMaxiCable: double read FCoteMaxiCable write FCoteMaxiCable;
end;
implementation
function TTyrolienne.Init(const GC: TGeneralCaracteristiques): Boolean;
var
i: integer;
RT: TValeursCalculeesTroncon;
begin
DispMessageMeth(self, 'Init');
Result := False;
FCancelled := False;
FCanDraw := False;
SetGeneralCaracteristiques(GC);
if FGeneralCaracteristiques.NbElements = 0 then begin
DispMessageMeth(self, 'Init KO: Nombre de barres nul');
Exit;
end;
// dimensionner les tableaux
with FConfigurationsCables[0] do begin
SetLength(ResultatsTroncons, 0);
SetLength(ResultatsTroncons, 1 + FGeneralCaracteristiques.NbElements);
// configurer tableau
for i := 0 to FGeneralCaracteristiques.NbElements do begin
//RT.Charge := FGeneralCaracteristiques.ChargeRepartie;
FillChar(RT, SizeOf(TValeursCalculeesTroncon), 0);
end;
end;
//*)
// calcul de valeurs
with FGeneralCaracteristiques do begin
ChargeRepartie := (MasseLineique /1000) * g * NbCables;
LongueurInitialeCable := CalcLongueurCable(Lo, Ho, AngleInitial);
end;
// afficher données initiales
DispMessage('------------------');
DispMessage('Données initiales');
DispMessage('------------------');
with FGeneralCaracteristiques do begin
DispMessage(Format(' Lo = %.2f m',[Lo]));
DispMessage(Format(' Ho = %.2f m',[Ho]));
DispMessage('');
DispMessage(Format(' Longueur câble = %.2f m',[LongueurInitialeCable]));
DispMessage(Format(' Câble discrétisé en %d éléments',[NbElements]));
DispMessage('');
DispMessage(Format(' Nombre de câbles: %d',[NbCables]));
DispMessage(Format(' Diamètre des cables = %.2f mm',[DiametreCables]));
DispMessage(Format(' Masse linéique: w = %.2f g/m',[MasseLineique]));
DispMessage(Format(' Elasticité: E = %.2f%% sous %.2f',[100 * Elasticite, TensionCaracteristique]));
DispMessage('');
DispMessage(Format(' Charge répartie G = %.2f N',[ChargeRepartie]));
DispMessage(Format(' Charge concentrée Q = %.2f N sur la barre #%d)',[ValeurQ, NoBarreEffortConcentre]));
DispMessage('');
DispMessage(Format(' Tension initiale = %.2f N',[TensionInitiale]));
DispMessage(Format(' Angle initial = %.5f °',[AngleInitial]));
DispMessage('');
DispMessage(Format(' Incrément efforts = %.2f N',[IncrEffort]));
DispMessage(Format(' Incrément angle = %.5f °',[IncrAngle]));
DispMessage('');
DispMessage(Format(' Tolérance distance = %.2f m',[DistanceMax]));
DispMessage('------------------');
end;
end;
function TTyrolienne.GetGeneralCaracteristiques: TGeneralCaracteristiques;
begin
Result := FGeneralCaracteristiques;
end;
procedure TTyrolienne.SetGeneralCaracteristiques(const GC: TGeneralCaracteristiques);
begin
FGeneralCaracteristiques := GC;
end;
// calcul de la configuration du câble
// retourne la distance à l'appui
//ce code a l'air de bien fonctionner
function TTyrolienne.CalculerConfigurationCable(const NoTableau: integer; // tableau de résultats considéré
const NoBarre : integer; // numéro de la barre chargée
const N_Initial: double; // effort normal initial
const Alpha_0 : double;
const LongueurBarre: double; // longueur d'un élément de câble
out LongueurDuCable: double;
out XAtteint, YAtteint: double; // écart par rapport à l'appui
out Angle_1 : double; // angle de sortie
out N_Final : double // effort en sortie
): double; // Angle initial
var
i,Nb: integer;
Am: Double;
Eq101a, Eq101b: double;
b: double;
begin
Result := 1e10;
//DispMessageMeth(self, Format('CalculerConfigurationCable: Cas %d - Barre %d',[NoTableau, NoBarre]));
//DispMessage(Format('N_G = %.2f - A_G = %.5f',[N_Initial, RTD *Alpha_0]));
// b: longueur initiale des tronçons
b := LongueurBarre;
//WriteLn(b);
with FConfigurationsCables[NoTableau] do begin
// longueur cable
LongCable := 0.00;
with ResultatsTroncons[0] do begin
Angle := Alpha_0;
Charge := FGeneralCaracteristiques.ChargeRepartie * b;
B_Prime := B;
Effort := N_Initial;
dx := 0.00;
dy := 0.00;
Xd := 0.00;
Yd := 0.00;
end; //with ResultatsTroncons[0] do begin
Nb:= FGeneralCaracteristiques.NbElements;
LongueurDuCable := 0.00;
for i := 1 to Nb do begin
ResultatsTroncons[i].Charge := FGeneralCaracteristiques.ChargeRepartie * b;
if (i = NoBarre) then begin// ajout des forces concentrées
ResultatsTroncons[i].Charge := ResultatsTroncons[i].Charge +
FGeneralCaracteristiques.ValeurQ;
end;
// ajout du poids du blaireau qui a mis sa poignée à l'envers ...
ResultatsTroncons[34].Charge := ResultatsTroncons[34].Charge + 1000.00;
Eq101a := CalcEqu101a(ResultatsTroncons[i-1].Effort,
ResultatsTroncons[i-1].Angle,
0.00);
Eq101b := CalcEqu101b(ResultatsTroncons[i-1].Effort,
ResultatsTroncons[i-1].Angle,
ResultatsTroncons[i].Charge);
//WriteLn(Eq101a, Eq101b);
ResultatsTroncons[i].Effort := CalcN1(Eq101a, Eq101b);
ResultatsTroncons[i].Angle := CalcAlpha1(Eq101a, Eq101b);
// calcul de b'
ResultatsTroncons[i].B_Prime := CalcBPrime(b,
FGeneralCaracteristiques.Elasticite,
ResultatsTroncons[i-1].Effort,
ResultatsTroncons[i].Effort,
FGeneralCaracteristiques.TensionCaracteristique);//
//);
// WriteLn(RTD*ResultatsTroncons[i-1].Angle, RTD*ResultatsTroncons[i].Angle);
// longueur câble
LongueurDuCable := LongueurDuCable + ResultatsTroncons[i].B_Prime;
LongCable := LongueurDuCable;
// composantes de b': angle moyen
Am := AngleMoy(ResultatsTroncons[i-1].Angle, ResultatsTroncons[i].Angle);
ResultatsTroncons[i].dx := CalcBPrimeX(ResultatsTroncons[i].B_Prime, Am);
ResultatsTroncons[i].dy := CalcBPrimeY(ResultatsTroncons[i].B_Prime, Am);
// coordonnées de l'extrémité de la barre
ResultatsTroncons[i].Xd := ResultatsTroncons[i-1].Xd + ResultatsTroncons[i].dx;
ResultatsTroncons[i].Yd := ResultatsTroncons[i-1].Yd + ResultatsTroncons[i].dy;
end; //for i := 0 to FGeneralCaracteristiques.NbElements-1 do begin
// longueur corrigée de la barre = longueur de l'élément n°1.
//DispMessage (Format('b = %.2f, b'' = %.2f',[LongueurBarre, ResultatsTroncons[Nb].B_Prime]));
//LongueurBarre := ResultatsTroncons[Nb].B_Prime;
// écart = extrémités de la barre
XAtteint := ResultatsTroncons[Nb].Xd;// - FGeneralCaracteristiques.Lo;
YAtteint := ResultatsTroncons[Nb].Yd;// - FGeneralCaracteristiques.Ho;
// distance
//Distance := Hypot(DeltaX, DeltaY);
Distance := Hypot(ResultatsTroncons[Nb].Xd - FGeneralCaracteristiques.Lo,
ResultatsTroncons[Nb].Yd - FGeneralCaracteristiques.Ho);
// angle à l'extrémité du câble
Angle_1 := ResultatsTroncons[Nb].Angle;
N_Final := ResultatsTroncons[Nb].Effort;
// valeur de retour
Result := Distance;
end; //with FConfigurationsCables[NoTableau] do begin
end;
// détermination d'une configuration
// Valeur de retour: nombre d'itérations
function TTyrolienne.DeterminerConfigurationCable(const Application: TApplication; // pour ProcessMessages
const NoTableau: integer; // tableau de résultats considéré
const NoBarre : integer; // numéro de la barre chargée
const N_Dep, N_Arr: double; // effort normal initial
const A_Dep, A_Arr: double; // Angle initial (radians)
const Inc_N, Inc_A: double; // Incréments
const Tolerance: double // tolérance
): int64;
var
// écarts-types angles et efforts
StdDevAngs, // = DTR * 8.00;
StdDevEffort: double; // = 2000;
i: integer;
// angle d'entrée
Alpha_G: double;
// dilution angulaire
Alpha_Dilution: double;
// effort d'entrée
N_Gauche: double;
// dilution de l'effort normal
N_Dilution: double;
//---------------------------------
LCable: double;
LBR : double; // longueur de la barre élémentaire
LongueurCable0: double; //longueur cable avant détermination
LongueurCable1: double; //longueur cable après détermination
LongCablePrecontraint: double; // longueur du câble précontraint
XAtteint, YAtteint : double; // écart en X et Y par rapport à l'appui
IncrL, IncrA : double; // incréments
Distance : double; // distance à un ancrage
// corde ravalée à chaque itération
CableRavale : double;
// différences
DeltaX, DeltaY : double;
// angle de sortie
Alpha_D: double;
// effort de sortie
N_Droite : double;
// Distance mini
DistMini: double;
// NbIterations
NbIters: Int64;
begin
Result := -1;
FCancelled := False;
// écarts-types
StdDevAngs := DTR * 10.00; // = DTR * 8.00;
StdDevEffort:= FGeneralCaracteristiques.TensionInitiale * 0.1;
// initialisation du générateur de nombres aléatoires
Randomize();
DispMessageMeth(self, Format('DeterminerConfigurationCable: Cas %d - Barre %d',[NoTableau, NoBarre]));
DispMessage('');
DispMessage(Format('Efforts: de %f a %f',[N_Dep, N_Arr]));
DispMessage(Format('Angles : de %f a %f',[RTD * A_Dep, RTD * A_Arr]));
DispMessage('');
// Première détermination pour obtenir la configuration du câble déchargé: angle et effort initiaux
//--------------------------------------------------------------------------------------
Alpha_G := A_Dep;
N_Gauche := N_Dep;
DispMessage(Format('Angle départ : %f - Effort initial %f',[RTD * Alpha_G, N_Gauche]));
FGeneralCaracteristiques.LongueurInitialeCable := CalcLongueurCable(FGeneralCaracteristiques.Lo,
FGeneralCaracteristiques.Ho,
Alpha_G
);
//------------------------------------------------
LongueurCable0 := FGeneralCaracteristiques.LongueurInitialeCable;
LBR := LongueurCable0 / FGeneralCaracteristiques.NbElements;
LCable := 0;
// Première détermination pour le calcul de la longueur du câble ravalé
Distance := CalculerConfigurationCable(0, // tableau de résultats considéré
0, //FGeneralCaracteristiques.NoBarreEffortConcentre, // numéro de la barre chargée
N_Gauche, // effort normal initial
Alpha_G, // angle initial en radians
LBR, // longueur d'un élément de câble
LCable,
XAtteint, YAtteint,
Alpha_D,
N_Droite
);
CableRavale := LCable - FGeneralCaracteristiques.LongueurInitialeCable;
LongCablePrecontraint := LongueurCable0 - CableRavale;
//-------------------------------------------------
// Utilisation de la méthode de Monte - Carlo pour la détermination
NbIters := 0;
DistMini := 1E06;
repeat
Application.ProcessMessages;
if FCancelled then begin
DispMessage('*** Calcul arrêté par l''utilisateur ***');
Break;
end;
//LongueurCable0 := FGeneralCaracteristiques.LongueurInitialeCable;
// Deux déterminations pour déterminer la longueur de câble ravalé
// for i := 0 to 1 do begin
//LBR := LongueurCable0 / FGeneralCaracteristiques.NbElements;
LBR := LongCablePrecontraint / FGeneralCaracteristiques.NbElements;
LCable := 0;
Distance := CalculerConfigurationCable(0, // tableau de résultats considéré
NoBarre, //FGeneralCaracteristiques.NoBarreEffortConcentre, // numéro de la barre chargée
N_Gauche, // effort normal initial
Alpha_G, // angle initial en radians
LBR, // longueur d'un élément de câble
LCable,
XAtteint, YAtteint,
Alpha_D,
N_Droite
);
if (Distance < DistMini) then DistMini := Distance;
// correction sur la barre
LongueurCable1 := LCable;
CableRavale := (LongueurCable1 - LongueurCable0); // * 0.9;
//DispMessage(Format('L0 = %.2f - L1 = %.2f - r = %.2f', [LongueurCable0, LongueurCable1, CableRavale]));
//LongueurCable0 := LongueurCable0 - CableRavale;
//*)
// end; // for ou while
// nouveau tir
Alpha_G := RandRange(A_Dep - DTR * 25, DTR * 25);
N_Gauche := RandRange(N_Dep, N_Dep *2.0); //RandG(N_Dep, StdDevEffort);
DispMessage(Format('It: %d - Ng = %.0f - A=%.6f -Dist = %.2f',[NbIters, N_Gauche, Alpha_G, DistMini]));
Inc(NbIters);
//if (NbIters > 5000) then Break;
until (DistMini < FGeneralCaracteristiques.PrecisionCalcul);
DispMessage(Format('Itération: %d - Distance = %.2f',[NbIters, DistMini]));
// affichage de la longueur de câble ravalé:
DispMessage(Format('Longueur de câble ravalée: %.2f m',[CableRavale]));
// écrire résultats dans fichier
with TStringList.Create do begin
try
Add('Barre' + TAB + 'Charge' + TAB + 'Longueur' + TAB + 'Angle' + TAB + 'Effort' + TAB + 'X' + TAB + 'Y');
Add('');
for i := 0 to FGeneralCaracteristiques.NbElements do begin
with FConfigurationsCables[0].ResultatsTroncons[i] do begin
Add(Format('%d' + TAB + // barre
'%.3f' + TAB + // Charge
'%.3f' + TAB + // Longueur
'%.5f' + TAB + // Angle
'%.2f' + TAB + // Effort
'%.2f' + TAB + // X extrémité droite
'%.2f' + TAB // Y ext droite
,[
i,
Charge,
B_Prime,
Angle,
Effort,
Xd, Yd
])
);
end;
end;
SaveToFile(ExtractFilePath(ParamStr(0)) + 'miaou.txt');
finally
end;
end;
Result := NbIters;
end;
procedure TTyrolienne.SetCableCotesMinMax(const NoTableau: integer);
var
i : integer;
RT: TValeursCalculeesTroncon;
begin
DispMessage('SetCableCotesMinMax');
FCoteMiniCable := 0;
FCoteMaxiCable := 0;
for i := 1 to FGeneralCaracteristiques.NbElements do begin
RT := GetTronconCalcule(NoTableau, i);
if (RT.Yd > FCoteMaxiCable) then FCoteMaxiCable := RT.Yd;
if (RT.Yd < FCoteMiniCable) then FCoteMiniCable := RT.Yd;
end;
end;
// résultats éléments de câble
function TTyrolienne.GetTronconCalcule(const NoTableau, Idx: integer): TValeursCalculeesTroncon;
var
CFC: TConfigCable;
begin
CFC := FConfigurationsCables[NoTableau];
Result := CFC.ResultatsTroncons[Idx];
end;
// calculer l'angle initial câble déchargé
// par la méthode de Jippé
function TTyrolienne.GetAlphaInitial(const EffortPrecontrainte: double): double;
const
DecrementAngulaireApproche = 0.2 * PI/180.00;
DecrementAngulaireFinition = 0.01 * DecrementAngulaireApproche; // anciennement: 0.001 * ...
var
NbIter : integer;
_N0, _N1 : double;
PoidsCable: double;
Lsur2 : double;
AlphaG,
AlphaD : double;
LgCable : double;
aaa, bbb : double;
procedure CalcsInternesInWhile;
begin
CalcPolynomeByAngle(FGeneralCaracteristiques.Lo,
FGeneralCaracteristiques.Ho,
AlphaG, AlphaD,
aaa,bbb);
LgCable := CalcLengthArcParabole(aaa,bbb,
FGeneralCaracteristiques.Lo);
PoidsCable := LgCable * FGeneralCaracteristiques.ChargeRepartie;
AlphaD := ArcTan(ValueDerivPolynomeForX(aaa,bbb,
FGeneralCaracteristiques.Lo));
_N0:=GetN0(PoidsCable, AlphaG, AlphaD);
_N1:=GetN1(PoidsCable, AlphaG, AlphaD);
end;
begin
_N0:=1e9;
NbIter:=0;
AlphaG:=Arctan(FGeneralCaracteristiques.Ho /
FGeneralCaracteristiques.Lo) -
DecrementAngulaireFinition;
// Itérations d'approche
while(_N0>EffortPrecontrainte) do begin
try
Inc(NbIter);
CalcsInternesInWhile;
AlphaG:=AlphaG - DecrementAngulaireApproche;
except
dispMessage('666');
end; // try
end; // while
// on prépare la finition
AlphaG:=AlphaG + 2 * DecrementAngulaireApproche;
CalcsInternesInWhile;
// Itérations de finition
NbIter:=0;
while(_N0 > EffortPrecontrainte) do begin
try
Inc(NbIter);
CalcsInternesInWhile;
AlphaG:=AlphaG - DecrementAngulaireFinition;
except
DispMessage('666');
end;
end; //while
// résultats
(*
Lsur2:= Lo/2;
fMax := (Ho/Lo) * Lsur2 -
ValuePolynomeForX(a,b, Lsur2); // flèche maxi
LCorde := Hypot(Lo, Ho);
AlphaC := ArcCos(Lo/LCorde);
AlphaM := ArcTan(ValueDerivPolynomeForX(a,b,Lsur2));
N1:=GetN1(PoidsCable,AlphaG, AlphaD);
// affichage de la géométrie du câble
//*)
Result := AlphaG;
end;
// numéro de barre en fonction de X OK.
// A n'utiliser qu'après une détermination.
function TTyrolienne.GetNumeroBarre(const NoTableau: integer; const X: double): integer;
var
i: integer;
B0, B1: TValeursCalculeesTroncon;
begin
Result := -1;
for i:=1 to FGeneralCaracteristiques.NbElements do begin
B0 := GetTronconCalcule(NoTableau, i-1);
B1 := GetTronconCalcule(NoTableau, i);
//DispMessage(Format('%d - %f - %f %f',[I, X, B0.Xd, B1.Xd]));
if (IsInRange(X, B0.Xd, B1.Xd)) then begin
Result := i;
exit;
end;
end;
end;
// position du câble par rapport à l'ancrage
function TTyrolienne.GetDeltaZCable(const NoTableau: integer; const X: double): double;
var
NB: integer;
B0, B1: TValeursCalculeesTroncon;
dx, dy: double;
m : double;
begin
Result := -1E06; // valeur d'erreur
NB := GetNumeroBarre(NoTableau, X);
if (NB=0) then Exit;
B0 := GetTronconCalcule(NoTableau, NB-1);
B1 := GetTronconCalcule(NoTableau, NB);
dx := B1.XD - B0.XD;
dy := B1.YD - B0.YD;
m := dy / dx;
Result := B0.YD +
m * (X - B0.XD) -
FGeneralCaracteristiques.Ho; // cote de l'ancrage
//DispMessage(Format('GetDeltaZCable: %d, %f', [NB, Result]));
end;
end.Unité Pascal de fonctions générales
unit GPFunctions;
interface
uses
SysUtils,
Math,
Classes;
function IsInRange(const V, V1, V2: double): boolean;
// affichage de débug
procedure DispMessage(const Msg: string);
procedure DispMessageMeth(const Obj: TObject; const Meth: string);
// calculs de polynomes (longueurs, paramètres)
// calcul de la longueur développée d'une section de parabole
function CalcLengthArcParabole(const a,b,L: Double): Double;
// calcul des valeurs y pour les polynomes et leurs dérivées
function ValuePolynomeForX(const aa,bb,xx: Double):Double;
function ValueDerivPolynomeForX(const aa,bb, xx: Double): Double;
//calcul du polynome avec angle imposé
procedure CalcPolynomeByAngle(const L,H: Double;
const A0: Double;
var A1: Double;
var aa,bb: Double);
// calcul de la longueur d'un câble
// déterminé par sa parabole*
function CalcLongueurCable(const L, H, A0: double): double;
// calcul de la longueur b' du tronçon déformé
function CalcBPrime(const b, e, T0, T1, Tn: double): double;
// calcul des composantes de b' en fonction de Alpha0 et Alpha1
function AngleMoy(const A0, A1: double): double;
function CalcBPrimeX(const BPrime, Am: double): double;
function CalcBPrimeY(const BPrime, Am: double): double;
// élimination de l'angle Alpha (voir cours)
function CalcEqu101a(const N0, Alpha0, Fx: double): double;
// élimination de l'angle Alpha (voir cours)
function CalcEqu101b(const N0, Alpha0, Fy: double): double;
// effort en extrémité droite de la barre
function CalcN1(const Equ101a, Equ101b: double): double;
// angle pour la barre i
function CalcAlpha1(const Equ101a, Equ101b: double): double;
// calcul des efforts dans le triangle des forces
// Données: angles Alpha0 et Alpha1; force F
// en cas d'erreur, retourne une valeur négative
function GetN1(const F: Double; const Alpha0, Alpha1: Double): Double;
function GetN0(const F: Double; const Alpha0, Alpha1: Double): Double;
// nb aléatoires sur étendue
function RandRange(const Min, Max: double): double;
// constantes physiques
const EPSILON = 1E-12;
const PI_2 = PI/2;
const g = 9.810;
implementation
function IsInRange(const V, V1, V2: double): boolean;
begin
result := (V >= V1) and (V <= V2);
end;
procedure DispMessage(const Msg: string);
begin
WriteLn(msg);
end;
// affichage des infos d'une méthode d'objet
procedure DispMessageMeth(const Obj: TObject; const Meth: string);
begin
WriteLn(Format('%s.%s',[Obj.ClassName, Meth]));
end;
//------------------------------------------------------------------------------
// calcul de la longueur initiale du câble
// L: Longueur travée
// H: Dénivelé
// A0: Angle au départ
function CalcLongueurCable(const L, H, A0: double): double;
var
A1: double;
aa,bb: double;
begin
// calcul du polynome d'équilibre d'une section de câble seul
CalcPolynomeByAngle(L,H, A0, A1, aa,bb);
Result := CalcLengthArcParabole(aa, bb, L);
end;
// calcul de la longueur développée d'une section de parabole
// Ld = Integrale(0, L, sqrt(1+y'²), dx) avec y'= 2.a.x + b
function CalcLengthArcParabole(const a,b,L: Double): Double;
(* -- sous-expressions de la primitive de sqrt(1+(2a.x + b)**2) -- *)
function q2AXB(const aa,bb, XX: Double): Double;
begin
Result:=2*aa*XX + bb;
end;
function qRAC2(const aa, bb, XX: Double): Double;
begin
(* -- utilisation de IntPower(x,n), plus rapide que Power(x,n) -- *)
Result:=Sqrt(1 + IntPower(q2AXB(aa,bb, XX),2));
end;
(* -- primitive de sqrt(1+(2a.x + b)^2) -- *)
function S(const X: Double): Double;
var
M1, M2: Double;
begin
M1:=q2AXB(a,b,X);
M2:=qRAC2(a,b,X);
Result:= (M1*M2 +ln(Abs(4*a*(M1+M2)))) / (4*a);
end;
begin
Result:=S(L) - S(0.00);
end;
// calcul des valeurs y pour les polynomes
function ValuePolynomeForX(const aa,bb,xx: Double):Double;
begin
Result:= xx * (aa * xx + bb);
end;
function ValueDerivPolynomeForX(const aa,bb, xx: Double): Double;
begin
Result:= 2 * aa * xx + bb;
end;
// calcul du câble - Méthode de Lismonde
// 18/07/2008
// calcul de la longueur b' du tronçon déformé
// si erreur > longueur négative
function CalcBPrime(const b, e, T0, T1, Tn: double): double;
var T: Double;
begin
try
//DispMessage(Format('e = %f - T0 = %f T1 = %f TM = %f',[e, T0, T1, Tm]));
//T := (T0 + T1)/2; // tension moyenne /(2*Tm)
T := (T1+T0)/2; //
//T := T/Tm;
Result := b * (1 + (e / Tn) * T);
//Result := b;
except
Result :=-1.0;
end;
end;
// calcul des composantes de b' en fonction de Alpha0 et Alpha1
function AngleMoy(const A0, A1: double): double;
begin
Result := (A0 + A1) / 2;
end;
function CalcBPrimeX(const BPrime, Am: double): double;
begin
Result := BPrime * cos(Am);
end;
function CalcBPrimeY(const BPrime, Am: double): double;
begin
Result := BPrime * sin(Am);
end;
// élimination de l'angle Alpha (voir cours)
function CalcEqu101a(const N0, Alpha0, Fx: double): double;
begin
Result := N0 * cos(Alpha0) + Fx;
end;
// élimination de l'angle Alpha (voir cours)
function CalcEqu101b(const N0, Alpha0, Fy: double): double;
begin
Result := N0 * sin(Alpha0) + Fy;
end;
// effort en extrémité droite de la barre
function CalcN1(const Equ101a, Equ101b: double): double;
begin
Result := Hypot(Equ101a, Equ101b);
end;
// angle pour la barre i
function CalcAlpha1(const Equ101a, Equ101b: double): double;
begin
Result := ArcTan(Equ101b/Equ101a);
end;
//------------------------------------------------------------------------------
//********************************************
// calcul du polynome d'équilibre d'une section de câble seul
procedure CalcPolynomeByAngle(const L,H: Double;
const A0: Double;
var A1: Double;
var aa,bb: Double);
var
TanA0: Double;
begin
TanA0 := tan(A0);
aa:=(H - TanA0*L)/(L*L);
bb:=TanA0;
A1:=ArcTan(ValueDerivPolynomeForX(aa,bb,L));
end;
// calcul des efforts dans le triangle des forces
// Données: angles Alpha0 et Alpha1; force F
// en cas d'erreur, retourne une valeur négative
function GetN1(const F: Double; const Alpha0, Alpha1: Double): Double;
var
DT:Double;
begin
Result:=-1.690;
DT:= Alpha1 - Alpha0;
if (Abs(DT)<EPSILON) then Exit;
//Result:=F * sin(PI_2 + Alpha0) / sin(DT);
Result:=F * sin(Alpha0 + PI_2) / sin(Alpha1 - Alpha0);
end;
//-------------------------------
function GetN0(const F: Double; const Alpha0, Alpha1: Double): Double;
var
DT:Double;
begin
Result:=-1.690;
DT:= Alpha1 - Alpha0;
if (Abs(DT)<EPSILON) then Exit;
Result:=F * sin(PI_2 - Alpha1) / sin(Alpha1 - Alpha0);
end;
// nombres aléatoires sur étendue
function RandRange(const Min, Max: double): double;
begin
Result := Min +
Random * (Max - Min);
end;
end.

Aide




