Angolo della seconda retta tangente

Eh, capita a tutti (credo) quando passi da uno strumento ad un altro (vale per i CAD come per i linguaggi)
Man mano che … traduci, pero’ impari come fare con Python e poco per volta avrai sempre meno cose da tradurre-per-imparare … :slight_smile:
… Direi che la soluzione e’ … imparare diversi linguaggi, cosi’ non tenderai piu’ a ragionare sempre secondo un unico schema … :smile:

Teoricamente si’, ci sono sempre gli errori di arrotondamento.
Pero’, dato che Rhino, a quanto ne so, usa i numeri floating point a 64 bit che hanno una precisione di circa 14 cifre, per avere errori apprezzabiil devi fare molte, ma molte rotazioni. :wink:

In ogni caso puoi evitare il problema alla radice: tu parti sempre dallo stesso piano e ogni volta cambia l’angolo di rotazione, cosi’ per ogni caso che calcoli avrai eseguito solo una singola rotazione.

Tanto rs.RotatePlane() (se e’ quello che stai usando) ogni volta costruisce un nuovo piano, quindi non devi cambiare niente altro nello script.

si stavo provando con rs.RotatePlane() e anche rs.RotateView() che ho notato possono lavorare insieme

poi come già accennato sto approfondendo le liste/indici le stringhe e adesso sono uscite anche le “tupla”

ma non è meglio di sabato sera andare a mangiarsi qualcosa con birretta e r***o libero alla Fantozzi :joy::joy:

pensiero della sera (o della notte ormai):
ripensando al fatto della difficoltà di passare da un linguaggio ad un’altro come parlavamo prima
credo che però un punto “non da sottovalutare” ci sia è non è poco, il fatto che se con un linguaggio
devi pensare in una maniera mentre con un’altro devi pensare in un’altra quando impari e usi il secondo
linguaggio puoi mettere in pratica anche il primo modo di pensare di fare un codice di programmazione
cosa che tanto per fare un esempio a scuola/corso ti insegnano determinate cose impostate in un certo
modo e quella persona cresce formandosi ragionando solo in quel modo senza pensare se ne esiste un’altro.

conclusione sarà pure vero che quella persona avrà una mente meno aperta però con meno mal di testa
ahahahah ahahahah

Esatto
E’ quello che dicono i professionisti. Lo ha detto recentemente sul forum USA anche Nathan Letwory di McNeel …

Poi … va beh, loro con i loro super-brains possono tenere a mente 25 modi diversi di fare le cose, io da povero cristo di scriptomane a tempo perso, va gia’ bene se ne imparo mezzo … :smile:

… Ma non ci scoraggiamo per queste quisquilie … :grinning:

Parlavi di stringhe … le stai usando per il problema delle tangenti ? ( Scusa la curiosita’ )

magari Emilio, per adesso sto cercando di capire le differenze tra liste e stringhe che se non errò in VbScript non esiste e quindi capire come posso muovermi per dialogare con Python ma sopratutto come lui ragiona.

adesso sono arrivato a trattare i coerce3dpoint infatti mi sono un pò impantanato per una stupidaggine:
mi serviva verificare se una variabile sia un punto a=[0,0,0] e per portare il punteggio a casa ho subito arraggianto in “if len(a)==3:” poi adesso usando i coerce ho scritto questo “if rs.coerce3dpoint(a):”
di sicuro la seconda soluzione è migliore ma non saprei se sia proprio quella idonea ho dei dubbi :thinking::thinking:

sto all’inizio in questo mare sterminato che è Python ogni modulo importato è un oceano sterminato
ad ogni “.” che si mette alla fine di un comando/funzione/istruzione escono altri menù ahahahah

siamo pazzi ragazzi siamo pazzi :slight_smile::slight_smile:

EDIT: a proposito delle stringhe perchè come potrei usarle per il problema delle tangenze?

Beh, se paragoniamo le array VBS alle liste Python (mi sembrano la stessa cosa), allora le stringhe sono una cosa diversa.
Da quanto ricordo, in VBS una ‘array’ e’ una cosa che costruisci, ad esempio, cosi’:

a = Array( 1, 2, 3 )

che in Python corrisponde a una ‘lista’:

a = [ 1, 2, 3 ]

Mentre le stringhe, sia in VBS che in Python sono dei semplici testi:
(VBS)

b = "porco cane, domani e' lunedi'"

e (Python)

b = "... e non ci danno nemmeno le 35 ore"

Io non vedo differenze concettuali tra stringhe VBS e stringhe Python, a parte ovviamente la sintassi per lavorarci sopra …
Tu quali differenze trovi ?

