/// <summary> /// Proiezione di un punto su un arco /// </summary> /// <param name="p">Punto</param> /// <param name="a">Arco</param> /// <param name="projection">Proiezione (parametro out)</param> /// <param name="bInside">true se richiesta appartenenza proiezione all'interno dell'arco</param> /// <returns>true se trovata</returns> public static bool Projection( Point2D p, Arc2D a, out Point2D projection, bool bInside = false) { Point2D proj = null; // La proiezione, se trovata Point2D dir = p - a.Center; // Calcola il vettore dal centro al punto if(dir.Normalize()) // Lo normalizza. Se nessun errore... { Point2D proj1 = a.Center + a.Radius * dir; // Calcola le due proiezioni sul cerchio. Point2D proj2 = a.Center - a.Radius * dir; double d1 = Function2D.Distance(proj1, p); // e le distanze tra punto e proiezione double d2 = Function2D.Distance(proj2, p); bool app1, app2; // Appartenenza all'arco delle due proiezione app1 = app2 = true; if( bInside == true) // Verifica le appartenenze all'arco { double alfa; if(a.Alfa(proj1, out alfa)) // calcola l'angolo del primo e del secondo punto proiettato { // scarta, se non appartiene all'arco if(!a.Belongs(alfa)) app1 = false; } if(a.Alfa(proj2, out alfa)) { if(!a.Belongs(alfa)) app2 = false; } } if( (app1==true) && (app2==true) ) // Se entrambi appartengono all'arco { // scarta quello con distanza maggiore if(d1 >= d2) app1 = false; else app2 = false; } if(app1) // Imposta proj con la proiezione valida... proj = proj1; // ...se c'e` else if(app2) proj = proj2; } if(proj != null) // Se trovata proiezione, esce con true... { projection = proj; return true; } projection = new Point2D(); return false; // ...se non trovata, esce con false + punto vuoto. }
private void test1ToolStripMenuItem_Click(object sender, EventArgs e) { Point2D p1 = new Point2D(1, 0); Point2D p2 = new Point2D(0, 1); Point2D p3 = new Point2D (1,1); Point2D pc = new Point2D (0,0); Point2D p4 = new Point2D (0, -1); Point2D p5 = new Point2D (1, 2); Point2D p6 = new Point2D (1, -1); Arc2D ar1 = new Arc2D(pc, p1, p2); Arc2D ar1x = new Arc2D(p1, p2, pc, Arc2D.TrePunti.Estremi_e_Centro); Arc2D ar2 = new Arc2D(pc, p2, p1); Arc2D ar2x = new Arc2D(p2, p1, pc, Arc2D.TrePunti.Estremi_e_Centro); Arc2D ar3 = new Arc2D(p3, p2); Line2D ln1 = new Line2D(p1, p2); Line2D ln2 = new Line2D(pc, p3); Line2D ln3 = new Line2D(0,0,30,3,false,true); Line2D ln4 = new Line2D(pc, p2, true); Line2D ln5 = new Line2D(p2, p3); bool b1 = ar1.Belongs(0); bool b2 = ar1.Belongs(Math.PI/4); bool b3 = ar1.Belongs(Math.PI / 8); bool b4 = ln1.Belongs(p1); bool c1 = ar1.Belongs(new Point2D(0,1)); bool c2 = ar1.Belongs(new Point2D(1,0)); bool c3 = ar1.Belongs(new Point2D(Math.Sqrt(2)/2,Math.Sqrt(2)/2)); List<Intersection> li1 = Function2D.Intersect(ln1, ln2); List<Intersection> li2 = Function2D.Intersect(ln2, ar1); List<Intersection> li3 = Function2D.Intersect(ln2, ar1, true, true); List<Intersection> li4 = Function2D.Intersect(ln3, ar1); List<Intersection> li5 = Function2D.Intersect(ln2, ar2, false, true); List<Intersection> li6 = Function2D.Intersect(ln4, ar3, false, false); List<Intersection> li7 = Function2D.Intersect(ln5, ln3); Point2D[] nr = new Point2D[3]; double[] nrd = new double[3]; Function2D.Nearest(p2, ln2, out nr[0], out nrd[0]); Function2D.Nearest(p4, ln3, out nr[1], out nrd[1], true); Function2D.Nearest(p6, ln3, out nr[2], out nrd[2]); Point2D[] nrx = new Point2D[3]; nrx[0] = Function2D.Nearest(p2, ln2); nrx[1] = Function2D.Nearest(p4, ln3, true); nrx[2] = Function2D.Nearest(p6, ln3); Point2D[] pr = new Point2D[4]; bool[] prb = new bool[4]; prb[0] = Function2D.Projection(p3, ln2, out pr[0]); prb[1] = Function2D.Projection(p4, ln2, out pr[1]); prb[2] = Function2D.Projection(p6, ln2, out pr[2]); prb[3] = Function2D.Projection(p2, ln3, out pr[3]); Point2D[] prx = new Point2D[4]; prx[0] = Function2D.Projection(p3, ln2); prx[1] = Function2D.Projection(p4, ln2); prx[2] = Function2D.Projection(p6, ln2); prx[3] = Function2D.Projection(p2, ln3); Point2D[] pra = new Point2D[5]; bool[] prab = new bool[5]; prab[0] = Function2D.Projection(p6, ar2, out pra[0], true); prab[1] = Function2D.Projection(p5, ar1, out pra[1], true); prab[2] = Function2D.Projection(p5, ar2, out pra[2], true); prab[3] = Function2D.Projection(p5, ar2, out pra[3], false); prab[4] = Function2D.Projection(p4, ar3, out pra[4], true); Point2D[] prax = new Point2D[5]; prax[0] = Function2D.Projection(p6, ar2, true); prax[1] = Function2D.Projection(p5, ar1, true); prax[2] = Function2D.Projection(p5, ar2, true); prax[3] = Function2D.Projection(p5, ar2); prax[4] = Function2D.Projection(p4, ar3, true); Point2D x = new Point2D(10,-1); x = -x; Line2D[] vout = new Line2D[3]; bool[] bv = new bool[3]; bv[0] = Function2D.LineOut(pra[0], ar2, out vout[0], p6); bv[1] = Function2D.LineOut(pr[3], ln3, out vout[1], p3); bv[2] = Function2D.LineOut(pra[0], ar2, out vout[2], p2); Line2D[] voux = new Line2D[3]; voux[0] = Function2D.LineOut(pra[0], ar2, p6); voux[1] = Function2D.LineOut(pr[3], ln3, p3); voux[2] = Function2D.LineOut(pra[0], ar2, p2); Point2D[] vettori = new Point2D[3]; vettori[0] = voux[0].Vector(); vettori[1] = voux[1].Vector(); vettori[2] = voux[2].Vector(); Point2D[] vvout = new Point2D[3]; bool[] bvv = new bool[3]; bvv[0] = Function2D.VersorOut(pra[0], ar2, out vvout[0], p6); bvv[1] = Function2D.VersorOut(pr[3], ln3, out vvout[1], p3); bvv[2] = Function2D.VersorOut(pra[0], ar2, out vvout[2], p2); Point2D[] vvoux = new Point2D[3]; vvoux[0] = Function2D.VersorOut(pra[0], ar2, p6); vvoux[1] = Function2D.VersorOut(pr[3], ln3, p3); vvoux[2] = Function2D.VersorOut(pra[0], ar2, p2); double[] scalari = new double[3]; scalari[0] = vvoux[0]^vettori[0]; scalari[1] = vvoux[1]^vettori[1]; scalari[2] = vvoux[2]^vettori[2]; Point2D Punto2 = new Point2D(-5.17,9.91); Point2D Punto3 = new Point2D(-4.82,-10.08); Point2D centroX = new Point2D(94.48,1.64); Arc2D Arco = new Arc2D(Punto2,Punto3,centroX,Arc2D.TrePunti.Estremi_e_Centro); #pragma warning disable int tmp; tmp = 1; #pragma warning restore }
/// <summary> /// Intersezioni tra linea ed arco /// </summary> /// <param name="l1">Linea</param> /// <param name="a2">Arco</param> /// <param name="bCheckInside1">Richiesta intersezione interna alla linea</param> /// <param name="bCheckInside2">Richiesta intersezione interna all'arco</param> /// <returns></returns> public static List<Intersection> Intersect( Line2D l1, Arc2D a2, bool bCheckInside1 = false, bool bCheckInside2 = false) { double[] t = new double[2]; double[] a = new double[2]; Point2D[] p = new Point2D[2]; bool[] ok = new bool[2]; // soluzione trovata e valida bool[] tg = new bool[2]; // intersezione doppia List<Intersection> intersezioni = new List<Intersection>(); // P = P1 + t (P2 - P1) equazione della retta del segmento // P = C + r (cos a, sin a) oppure equazione della circonferenza // || P - C ||^2 = r^2 altra equazione della circonferenza // || P1 - C + t (P2 - P1) ||^2 = r^2 Intersezione: punto su entrambi // A = P1 - C; B = P2 - P1 Sostituzioni // || V || = V.x^2 + V.y^2 = V ^ V (scalare) Definizione di modulo // || A + t B ||^2 = r^2 Intersezione, sostituendo... // (A.x + t B.x)^2 + (A.y + t B.y)^2 - r^2 = 0 ... // A.x^2 + t^2 B.x^2 + 2 t A.x B.x + A.y^2 + t^2 B.y^2 + 2 t A.y B.y - r^2 = 0 ... // A.x^2 + A.y^2 + t^2 ( B.x^2 + B.y^2) + 2 t ( A.y B.y + A.x B.x) - r^2 = 0 ... // t^2(B^B) + 2 t (A^B) + A^A - r^2 = 0 Equazione di secondo grado da risolvere // a=B^B 2b=2*A^B c=A^A-r^2 in a*t^2 + 2*b*t + c = 0 Coefficienti // t12 = [-2b +- sqr( (2b)^2 - 4ac) ] / 2a = [-2b +- 2sqr( b^2 - ac) ] / 2a Formula completa... // t1 = [-b +- sqr(b^2-ac)]/a ...e ridotta Point2D A = l1.P1 - a2.Center; Point2D B = l1.P2 - l1.P1; double r = a2.Radius; ok[0] = ok[1] = false; // Imposta i flag tg[0] = tg[1] = false; double aEq, bEq, cEq, dEq24, dEq2; // Calcola con formula ridotta ERRORE NELLA FORMULA ??? aEq = B^B; bEq = A^B; cEq = (A^A) - r*r; dEq24 = bEq*bEq - aEq*cEq; if(dEq24 >= 0.0) // Cerca le soluzioni, memorizza valori ed imposta i flag { // Se ci sono soluzioni if(Math.Abs(dEq24) < Function2D.epsilon) // Delta = 0, una soluzione { t[0] = -bEq / aEq; p[0] = l1.P1 + t[0] * (l1.P2 - l1.P1); if(a2.Alfa(p[0], out a[0])) // Calcola alfa dell'arco e imposta flag della soluzione { ok[0] = true; tg[0] = true; // tangente, soluzione doppia } } else // Delta > 0, due soluzioni { dEq2 = Math.Sqrt(dEq24); // Radice di delta t[0] = (-bEq - dEq2) / aEq; t[1] = (-bEq + dEq2) / aEq; p[0] = l1.P1 + t[0] * (l1.P2 - l1.P1); p[1] = l1.P1 + t[1] * (l1.P2 - l1.P1); if(a2.Alfa(p[0], out a[0])) // Calcola alfa e flag delle due soluzioni ok[0] = true; if(a2.Alfa(p[1], out a[1])) ok[1] = true; } } for(int i=0; i<2; i++) // Verifica, se richieste, le appartenenze a segmento e arco { if(ok[i]) // Esamina, se c'e', la soluzione { if(bCheckInside1) // Se richiesto punto interno verifica... { if( (t[i] < 0.0) || (t[i] > 1.0) ) // Se t trovato indica che e` esterno, imposta a false ok[i] = false; } if(bCheckInside2) // Idem per l'arco... { if(!a2.Belongs(a[i])) ok[i] = false; } } } for(int i=0; i<2; i++) // Riesamina le soluzione { if(ok[i]) // Se trovata, aggiunge intersezione alla lista { intersezioni.Add(new Intersection(p[i], t[i], a[i], l1, a2, false, tg[i])); } } return intersezioni; // Restituisce il rif. alla lista }