Sbaglierò, ma quello non è un codice nativo di VB.
Appartiene a qualche libreria o algoritmo di ingeneria e dovrebbe essere legato al calcolo su strutture 3D del dominio di rottura su una sezione.
Su questo, ritengo che un ingegnere civile del forum possa darti una mano.
In generale "REDIM" in VB è equivalente a "SetLength" in Pascal.
La scrittura "1 To MomentiRottura.polix(NP).numv" equivale alla definizione di un array. Però senza una definizione del contenuto dell'array non è possibile definire l'array stesso.
Come dato generico, la scrittura potrebbe essere equivalente a:
// ATTTENZIONE CHE IN PASCAL GLI ARRAY DINAMICI (CHE SONO GLI UNICI CHE POSSONO ESSERE RIDIMENSIONATI) INIZIANO CON INDICE 0 E NON 1.
// QUINDI L'ARRAY sotto indicato avà un indice in più, ossia lo zero.
SetLength(MomentiRottura.polix[NP].X, MomentiRottura.polix[NP].numv+1);
Avendo sempre messo dati nativi dentro gli array, o oggetti che dovevo passare ad altri pezzi di software, non mi sono mai posto la questione se :
Viene invocato il "finalize" degli elementi se rimpicciolisco l'array?
Se allarghi l'array non hai problemi di questo tipo. Ti prepara degli spazi "vuoti" da assegnare come preferisci.
[0..Length-1] sono gli indici validi.
In alternativa puoi usare Low(tuoArray) e High(tuoArray) per avere gli indici minori e superiori validi.
Se vuoi ancora meno sbattimenti puoi usare gli enumeratori automatici.
Dichiari una variabile del tipo che ti interessa e la usi nel ciclo for che diventa
for variabileDelTipoCheTiInteressa in ilTuoArray do
begin
end;
Spero di essere stato d'aiuto.
Stilgar
Stilgar
Ciao
Solo qualche piccolo accorgimento nel codice.
type
TNumeroValoriMassimo = 0..100; //<-- Dichiari solo una volta l'insieme, se hai bisogno di ridimensionare l'insieme, tocchi qui e ricompili.
type
// Struttura dati che contiene i valore dei momenti di rottura della sezione //
// -------------------------------------------------------------------------- //
TMomentiRottura = record
mrx: double; // Momento di rottura con asse momento x
mry: double; // Momento di rottura con asse momento y
ang: double; // Rotazione dell//asse neutro rispetto all//asse x, antioraria positiva
polix: array of poligono_sezione; // Poligono che definisce la porzione di cls compressa della sezione
sigmaSo: array of double; // ' Array contenente le tensioni nelle barre di armatura a rottura
sigmaPp: array of double; // ' Array contenente le tensioni nei trefoli a rottura
def_rottura: deform_sezione; // configutrazione deformativa a rottura
etacMax: double; // distanza tra l//asse neutro e la fibra maggiormente compressa a rottura
etasMin: double; // distanza tra l//asse neutro e la fibra maggiormente tesa a rottura
curvRottura: double; // curvatura della sezione a rottura
end;
// Struttura dati in cui sono definiti i dati dei singoli poligoni che com- //
// pongono la sezione //
// -------------------------------------------------------------------------- //
TPoligonoSezione = record
x: array[TNumeroValoriMassimo] of double; // coordinata x del vertice
y: array[TNumeroValoriMassimo] of double; // coordinata y del vertice
numv: integer; // numero di vertici del poligono
fck: double; //' fck
fd: double; // Resistenza massima di calcolo (per verifiche SLU)
omog: double; // coefficiente di omogeneizzazione (per verifiche SLE)
traz: boolean; // 0=non reagente a trazione; 1=reagente a trazione
epsc0: double; // Deformazione in corrispondenza della fine della parte parabola/lineare del dominio
epscu: double; // Deformazione ultima del dominio
sigma: array[TNumeroValoriMassimo] of double;
end;
Personalmente eviterei di utilizzare le stringhe nel case. Utilizzerei degli indici.
Utilizzando una combo box puoi ottenere l'indice dell'opzione selezionata attraverso . Restituisce -1 Se non è selezionato nulla.
procedure TForm1.calcoloGeometria1;
var
tipo1: integer;
begin
// -------------------------------------------------------------------------- //
//'carica geometria 1 *********************************************************
tipo1 := Form1.CB1.Index;// <-- Il cb mi fa supporre sia una combo box
case (tipo1) of
indiceTrave:
begin
tipogetto[1] := Trave;
nv[1] := StrToInt(Form1.EVertici1.Text);
for k := 1 to nv[1] do
begin
X1[k] := StrToFloat(Form1.StringGrid1.Cells[1, k]);
Y1[k] := StrToFloat(Form1.StringGrid1.Cells[2, k]);
end;
fck := StrToInt(Form1.CBcls1.Text);
end;
indiceGetto2aFase:
begin
tipogetto[1] := Getto;
nv[1] := StrToInt(Form1.EVertici1.Text);
for k := 1 to nv[1] do
begin
X1[k] := StrToFloat(Form1.StringGrid1.Cells[1, k]);
Y1[k] := StrToFloat(Form1.StringGrid1.Cells[2, k]);
end;
fck := StrToInt(Form1.CBcls1.Text);
end;
indiceForo:
begin
tipogetto[1] := Foro;
nv[1] := StrToInt(Form1.EVertici1.Text);
for k := 1 to nv[1] do
begin
X1[k] := StrToFloat(Form1.StringGrid1.Cells[1, k]);
Y1[k] := StrToFloat(Form1.StringGrid1.Cells[2, k]);
end;
fck := StrToInt(Form1.CBcls1.Text);
end;
end;
end;
//******************************************************************************
@alexarmato66
Ciao, ma quindi esaminando la riga
type
TNumeroValoriMassimo = 0..100; //<-- Dichiari solo una volta l'insieme, se hai bisogno di ridimensionare l'insieme, tocchi qui e ricompili
il tuo programma è limitato a 101 campi..... :(
Non ti conviene usare oggetti/elementi dinamici (io, personalmente, uso solo array dinamici per le matrici usate nei calcoli) in modo da non avere questa limitazione? Anche perchè leggo "...se hai bisogno di ridimensionare l'insieme, tocchi qui e ricompili." il che ti costringe a nuove compilazioni ogni volta che devi ridimensionare questo insieme.
Era solo un suggerimento, per il resto ottimo lavoro.
In modo simile a quanto già suggerito:
Type
TDominio_slu = record
mrx: array of ??????????? <---- definire il tipo
end;
//Nel codice
var dominio_slu: TDominio_slu;
SetLength(dominio_slu.mrx, NMaxDom+1); //L'array parte de 0 non da 1
esiste STEP in Lazarus?:
esempio
For Y = yn + dX / 2# To ymaxpe Step dX
No, non esiste. L'incremento della variabile di controllo è sempre di 1.
Si può ovviare con la funzione while o la funzione repeat.
Y := yn + dx /2;
while (Y <= ymaxpe) do
begin
//Inserisci qui il tuo codice
//alla fine incrementa la variabile di controllo
Y := Y + dx;
end;
Alex.
Cosa intendi di preciso per wrapper? Io ho un'idea, magari non vorrei capire male quello che chiedi.
In Freepascal hai la possibilità di mettere dei metodi nei record.
Devi attivare i record "cazzuti" con alcune direttive del compilatore.
Forse non ti serve un wrapper.
{$ModeSwitch advancedrecords}
{$ModeSwitch typehelpers}
type
TPunto = record
x, Y : Double;
end;
TPoligono = record
punti : array of TPunto;
class operator Initialize(var aRec: TPoligono ); //<- "costruttore" del record
class operator Finalize(var aRec: TPoligono ); //<- "distruttore" del record
procedure aggiungiPunto(const punto : TPunto);
function isPuntoIncluso(const pt : TPunto) : boolean;
end;
Se fa la copia dei valori nello stack così.procedure Calcolo_precompressione(N_ As :Double; Mx_ As:Double; My_ : Double, _nd : Double; Mx : Double, My : Double);
se passa un "riferimento" senza copiare nello stack i valori, ma depositando i puntatori alle variabili:
procedure Calcolo_precompressione(var N_ As :Double; var Mx_ As:Double; var My_ : Double; var _nd : Double; Mx : Double, My : Double);
Stilgar
Dovrebbe funzionare, verifica che l'estensione degli array x e Y siano [0..numv] o [1..numv], altrimenti si dovrebbe usare:
for k:=1 to polic[np].numv - 1 do
L'importante è che le variabili "polic" e "poli" non siano mai state assegnate direttamente se non tramite assegnazione tra i singoli membri.
***EDIT: effettua lo stesso controllo anche per "For np := 1 To N_POLI do"
N.B.: ricordati nei post di inserire il codice marcandolo con il tasto # (inserisce il tag code).
Ho provato così ma no riesco a copiare le coordinate dalla struttura poli a polic:
# setlength(polic,N_POLI+1);
# c := Cos(alfa) ;
# s := Sin(alfa) ;
# For np := 1 To N_POLI do
# begin
# polic[np].numv := poli[np].numv;
# For k := 1 To polic[np].numv do
# begin
# polic[np].x[k] := poli[np].x[k] * c + poli[np].y[k] * s ; //SI PIANTA QUI
# polic[np].y[k] := -poli[np].x[k] * s + poli[np].y[k] * c ;
# end;
# end;
le strutture sono :
#// -------------------------------------------------------------------------- //
# poligono_sezione = record
# x:array of Double ; // coordinata x del vertice
# y:array of Double ; // coordinata y del vertice
# numv : Integer; // numero di vertici del poligono
# fck : Double; //' fck
# fd : Double ;
# omog : Double ;
# traz : Integer ;
# epsc0 : Double;
# epscu : Double; // Deformazione ultima del dominio
# sigma:array of Double ;
# end ;
#// -------------------------------------------------------------------------- //
# poligono_sezione_c = record
# x:array of Double ; // coordinata x del vertice
# y:array of Double ; // coordinata y del vertice
# numv : Integer; // numero di vertici del poligono
# fck : Double; //' fck
# fd : Double ; # omog : Double ;
# traz : Integer ;
# epsc0 : Double;
# epscu : Double; // Deformazione ultima del dominio
# sigma:array of Double ;
# end ;
#// -------------------------------------------------------------------------- //
Ho provato così ma no riesco a copiare le coordinate dalla struttura poli a polic:
# setlength(polic,N_POLI+1);
# c := Cos(alfa) ;
# s := Sin(alfa) ;
# For np := 1 To N_POLI do
# begin
# polic[np].numv := poli[np].numv;
# For k := 1 To polic[np].numv do
# begin
# polic[np].x[k] := poli[np].x[k] * c + poli[np].y[k] * s ; //SI PIANTA QUI
# polic[np].y[k] := -poli[np].x[k] * s + poli[np].y[k] * c ;
# end;
# end;
le strutture sono :
#// -------------------------------------------------------------------------- //
# poligono_sezione = record
# x:array of Double ; // coordinata x del vertice
# y:array of Double ; // coordinata y del vertice
# numv : Integer; // numero di vertici del poligono
# fck : Double; //' fck
# fd : Double ;
# omog : Double ;
# traz : Integer ;
# epsc0 : Double;
# epscu : Double; // Deformazione ultima del dominio
# sigma:array of Double ;
# end ;
#// -------------------------------------------------------------------------- //
# poligono_sezione_c = record
# x:array of Double ; // coordinata x del vertice
# y:array of Double ; // coordinata y del vertice
# numv : Integer; // numero di vertici del poligono
# fck : Double; //' fck
# fd : Double ; # omog : Double ;
# traz : Integer ;
# epsc0 : Double;
# epscu : Double; // Deformazione ultima del dominio
# sigma:array of Double ;
# end ;
#// -------------------------------------------------------------------------- //
Non serve definire due record distinti, sono identici quindi basta definirne uno solo. La dichiarazione delle variabili può avvenire tranquillamente con lo stesso record.
N.B.: per ragioni di leggibilibiltà, conviene che i nuovi tipi (come i record da te definiti) abbiano il prefisso T iniziale, ad esempio TPoligono_Sezione, ma è solo uno stile di scrittura.
var
polic, poli: poligono_sezione;
//da qualche parte devi effettuare il setlength dei singoli array:
setlength(polic,N_POLI+1); //questo lo fai già
//setlength(poli,N_POLI+1); // <= già fatto ???
//Questo blocco lo puoi eseguire ogni qualvolta ti serve ridimensionare gli array
For np := 0 To N_POLI do // <= qui sarebbe meglio: For np:= low(polic) to high(polic) do
begin
//numv !!!!!!!!!!!! deve essere dichiarato e settato ovviamente PRIMA DI usarlo qui
setlength(polic[np].X, numv+1); //SERVE AD ALLOCARE LO SPAZIO PER GLI ARRAY DINAMICI ..... DEVE ESSERE FATTO PRIMA DI USARLI
setlength(polic[np].Y, numv+1);
setlength(polic[np].Sigma, numv+1); //Ci ho messo anche sigma !!! non sò se la lunghezza è sempre quella
//setlength(poli[np].X, numv+1); // <= già fatto ???
//setlength(poli[np].Y, numv+1); // <= già fatto ???
//setlength(poli[np].Sigma, numv+1); // <= già fatto ???
end;
da qualche altra parte:
//Calcolo
For np := 1 To N_POLI do
begin
polic[np].numv := poli[np].numv; // ATTENZIONE CHE poli[np].numv deve essere già impostato e poli[] e polic[] già con un setlength effettuato con gli array X e Y anche quelli con un setlength come da blocco sopra
For k := 1 To polic[np].numv do
begin
polic[np].x[k] := poli[np].x[k] * c + poli[np].y[k] * s ; //SI PIANTA QUI
polic[np].y[k] := -poli[np].x[k] * s + poli[np].y[k] * c ;
end;
end;
I record in pascal, in realtà è una "ficture" introdotta da FPC e Delphi e non fà parte del Pascal standard, possono avere anche dei metodi usati normalmente per la "manutenzione" dei singoli membri .... ad esempio potresti avere un metodo che esegue il "setlength" di tutti i membri necessari senza dover chaimare a codice esplicito il "for" indicato nel post precedente:
...... (segue esempio) ......
type
TProva = record
X: array of integer;
procedure NuovaLunghezza(Value: cardinal);
end;
var
Prova: TProva;
procedure TProva.NuovaLunghezza(Value: cardinal);
begin
SetLength(X, Value);
end;
begin
//Come usarla nel codice
Prova.NuovaLunghezza(10);
end;
L'array sopra citato (polic) quando lo passerò ad una funzione tipo:
Function risult_compr(var polic:array of poligono_sezione; armco : armo_sezione;armcp:armp_sezione ; deform : deform_sezione; ymax : Double; yamin : Double; yn : Double) : risultante_n;
come lo dovrei passare. Poi all'interno della funzione devo sempre ridimensionare i vari array passati o dipende
da come li passo( var o valore)
Ho provato a scrivere la seguente procedura che chiama un'altra procedura.La cosa strana che alla fine
dell'esecuzione della seconda procedura c'è un ritorno alla prima procedura senza un apparente motivo:
1a procedura:
Procedure calcola_MomentiRottura( dom : Dominio_Rottura; soll : soll_esterne; MomentiRottura : momenti_rottura;flag_convergenza : Boolean; flag_circa : Boolean; index : Integer);
var
tipo_conv : integer;
begin
tipo_conv := StrtoInt(Form1.CBconverg.Text);
case (tipo_conv) of
1: begin // Approssimato
calcola_MomentiRottura_A(dom, soll, MomentiRottura, flag_convergenza, flag_circa, index) ;
end;
2: begin // Bisezione
calcola_MomentiRottura_B(dom, soll, MomentiRottura, flag_convergenza, flag_circa, index) ;
end;
end;
end;
2a procedura
Procedure calcola_MomentiRottura_A(dom : Dominio_Rottura; soll : soll_esterne; MomentiRottura : momenti_rottura;flag_convergenza : Boolean; flag_circa : Boolean; index : Integer); ...........
la seconda procedura esegue correttamente il calcolo ma poi ritornando alla prima procedura i valori si azzerano.
Le strutture sono:
dominio_rottura = record
nd : Double; // Sforzo normale con cui si determinano i vari momenti di rottura
mrx:array of Double ; // vettore con i valori dei momenti Mrx del dominio
mry:array of Double ; // vettore con i valori dei momenti Mry del dominio
ang:array of Double ; // vettore con i valori dell//inclinazione sull//orizzontale dell//asse neutro in radianti, rotazione antioraria positiva
nrc:array of Double ; // vettore con valori dello sfozo normale nella parte compressa della sezione a rottura
nrt:array of Double ; // vettore con valori dello sforzo normale nella parte in trazione della sezione a rottura
xrc:array of Double ; // posizione della risultante dello sforzo di compressione
yrc:array of Double ; // (nel sistema di riferimento cartesiano della sezione)
xrt:array of Double ; // posizione della risultante dello sforzo di trazione
yrt:array of Double ; // (nel sistema di riferimento cartesiano della sezione)
epsc:array of Double ; // vettore con le deformazioni limite della fibra più compressa
epss:array of Double ; // vettore con le deformazioni limite della barra di armatura più distante dall//asse neutro
yn:array of Double ; // posizione asse neutro (nel sistema ruotato di ogni singola verifica)
curv:array of Double ; // Curvatura della deformazione della sezione
End ;
oll_esterne =record
N : Double ; // Sforzo normale: positovo se di compressione
Mx : Double ; // Momento flettente asse momento X: positivo se comprime fibra Y+
My : Double ; // Momento flettente asse momento Y: positivo se comprime fibra X+
End;
momenti_rottura = record
mrx : Double; // Momento di rottura con asse momento x
mry : Double; // Momento di rottura con asse momento y
ang : Double; // Rotazione dell//asse neutro rispetto all//asse x, antioraria positiva
polix : Array of poligono_sezione; // Poligono che definisce la porzione di cls compressa della sezione
sigma_so: Array of Double; // ' Array contenente le tensioni nelle barre di armatura a rottura
sigma_sp: Array of Double; // ' Array contenente le tensioni nei trefoli a rottura
def_rottura : deform_sezione; // configutrazione deformativa a rottura
etac_max : Double; // distanza tra l//asse neutro e la fibra maggiormente compressa a rottura
etas_min : Double; // distanza tra l//asse neutro e la fibra maggiormente tesa a rottura
curv_rottura : Double; // curvatura della sezione a rottura
End ;
La chiamante :
Procedure calcola_MomentiRottura( dom : Dominio_Rottura; soll : soll_esterne; MomentiRottura : momenti_rottura;flag_convergenza : Boolean; flag_circa : Boolean; index : Integer);
var
tipo_conv : integer;
begin
tipo_conv := StrtoInt(Form1.CBconverg.Text);
case (tipo_conv) of
1: begin // Approssimato
calcola_MomentiRottura_A(dom, soll, MomentiRottura, flag_convergenza, flag_circa, index) ;
end;
2: begin // Bisezione
calcola_MomentiRottura_B(dom, soll, MomentiRottura, flag_convergenza, flag_circa, index) ;
end;
{ 3: begin // Secante
calcola_MomentiRottura_C(dom, soll_SLU, MomentiRottura, flag_convergenza, flag_circa, index) ;
end;
}//questa devo ancora implementarla
end;
end;
La chiamata :
Procedure calcola_MomentiRottura_A(dom : Dominio_Rottura; soll : soll_esterne; MomentiRottura : momenti_rottura;flag_convergenza : Boolean; flag_circa : Boolean; index : Integer);
{
'flag_convergenza --> se TRUE convergenza della funzione e restituzione risultati precisi, se FALSE la funzione non è andata a convergenza
'flag_circa --> se TRUE vuol dire che la funzione non è andata a convergenza ma restituisce comunque un risultato conservativo
'se il flag_convergenza = FALSE ed il flag_circa = FALSE significa che non vengono restituiti valori accettabili, la funzione è fallita completamente
'index --> indice del primo punto del segmento del dominio in cui vi è la intersezione con la retta passante per [O.x, O.y] ed [soll.Mx soll.My]
'utile nel caso di fallimento della convergenza per infittire eventualmente i punti del dominio localmente e ritentare il calcolo }
var
i : Integer ; // 'contatore generico
ip1 : Integer ; // 'i+1
k : Integer; // 'contatore generico
kp1 : Integer; // 'k+1
O : TipoPunto ; // 'punto origine della retta di sollecitazione
Mx_My : TipoPunto ; // 'punto che definise la retta di sollecitazione
D_R_1 : TipoPunto; // 'punto iniziale del generico segmento del dominio
D_R_2 : TipoPunto ; // 'punto finale del generico segmento del dominio
retta_soll : TipoSegmento; // 'retta di sollecitazione
seg_dom : TipoSegmento; // 'generico segmento del dominio
P_int : TipoPunto ; // 'punto di intersezione tra retta di sollecitazione e dominio di rottura
P_int0 : TipoPunto ; // 'punto di intersezione tra retta di sollecitazione e dominio di rottura
np : Integer ; // 'contatore poligoni
polic: array of poligono_sezione; //'poligono copia che viene ruotato e sottoposto ad elaborazione
//polic:array[0..3] of poligono_sezione ;
armco : armo_sezione ; // 'armature copia che vengono ruotate e sottoposte ad elaborazione
armcp : armp_sezione ; // 'armature copia che vengono ruotate e sottoposte ad elaborazione
Nfin : risultante_n_finale ; // 'risultante degli sforzi ad asse neutro individuato
ymax : Double ; // 'ordinata massima dei vertici della sezione
yamin : Double ; // 'ordinata minima delle armature
deformazione : Double ;
x_provv : Double ; // 'ascissa provvisoria
y_provv : Double ; // 'ordinata provvisoria
r0 : Double ;
alfa : Double ;
Mrx_alfa : Double ;
Mry_alfa : Double ;
r_alfa : Double ;
alfa1 : Double ;
Mrx_alfa1 : Double ;
Mry_alfa1 : Double ;
r_alfa1 : Double ;
alfa2 : Double ;
Mrx_alfa2 : Double ;
Mry_alfa2 : Double ;
r_alfa2 : Double ;
c : Double; // 'variabile temporanea
s : Double; // 'variabile temporanea
D : Double ;
DeltaP_dom : Double ;
D0 : Double ;
d1 : Double;
d2 : Double ;
label
continua;
begin
SetLength(polic, N_POLI+1); //ReDim polic(N_POLI)
SetLength(MomentiRottura.polix, N_POLI+1); //ReDim MomentiRottura.polix(N_POLI)
SetLength(MomentiRottura.sigma_so, arm.numarm+1); //ReDim MomentiRottura.sigma_so(arm.numarm)
SetLength(MomentiRottura.sigma_sp, armp.numarm+1); // ReDim MomentiRottura.sigma_sp(armp.numarm)
// imposto di default false (convergenza fallita)
flag_convergenza := False;
// imposto di default false (risultato corretto)
flag_circa := False;
// 'If Abs(soll.My) > Abs(soll.Mx) Then
//' r0 = soll.Mx / soll.My
//'Else
//' r0 = soll.My / soll.Mx
//'End If
//'If Not soll.Mx = 0# Then
//' r0 = soll.My / soll.Mx
//'Else
//' r0 = Sgn(soll.My) * 100000000#
//'End If
//controllo se O è interno al dominio, se sì esiste un unico punto di intersezione col dominio
If Punto_Interno_poligonoB(0, 0, dom.mrx, dom.mry, NMaxDom) = 4 Then
begin
O.X := 0 ;
O.Y := 0;
Mx_My.X := soll.Mx ;
Mx_My.Y := soll.My ;
retta_soll.start := O ;
retta_soll.ends := Mx_My ;
For i := 1 To NMaxDom do
begin
If i = NMaxDom Then
begin
ip1 := 1 ;
end
Else
begin
ip1 := i + 1 ;
end;
D_R_1.X := dom.mrx[i];
D_R_1.Y := dom.mry[i];
D_R_2.X := dom.mrx[ip1];
D_R_2.Y := dom.mry[ip1];
seg_dom.start := D_R_1 ;
seg_dom.ends := D_R_2 ;
If IntersezRettaSegmento(retta_soll, seg_dom, P_int) = True Then
begin
If (sign(P_int.x) = sign(soll.Mx)) And (sign(P_int.y) = sign(soll.My)) Then
begin
// 'alfa1 = dom.ang(i): alfa2 = dom.ang(ip1)
// 'alfa = (alfa1 + alfa2) / 2
index := i; //'indice del punto corrente del dominio
GoTo continua ;
end ;
end;
end;
end
Else
begin
// 'se il punto sollecitante è fuori dal dominio non è verificato
If Punto_Interno_poligonoB(soll.Mx, soll.My, dom.mrx, dom.mry, NMaxDom) = 1 Then Exit;
O.X := 0;
O.Y := 0;
Mx_My.X := soll.Mx ;
Mx_My.Y := soll.My ;
retta_soll.start := O ;
retta_soll.ends := Mx_My ;
For i:= 1 To NMaxDom do
begin
If i = NMaxDom Then
begin
ip1 := 1 ;
end
Else
begin
ip1 := i + 1 ;
end;
D_R_1.X := dom.mrx[i] ;
D_R_1.Y := dom.mry[i] ;
D_R_2.X := dom.mrx[ip1] ;
D_R_2.Y := dom.mry[ip1] ;
seg_dom.start := D_R_1 ;
seg_dom.ends := D_R_2 ;
If IntersezRettaSegmento(retta_soll, seg_dom, P_int) = True Then
begin
If (sign(P_int.X) = sign(soll.Mx)) And (sign(P_int.Y) = sign(soll.My)) Then
begin
//'alfa1 = dom.ang(i): alfa2 = dom.ang(ip1)
// 'alfa = (alfa1 + alfa2) / 2
index := i; //'indice del punto corrente del dominio
//'verifico se esiste anche un altro punto di intersezione col dominio
// 'dallo stesso lato.
// '(questo succede nel caso di domini scostati dall'origine degli assi,
// 'capita quando ci si aprossima a +Nmax o -Nmax, oppure anche nel
// 'caso di alcuni profili particolari)
D0 := (sqr(soll.Mx) + sqr(soll.My)) ;
d2 := (sqr(P_int.X) + sqr(P_int.Y)) ;
For k := i To NMaxDom do
begin
If k = NMaxDom Then
begin
kp1 := 1;
end
Else
begin
kp1 := k + 1 ;
end;
D_R_1.X := dom.mrx[k] ;
D_R_1.Y := dom.mry[k] ;
D_R_2.X := dom.mrx[kp1] ;
D_R_2.Y := dom.mry[kp1];
seg_dom.start := D_R_1 ;
seg_dom.ends := D_R_2 ;
If IntersezRettaSegmento(retta_soll, seg_dom, P_int0) = True Then
begin
If (sign(P_int0.X) = sign(soll.Mx)) And (sign(P_int0.Y) = sign(soll.My)) Then
begin
d1 := (sqr(P_int0.X) + sqr(P_int0.Y)) ;
//'memorizzo il punto più distante da O
If d1 > d2 Then
begin
P_int := P_int0 ;
//'alfa1 = dom.ang(k): alfa2 = dom.ang(kp1)
//'alfa = (alfa1 + alfa2) / 2
index := k; //'indice del punto corrente del dominio
End ;
End ;
End ;
end;
GoTo continua ;
End ;
End ;
end; // fine for i:=1 to.....
end;
//'non ci sono intersezioni valide col poligono del dominio
Exit;
continua:
//'indica soluzione aprossimata
flag_circa := True;
//'convergenza secca sempre possibile
flag_convergenza := True;
//'calcoliamo col metodo secco di GIARIA recupernando index
i := index ;
If i = NMaxDom Then
begin
ip1 := 1;
end
Else
begin
ip1 := i + 1;
end;
D_R_1.X := dom.mrx[i] ;
D_R_1.Y := dom.mry[i] ;
D_R_2.X := dom.mrx[ip1] ;
D_R_2.Y := dom.mry[ip1];
alfa1 := dom.ang[i];
alfa2 := dom.ang[ip1];
If alfa2 < alfa1 Then
begin
alfa2 := alfa2 + 2 * pi;
end;
D := sqrt(sqr(P_int.x - D_R_1.x) + sqr(P_int.y - D_R_1.y)) ;
DeltaP_dom := sqrt(sqr(D_R_2.x - D_R_1.x)+ sqr(D_R_2.y - D_R_1.y));
alfa := alfa1 + (alfa2 - alfa1) * D / DeltaP_dom ;
//'calcola momenti resistenti con alfa
Mr_alfa (dom, soll, alfa, polic , armco, armcp, Nfin, ymax, yamin, mrx_alfa, mry_alfa, r_alfa );
If alfa > (2 * pi) Then
begin
alfa := (alfa - 2)* pi;
end;
MomentiRottura.ang := alfa;
MomentiRottura.mrx := Mrx_alfa;
MomentiRottura.mry := Mry_alfa ;
MomentiRottura.def_rottura.epsa := Nfin.epsc ;
MomentiRottura.def_rottura.epsb := Nfin.epss ;
MomentiRottura.curv_rottura := Nfin.epsc / (ymax - Nfin.yn) ;
MomentiRottura.etac_max := ymax - Nfin.yn ;
MomentiRottura.etas_min := yamin - Nfin.yn ;
// Calcola una sola volta cos(alfa) e sin(alfa) per evitare elaborazione ogni volta
c := Cos(alfa) ;
s := Sin(alfa) ;
//vengono calcolate le tensioni nelle barre di armatura a rottura
// setlength( armco.y,arm.numarm+1);
// setlength( arm.fyd,arm.numarm+1);
For i := 1 To arm.numarm do
begin
deformazione := Nfin.epsc * (armco.y[i] - Nfin.yn) / (ymax - Nfin.yn) ;
MomentiRottura.sigma_so[i] := elast_plast_indef(deformazione, arm.fyd[i], E_arm);
end;
For i := 1 To armp.numarm do
begin
deformazione := Nfin.epsc * (armcp.y[i] - Nfin.yn) / (ymax - Nfin.yn);
MomentiRottura.sigma_sp[i] := elast_plast_indefps(deformazione + armp.def_prec[i], armp.fyd[i], E_armp);
end;
//'viene individuato il poligono che delimita la porzione compressa
//'Calcola una sola volta Cos(alfa) e Sin(alfa) per evitare elaborazione ogni volta
c := Cos(alfa) ;
s := Sin(alfa) ;
//'viene individuato il poligono che delimita la porzione compressa
For np := 1 To N_POLI do
begin
MomentiRottura.polix[np].numv := 0 ;
For i := 1 To polic[np].numv do
begin
If i = polic[np].numv Then
begin
ip1 := 1 ;
end
Else
begin
ip1 := i + 1;
end;
If (polic[np].y[i] >= Nfin.yn) Then
begin
MomentiRottura.polix[np].numv := MomentiRottura.polix[np].numv + 1 ;
// ReDim Preserve MomentiRottura.polix(np).X(1 To MomentiRottura.polix(np).numv)
SetLength(MomentiRottura.polix[np].x, MomentiRottura.polix[np].numv+1);
// ReDim Preserve MomentiRottura.polix(np).Y(1 To MomentiRottura.polix(np).numv)
SetLength(MomentiRottura.polix[np].y, MomentiRottura.polix[np].numv+1);
//ReDim Preserve MomentiRottura.polix(np).sigma(1 To MomentiRottura.polix(np).numv)
SetLength(MomentiRottura.polix[np].sigma, MomentiRottura.polix[np].numv+1);
MomentiRottura.polix[np].x[MomentiRottura.polix[np].numv] := poli[np].x[i] ;
MomentiRottura.polix[np].y[MomentiRottura.polix[np].numv] := poli[np].y[i] ;
deformazione := Nfin.epsc * (polic[np].y[i] - Nfin.yn) / (ymax - Nfin.yn) ;
MomentiRottura.polix[np].sigma[MomentiRottura.polix[np].numv] := parabola_rett(deformazione, polic[np].epsc0, polic[np].fd) ;
end;
If (sign(polic[np].y[i] - Nfin.yn)) <> (sign(polic[np].y[ip1] - Nfin.yn)) Then
begin
MomentiRottura.polix[NP].numv := MomentiRottura.polix[np].numv + 1;
//'vengono prima individuate le coordinate del poligono ruotato
x_provv := polic[np].x[i] + (polic[np].x[ip1] - polic[np].x[i]) * (Nfin.yn - polic[np].y[i]) / (polic[np].y[ip1] - polic[np].y[i]) ;
y_provv := Nfin.yn;
//'le coordinate appena trovate vengono quindi ruotate e riportate rispetto al sistema di riferimento originario
//ReDim Preserve MomentiRottura.polix(NP).X(1 To MomentiRottura.polix(NP).numv)
//ReDim Preserve MomentiRottura.polix(NP).Y(1 To MomentiRottura.polix(NP).numv)
//ReDim Preserve MomentiRottura.polix(NP).sigma(1 To MomentiRottura.polix(NP).numv)
SetLength(MomentiRottura.polix[np].x, MomentiRottura.polix[np].numv+1);
SetLength(MomentiRottura.polix[np].y, MomentiRottura.polix[np].numv+1);
SetLength(MomentiRottura.polix[np].sigma, MomentiRottura.polix[np].numv+1);
MomentiRottura.polix[np].x[MomentiRottura.polix[np].numv] := x_provv * c - y_provv * s ;
MomentiRottura.polix[np].y[MomentiRottura.polix[np].numv] := x_provv * s + y_provv * c ;
End;
end; //Next i
end;//Next NP
end;
:)RISOLTO!!!
Dovevo semplicemente passare certi valori come riferimento!!:
Procedure calcola_MomentiRottura_A( dom : Dominio_Rottura; soll : soll_esterne;var MomentiRottura : momenti_rottura;flag_convergenza : Boolean; flag_circa : Boolean; index : Integer);