Si’ coerce3dpoint() serve proprio per ottenere un punto
Ma di solito lo richiamano gia’ le funzioni rs, tu come lo usi in questo caso ?

Hahaha … calma, non esageriamo. :grinning:
Tu per ora usi rhinoscriptsyntax, no ?
Di quali altri moduli hai bisogno ?

E’ proprio quello che ero curioso di sapere … :smile:

si la differenza della sintassi delle liste/indici tra VBS e PY questa l’avevo capito ormai
per me in VBS sia le liste/indici che le stringhe le usavo senza sapere che ci fossero differenze

a=rs.CurveCurveIntersection(rs.GetObject(), rs.GetObject())
for i in range(0,len(a)):
for j in range(0,len(a)):
if rs.coerce3dpoint(a[i][j]):
rs.AddPoint(a[i][j])

beh ho importato il modulo Rhino perchè stavo cercando come gestire un “array punto” quindi per capire cosa inglobava e se mi potesse essere utile. in pratica il codice sopra postato mi interessava far eseguire ogni combinazione ma accettare solo quando venissero generati gli “array punti” senza scegliere io gli indici.

il codice funziona ma il mio dubbio era se “if rs.coerce3dpoint(a[i][j]):” fosse la sintassi idonea a tale scopo?
in pratica potrebbe essere che il codice funzioni per caso usando coerce3dpoint dove invece ci vuole altro.

Vuoi dire che indicizzavi le stringhe come fai con gli array ?
Una cosa del genere ?

a = Array( 1, 2, 3 )
b = "123"
c = a(1)
d = b(1)

… mi sembra strano, non ricordavo che si potessero indicizzare le stringhe in VBS … ma forse me lo sono dimenticato …:slight_smile:

… Mi sembra un modo un po’ contorto di procedere …
(Come sai non sono molto … diplomatico … :smile: )
Intanto

for j in range( 0, len( a ) ):

non mi convince … J qui e’ il secondo indice, e dalla documentazione vedo che va da 0 a 8 …
len( a ) non c’entra niente.

Poi, sempre dalla documenatazione vedo che i punti li trovi con valori di J da 1 a 4 (e possono anche essere 4 punti uguali )
Se ti serve un punto, scegline uno, o ricava un punto medio, ma dagli tu l’indice ‘J’

Che senso ha spazzolare tuti i valori ottenuti, quando sappiamo benissimo dove sono i punti ? :slight_smile:
Inoltre come fai tu, per ogni intersezione disegni 4 punti … e’ quello che vuoi ?
Poi se con la J ti fermi a len( a ) … rischi di non trovare nemmeno un punto (se hai una sola intersezione) …

Se tu gli dai la J che ti serve, eviti tutta la faccenda coerce3dpoint() … che mi sembra superflua …

