Raggio CalcolaRaggio(Raggio rIn, CorpoOttico ambiente) { Raggio rout = null; if(ambiente==null) // controlli iniziali return rout; if((!ambiente.Ambiente) || (!ambiente.IsValid)) return rout; Intersection fint = TrovaPrimaIntersezione(rIn); // Trova prima intersezione if(fint != null) { List<Contorno> lc = Belongs(fint.p); // Trova i contorni cui appartiene la prima intersezione if(lc.Count > 2) // Se piu` di due tratti: errore throw new Exception("Intersezione unica di un raggio con piu` di due tratti, in CalcolaRaggio()"); if(lc.Count == 2) // Se due tratti: su vertica { if(Tangenti(lc[0].Tratto, lc[1].Tratto)) // Se tangenti, considero intersezione su uno dei due, equivalente { if(lc[0].Stato != lc[1].Stato) // Se hanno uno stato superficiale diverso, elimina il raggio { lc.Clear(); } else // altrimenti lc.Remove(lc[1]); // elimino l'ultimo contorno } } if(lc.Count == 1) // Se una sola intersezione { Point2D versoreIn = rIn.Vector(); // Versori entrante (Raggio gia` normalizzato) e normale. Point2D versoreNorm = Function2D.VersorOut(fint.p, lc[0].Tratto, rIn.Point(fint.t1 - dimcar*FrazioneEpsilon)); switch(lc[0].Stato) { case StatoSuperficie.Opaca: { // Non fa nulla, raggio assorbito, nessun raggio in uscita break; } case StatoSuperficie.Riflettente: { rout = new Raggio(new Line2D(fint.p, Ottica.Riflesso(versoreIn, versoreNorm), true)); rout.CorpoAttuale = rIn.CorpoAttuale; break; } case StatoSuperficie.Trasparente: { CorpoOttico co_in, co_out; // Corpi ottici del raggio in ingresso ed uscita co_in = rIn.CorpoAttuale; if(co_in == this) // Se il raggio entrante si trova nel corpo ottico { co_out = ambiente; // quello uscente nell'ambiente } else // se no, da ambiente... { co_out = this; // a corpo attuale } Point2D vrifr = Ottica.Rifratto(versoreIn, versoreNorm, co_in.IndiceRifrazione, co_out.IndiceRifrazione); if(vrifr != null) { rout = new Raggio(new Line2D(fint.p, vrifr, true)); // throw new Exception("Manca determinazione se il raggio parte dall'esterno o dall'interno, per scegliere n1->n2 o n2->n1 "); rout.CorpoAttuale = co_out; } break; } } } } return rout; }
/// <summary> /// Funzione principale di calcolo ottico /// </summary> /// <param name="rIncidente"></param> /// <param name="ambiente"></param> /// <returns></returns> public override List<Raggio> CalcolaRaggi(Raggio rIncidente, MaterialeOttico ambiente) { List<Raggio> lR = new List<Raggio>(); // Lista di raggi if(ambiente !=null) // Controllo iniziale { Raggio r1 = null; // Raggio entrante Raggio r2 = null; // Raggio uscente for(r1 = rIncidente; r1 != null; r1 = r2) // Ciclo di calcolo { r2 = null; Intersection fint = TrovaIntersezione(r1); // Trova prima intersezione di r1 con il corpo ottico if(fint != null) // Se non la trova, r2 resta null { List<Contorno> lc = Belongs(fint.p); // Trova i contorni cui appartiene la prima intersezione if(lc.Count > 2) // Se piu` di due tratti: errore throw new Exception("Intersezione unica di un raggio con piu` di due tratti, in CalcolaRaggio()"); if(lc.Count == 2) // Se due tratti: su vertice { if(Tangenti(lc[0].Tratto, lc[1].Tratto)) // Se tangenti, considero intersezione su uno dei due, equivalente { if(lc[0].Stato != lc[1].Stato) // Se hanno uno stato superficiale diverso, elimina il raggio { lc.Clear(); } else // altrimenti lc.Remove(lc[1]); // elimino l'ultimo contorno... } // ...e proseguo al prossimo if } if(lc.Count == 1) // Se una sola intersezione { Point2D versoreIn = r1.Vector(); // Versori entrante (Raggio gia` normalizzato) e normale. Point2D versoreNorm = Function2D.VersorOut(fint.p, lc[0].Tratto, r1.Point(fint.t1 - dimcar*FrazioneEpsilon)); switch(lc[0].Stato) { case StatoSuperficie.Opaca: { break; // Non fa nulla, raggio assorbito, nessun raggio in uscita } case StatoSuperficie.Riflettente: // Calcola raggio riflesso { r2 = new Raggio(new Line2D(fint.p, Ottica.Riflesso(versoreIn, versoreNorm), true),r1.Lambda); r2.CorpoAttuale = r1.CorpoAttuale; break; } case StatoSuperficie.Trasparente: { MaterialeOttico co1, co2; // Corpi ottici del raggio in ingresso ed uscita co1 = r1.CorpoAttuale; if(co1 == this.Materiale) // Se il raggio entrante si trova nel corpo ottico { co2 = ambiente; // quello uscente nell'ambiente } else // se no, da ambiente... { co2 = this.Materiale; // ...a corpo attuale } Point2D vrifr = Ottica.Rifratto(versoreIn, versoreNorm, co1.nRifrazione, co2.nRifrazione); if(vrifr != null) { r2 = new Raggio(new Line2D(fint.p, vrifr, true),r1.Lambda); r2.CorpoAttuale = co2; #warning Manca determinazione se il raggio parte dall'esterno o dall'interno } break; } } } r1.T2r = fint.t1; } lR.Add(r1); } } return lR; }