Ah, OK, giusto, anche se in RhinoCommon i punti non sono array, ma oggetti (cioe’ in C# sono strutture, ma in Python sono oggetti)
In questo caso non preoccuparti dei metodi che vedi elencati.
RhinoCommon va presa … a piccole dosi, all’inizio. :grinning:

Bene … scusa la franchezza, ma lo sai … io e te vediamo gli script da prospettive diverse … :smile:

EDIT:

Scusa, ancora una cosa …
Se stai lavorando sulle rette tangenti, perche’ usi CurveCurveIntersection() e non LIneLineIntersection() , che da’ un risultato piu’ semplice da gestire ? :slight_smile:

Ups scusate avrei dovuto cancellare quello script
Comunque basta che vai in questa cartella dentro alla tua appdata (C:\Users\NOME UTENTE\AppData\Roaming\Grasshopper) e cancelli il file (grasshopper_gui.xml)

Cerco di essere piu’ chiaro:
Se vuoi usare CurveCurveIntersection, io farei cosi’:
( … Poi ovviamente tu fai come ti pare :smile: )

a=rs.CurveCurveIntersection(rs.GetObject(), rs.GetObject())
for i in range(0,len(a)):
  rs.AddPoint( ( a[i][1] + a[i][3] ) / 2 )

LineLineIntersection risulta piu’ comodo se parti direttamente dai punti,
ma per provare possiamo benissimo partire da curve cliccabili, come abbiamo fatto sopra

b = rs.GetObject()
c = rs.GetObject()
a = rs.LineLineIntersection( 
    [ rs.CurveStartPoint(b), rs.CurveEndPoint(b) ],
    [ rs.CurveStartPoint(c), rs.CurveEndPoint(c) ] )
rs.AddPoint( ( a[0] + a[1] ) / 2 )

… tra l’altro usando RhinoCommon in entrambi i casi … senza accorgercene … :grinning:

grazie Emilio per lo script (ma io seguendo il tuo pensiero) ultimamente mi sono concentrato sul fatto di ruotare il piano e creare un box e trovare intersezioni e ricavarmi i due TAG per i due lati interessati
segue codice realizzato:

obj=rs.GetObject(“Seleziona”)
b=

for r in rs.frange(0,360,0.1):
rt=rs.RotatePlane(rs.ViewCPlane(),r,rs.ViewCPlane().ZAxis)
bb=rs.BoundingBox(obj,rt)
bbb=bb[:4]
bbb.append(bb[0])
pol=rs.AddPolyline(bbb)
int=rs.CurveCurveIntersection(pol, obj)
for i in range(0,len(int)):
#rs.AddPoint(int[i][2])
b=b+[int[i][2]]
#delete pol
if len(b)==5: rs.AddPoints(b)

beh piccolo inconveniente che come avevo ipotizzato non riesco a ricavare l’algolo giusto?
ho impostato anche a 0.001 in frange un lavoraccio troppo tempo e comunque non va lo stesso.

PS era una cosa del genere che mi avevi consigliato oppure avevo capito male?

Ciao Salvio

… Scusa, a prima vista non capisco cosa fa il tuo script …
Pero’ sembra diverso da quello che avevo pensato.

La mia idea era di dividere la curva in due parti.
Qui non vedo due curve, ci sono ?

Secondo passo: cercare con un loop l’angolo di rotazione per cui
la Y massima delle due curve (secondo il piano ruotato) risulti uguale, cioe’ facendo un
rs.BoundingBox() secondo il piano ruotato e chiedendo le coordinate del piano ruotato,
cioe’ con terzo parametro False. Per entrambe le curve.

E infine confrontare la Y massima: cioe’ la Y di bb[2] o bb[3], per le due curve.

Adesso non riesco, sorry. :disappointed:
Piu’ tardi … o domani o … :wink: … provo poi a buttar giu’ due linee di Python. :slight_smile:

esatto. questa era la tua idea iniziale che mi avevi consigliato: “Idea veloce buttata li’ …”

poi mi avevi consigliato di non muovere nulla e di creare delle BB incliante ruotanto il piano in un loop
da quello che avevo letto e capito è nato lo script postato (che funziona ma deve essere migliorato)

PS anzi ero entusiasta su questo sistema perchè se funzionasse al 100% mi eviterebbe di dover usare
il codice di Thomas in VBS che quindi dovrei riuscire (ipoteticamente) a tradurre in PY
quindi la situazione dove mi ritrovo con un retta alla base e le prime due TAN e usando questo codice.

quindi come potrai immaginare se ruotando il piano e creando le BB riesco a trovare i quattro punti TAN e ricavare le due linee rette potrei evitare di tradurre circa 500 righe del codice e sarei al 7° cielo :slight_smile:

adesso mi sto concentrando come avevi suggerito anche sulla tolleranza sperando che mi aiuti nel risultato.

grazie ancora Emilio e appena puoi dai una occhiata allo script che di sicuro serve il tuo contributo :slight_smile:

OK, allora puoi spiegarmi come funziona ?
Cosa fanno le varie istruzioni ? :slight_smile:

ruota il piano - crea una bbox - aggiunge i punti tra intersezione della curva selezionata e bbox creato

in teoria mi servirebbe i punti aggiunti solo quando ne riscontra 5
essendo che i due lati interessati hanno due punti TAN

PS non vorrei confondere con troppe notizie, ma posso postare foto esempio o altre spiegazioni se vuoi.

EDIT: non so se sto sulla strada giusta ma da ricerche fatte mi sa che la rotazione del piano non vada bene come codice da me postato. sia il codice di Thomas che la guida degli script usano (come temevo) “cos e sin” non saprei per me è la prima volta lavorare con questi sconosciuti…

Ak, OK, grazie.
E’ un algoritmo diverso, ma ovviamente tutto quello che funziona va bene ! :slight_smile:

Se usi rs.RotatePlane() non servono sin e cos per ruotare il piano. Pensa a tutto Rhino :slight_smile:

peccato che non ho il risultato desiderato

Se ti serve, questo sembra che funzioni (provato solo su due cerchi … :wink: )

import rhinoscriptsyntax as rs

# input curve
c1 = rs.GetObject( 'Curva 1 ?' )
c2 = rs.GetObject( 'Curva 2 ?' )
# differenza allineamento Y minima
diff_ymin = 1.0e20
# rotazione per allineamento Y minima
gradi_ymin = -1
# differenza allineamento Y massima
diff_ymax = 1.0e20
# rotazione per allineamento Y massima
gradi_ymax = -1
# nome piu' corto per piano WorldXY ... ;)
wxy = rs.WorldXYPlane()
# loop di ricerca tra 0 e 180 gradi
for gradi in range( 180 ):
  # piano ruotato
  plan = rs.RotatePlane( wxy, gradi, [ 0, 0, 1 ] )
  # punti bounding box ruotato curva 1
  # in coordinate ruotate
  p1 = rs.BoundingBox( c1, plan, False )
  # punti bounding box c ruotatourva 2
  # in coordinate ruotate
  p2 = rs.BoundingBox( c2, plan, False )
  # calcola differenza Y minima
  dy = abs( p1[ 1 ].Y - p2[ 1 ].Y )
  # se allineamento Y minima migliora: 
  if dy < diff_ymin:
    # salva nuova differenza Y minima e angolo
    diff_ymin = dy
    gradi_ymin = gradi
  # calcola differenza Y massima
  dy = abs( p1[ 2 ].Y - p2[ 2 ].Y )
  # se allineamento Y massima migliora: 
  if dy < diff_ymax:
    # salva nuova differenza Y massima e angolo
    diff_ymax = dy
    gradi_ymax = gradi
# ricalcola punti bounding box con angolo per allineamento Y minima
# con coordinate non ruotate per disegnare retta
plan = rs.RotatePlane( wxy, gradi_ymin, [ 0, 0, 1 ] )
pt = rs.BoundingBox( [ c1, c2 ], plan, True )
rs.AddLine( pt[ 0 ], pt[ 1 ] )
# ricalcola punti bounding box con angolo per allineamento Y massima
# con coordinate non ruotate per disegnare retta
plan = rs.RotatePlane( wxy, gradi_ymax, [ 0, 0, 1 ] )
pt = rs.BoundingBox( [ c1, c2 ], plan, True )
rs.AddLine( pt[ 2 ], pt[ 3 ] )

… ma e’ il mio algoritmo, non il tuo … :slight_smile:

obj1 = rs.GetObject(“Seleziona”)
for i in rs.frange(0, 360, .001):
rtp = rs.RotatePlane(rs.ViewCPlane(), abs(i), [0,0,1])
bbx = rs.BoundingBox(obj1, rtp)
#obj2 = rs.AddRectangle(rtp, bbx[0], bbx[2])
obj2 = rs.AddLine(bbx[0], bbx[1])
int = rs.CurveCurveIntersection(obj2, obj1)
if len(int) < 2: rs.DeleteObject(obj2)

con questo metodo è il massimo che sono riuscito ad ottenere, a parte il fatto che aggiunge qualche retta di troppo “cosa che vorrei cercare di evitare” e un’altra pecca e che ci mette un bel pò troppo tempo.

nel caso ci sarebbe un modo per velocizzare tipo evitare di creare le rette per poi eliminarle?

PS provare con il file postato ad inizio thread per visualizzare il risultato finale da ottenere.

scusa Emilio la domanda, ma sto facendo un raffronto con il tuo codice postato con il mio ultimo

lo sai se le cose non le si impara prima sulla propria pelle è ancora più difficile capire quello degli altri

ma nel mio caso la funzione “abs” serve oppure è messo dove non ci vuole?

PS mi sa che dovrei anchio mettere: rs.WorldXYPlane() al posto di rs.ViewCPlane() giusto?

abs() serve a rendere positivi i numeri negativi.
Tu qui hai la vairabile ‘i’ che va da 0 a 360 … non vedo valori negativi da convertire …
e poi a quale scopo ?

Poi, se permetti, ho qualche dubbio sulla strada che stai seguendo …
Se non sbaglio, vorresti ‘beccare’ gli angoli per cui il lato della bounding box tocca la curva in due punti.
Mi sembra una questione di tolleranze … se la tolleranza e’ bassa rischi di non trovare l’angolo.
Se e’ alta potresti trovare diversi risultati.
Non so, non mi sembra facile da gestire …

Potresti fare due cose:
1: la piu’ semplice:
Usare.rs.EnableRedraw(). Le rette le crei come prima, ma almeno non le disegni.
2: la piu’ radicale :wink: :
Usare RhinoCommon e lavorare solo su oggetti geometrici senza scomodare il data base del documento Rhino. Anche se non so quanto guadagneresti come tempo di esecuzione …