home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / w3dvb5 / lineanas.bas < prev    next >
Encoding:
BASIC Source File  |  1997-12-22  |  30.7 KB  |  1,224 lines

  1. Attribute VB_Name = "Lineanas"
  2.  
  3. ' Modulo per l'eliminazione delle linee nascoste.
  4. '
  5. ' ATTENZIONE - La Sub LineNas Φ la routine principale
  6. '              di questo modulo e (sigh!) non funziona.
  7. '              Comunque altre routine e variabili presenti
  8. '              sono indispensabili per l'algoritmo del pittore
  9. '              che Φ funzionante. Ergo, non eliminate il modulo
  10. '              dal progetto! Non funzionerα pi∙ niente!
  11.  
  12.  
  13. Public AlgoritmoAttivo As Integer ' 0 - Pittore, 1 - Linenas (serve per Orienta)
  14.  
  15. Public Const Nscreen = 10  '  // Ci saranno Nscreen x Nscreen quadrati
  16. Public density As Double
  17.  
  18. Public d As Double
  19. Public c1 As Double
  20. Public c2 As Double
  21. Public xfactor As Double
  22. Public yfactor As Double
  23.  
  24. Public Xrange As Double
  25. Public Yrange As Double
  26. Public Xvp_range As Double
  27. Public Yvp_range As Double
  28.  
  29. Public xmin As Double
  30. Public xmax As Double
  31. Public ymin As Double
  32. Public ymax As Double
  33. Public zmin As Double
  34. Public zmax As Double
  35.  
  36. Public deltax As Double
  37. Public deltay As Double
  38. Public denom As Double
  39. 'Public zemin As Double
  40. 'Public zemax As Double
  41.  
  42. Public eps1 As Double
  43. Public trset() As Integer
  44. Public dummy As Integer
  45. Public vertexcount As Integer
  46.  
  47. Public x_center As Double
  48. Public y_center As Double
  49. Public r_max As Double
  50. Public x_max As Double
  51. Public y_max As Double
  52. Public x_min As Double
  53. Public y_min As Double
  54.  
  55. Type Vertexes
  56.      Vt As Vec_Int
  57.      Z As Double
  58.      Connect(5) As Integer
  59. End Type
  60.  
  61. Public VV() As Vertexes
  62. Public pVertex As Integer
  63.  
  64. Type Nodo
  65.   idx As Integer
  66.   jtr As Integer
  67.   nextn As Integer
  68. End Type
  69.  
  70. Public VScreen(Nscreen, Nscreen) As Nodo
  71.  
  72. Type Point
  73.   Pntscr As Vec_Int
  74.   zPnt As Double
  75.   nrPnt As Integer
  76. End Type
  77.  
  78. Type linked_stack
  79.     p As Point
  80.     q As Point
  81.     k0 As Integer
  82.     nextn As Integer
  83. End Type
  84.     
  85. Public stptr(1) As linked_stack
  86.  
  87.  
  88. Sub add_linesegment(Pr As Integer, Qr As Integer)
  89. Dim iaux As Integer
  90. Dim p As Integer
  91. Dim i As Integer
  92. Dim n As Integer
  93. Dim Pt(3) As Integer
  94. Dim p_old(3) As Integer
  95. Dim Pnr As Integer
  96. Dim Qnr As Integer
  97.  
  98.  Pnr = Pr
  99.  Qnr = Qr
  100.   
  101.  
  102.    If (Pnr > Qnr) Then
  103.       iaux = Pnr
  104.       Pnr = Qnr
  105.       Qnr = iaux
  106.    End If
  107.    
  108.  ' Ora: Pnr < Qnr
  109.    p = VV(Pnr).Connect(0)
  110.    If (p = 0) Then
  111.        VV(Pnr).Connect(0) = 1
  112.        VV(Pnr).Connect(1) = Qnr
  113.        Exit Sub
  114.    End If
  115.    
  116.    n = VV(Pnr).Connect(0)
  117.    For i = 1 To n
  118.       If VV(Pnr).Connect(i) = Qnr Then Exit Sub ' Giα nella lista
  119.    Next i
  120.    
  121.    n = n + 1 ' Ora Q deve essere posto in p[n]
  122.    If (n Mod 3 = 0) Then
  123.       p_old(0) = VV(Pnr).Connect(0)
  124.       p_old(1) = VV(Pnr).Connect(1)
  125.       p_old(2) = VV(Pnr).Connect(2)
  126.     
  127.     ' Blocchi di tre interi
  128.       For i = 1 To n - 1
  129.           VV(Pnr).Connect(i) = p_old(i)
  130.       Next
  131.       VV(Pnr).Connect(0) = n
  132.       VV(Pnr).Connect(n) = Qnr '  // n Φ un multiplo di 3
  133.                                '  // *p=n, p[1],..., p[n] usati
  134.                                '  // (p[n+1], p[n+2] liberi)
  135.    Else
  136.       VV(Pnr).Connect(0) = n
  137.       VV(Pnr).Connect(n) = Qnr ' // n non Φ un multiplo di 3 (e n > 1)
  138.    End If
  139.  
  140.  
  141. End Sub
  142.  
  143. Function ColNr(x As Integer) As Integer
  144.          ColNr = (CLng(x) * Nscreen) / LARGE1
  145. End Function
  146.  
  147. Sub dealwithlinkedstack()
  148.  
  149. Dim Pt As linked_stack
  150. Dim p As Point
  151. Dim q As Point
  152. Dim k0 As Integer
  153. Dim Ptr As Integer
  154.  
  155. Ptr = 1
  156. Do While Ptr <> 0
  157.     Pt = stptr(Ptr)
  158.     p = Pt.p
  159.     q = Pt.q
  160.     k0 = Pt.k0
  161.     Ptr = Pt.nextn
  162.     linesegment Form1.Pict, p, q, k0
  163. Loop
  164.  
  165.  
  166. End Sub
  167.  
  168.  
  169. Sub LineNas(Pic As PictureBox)
  170.  
  171. Dim i As Integer
  172. Dim Pnr As Integer
  173. Dim Qnr As Integer
  174. Dim ii As Integer
  175. Dim vertexnr As Integer
  176. Dim Ptr As Integer
  177. Dim iconnect As Integer
  178. Dim code As Integer
  179. Dim ntr As Integer
  180. Dim i_i As Integer
  181. Dim j_j As Integer
  182. Dim jtop As Integer
  183. Dim jbot As Integer
  184. Dim jI As Integer
  185. Dim trnr As Integer
  186. Dim jtr As Integer
  187. Dim Poly() As Integer
  188. Dim nPoly As Integer
  189. Dim iLeft As Integer
  190. Dim iRight As Integer
  191. Dim nvertex As Integer
  192. Dim ntrset As Integer
  193. Dim maxntrset As Integer
  194. Dim VLOWER(Nscreen) As Integer
  195. Dim VUPPER(Nscreen) As Integer
  196. Dim Orient As Integer
  197. Dim maxnpoly As Integer
  198. Dim totntria As Integer
  199. Dim testtria(3) As Integer
  200.  
  201. Dim xsmin As Double
  202. Dim xsmax As Double
  203. Dim ysmin As Double
  204. Dim ysmax As Double
  205.  
  206.  
  207. Dim nrs_tr() As Trianrs
  208.  
  209. Dim deltax As Long
  210. Dim deltay As Long
  211.  
  212. Dim rho As Double
  213. Dim Theta As Double
  214. Dim Phi As Double
  215. Dim x As Double
  216. Dim Y As Double
  217. Dim Z As Double
  218. Dim xe As Double
  219. Dim ye As Double
  220. Dim ze As Double
  221. Dim xx As Double
  222. Dim yy As Double
  223. Dim fx As Double
  224. Dim fy As Double
  225. Dim Xcenter As Double
  226. Dim Ycenter As Double
  227.  
  228. Dim Ps As Vec_Int
  229. Dim Qs As Vec_Int
  230. Dim vLeft As Vec_Int
  231. Dim vRight As Vec_Int
  232.  
  233. Dim p As Vec3
  234.  
  235. Dim pNode As Integer
  236.  
  237. minvertex = 32000
  238. maxntrset = 400
  239. AlgoritmoAttivo = 1 ' Per Funct. Orienta
  240.  
  241. Erase stptr
  242.  
  243.  
  244.    nvertex = MaxVertNr + 1
  245.    ReDim Vt(nvertex)
  246.    
  247.    SetVista rho, Theta, Phi
  248.    SetLimitiVista xsmin, xsmax, ysmin, ysmax, nvertex, Vt()
  249.  
  250. ' Da InitGr
  251.    
  252.    x_max = 10
  253.    density = X__max / (x_max - x_min)
  254.    y_max = y_min + Y__max / density
  255.    x_center = 0.5 * (x_min + x_max)
  256.    y_center = 0.5 * (y_min + y_max)
  257.  
  258.    zfactor = LARGE / (zemax - zemin)
  259.    eps1 = 0.001 * (zemax - zemin)
  260.    
  261. '   // Calcola le costanti del video:
  262.    
  263.    Xrange = xsmax - xsmin
  264.    Yrange = ysmax - ysmin
  265.    
  266.    Xvp_range = x_max - x_min
  267.    Yvp_range = y_max - y_min
  268.    fx = Xvp_range / Xrange
  269.    fy = Yvp_range / Yrange
  270.    If fx < fy Then
  271.       d = 0.95 * fx
  272.    Else
  273.       d = 0.95 * fy
  274.    End If
  275.    
  276.    Xcenter = 0.5 * (xsmin + xsmax)
  277.    Ycenter = 0.5 * (ysmin + ysmax)
  278.    c1 = x_center - d * Xcenter
  279.    c2 = y_center - d * Ycenter
  280.    deltax = Xrange / Nscreen
  281.    deltay = Yrange / Nscreen
  282.    
  283.    xfactor = LARGE / Xrange
  284.    yfactor = LARGE / Yrange
  285.    
  286.    
  287.    
  288.    ReDim VV(nvertex)
  289.    
  290. ' Inizializza l'array dei vertici:
  291.    
  292.    For i = 0 To nvertex
  293.       If Vt(i).Z < -100000# Then
  294.          Erase VV(i).Connect
  295.       Else
  296.          Erase VV(i).Connect
  297.          VV(i).Vt.x = xIntScr(Vt(i).x / Vt(i).Z, xsmin)
  298.          VV(i).Vt.Y = yIntScr(Vt(i).Y / Vt(i).Z, ysmin)
  299.          VV(i).Z = Vt(i).Z
  300.   '       MsgBox "x= " & VV(i).Vt.X & "y= " & VV(i).Vt.Y & "z= " & VV(i).Z
  301.        End If
  302.   Next i
  303.   
  304.   Erase Vt
  305.  
  306. ' Trova il numero massimo di vertici in un solo poligono
  307. ' e il numero totale dei triangoli che non sono
  308. ' retrosuperfici:
  309.    
  310. maxnpoly = 0
  311. totntria = 0
  312.          
  313. nPoly = 0
  314. For k = 1 To UBound(FileVertex)
  315.  nPoly = 0
  316.  i = Abs(FileVertex(k).Vert(1))
  317.  If i > 0 Then
  318.     For j = 1 To FileVertex(k).Count
  319.         i = Abs(FileVertex(k).Vert(j))
  320.               
  321.         If i >= nvertex Then
  322.            MsgBox "Vertice nr." & CStr(i) & " indefinito"
  323.            End
  324.         End If
  325.         If nPoly < 3 Then testtria(nPoly) = i
  326.     
  327.         nPoly = nPoly + 1
  328.     Next j
  329.          
  330.          If (nPoly > maxnpoly) Then maxnpoly = nPoly
  331.          If Not (nPoly < 3) Then  '  // Ignora il segmento 'libero'
  332.             If (orienta(testtria(0), testtria(1), testtria(2)) >= 0) Then totntria = totntria + nPoly - 2
  333.          End If
  334.        
  335.  End If
  336.           
  337. Next k
  338.          
  339.          
  340. ' =========
  341.  
  342.   ReDim Triangles(totntria)
  343.   ReDim Poly(maxnpoly)
  344.   ReDim nrs_tr(maxnpoly - 2)
  345.  
  346.  
  347. '   // Lettura delle facce dell'oggetto e memorizzazione dei
  348. '   // triangoli:
  349.    
  350.    
  351. For k = 1 To UBound(FileVertex)
  352.          
  353.     nPoly = 0
  354.     For j = 1 To FileVertex(k).Count
  355.         
  356.         i = Abs(FileVertex(k).Vert(j))
  357.         If nPoly = maxnpoly Then
  358.            MsgBox "Errore di programmazione maxnpoly"
  359.            End
  360.         End If
  361.         Poly(nPoly) = i
  362.         nPoly = nPoly + 1
  363.     
  364.     Next j
  365.     
  366.    
  367.   '  If (nPoly = 1) Then
  368.       '  MsgBox "Solo un vertice del poligono?"
  369.       '  End
  370.   '  End If
  371.     
  372.     If nPoly = 2 Then
  373.       Call add_linesegment(Poly(0), Poly(1))
  374.     Else
  375.     
  376.        Pnr = Abs(Poly(0))
  377.        Qnr = Abs(Poly(1))
  378.        For s = 2 To nPoly - 1
  379.           Orient = LOrienta(Pnr, Qnr, Abs(Poly(s)))
  380.           If (Orient <> 0) Then Exit For ' // Normalmente, s = 2
  381.        Next
  382.    
  383.     
  384.        If (Orient >= 0) Then   ' ; // Non Retrosuperficie
  385.    
  386.           For s = 1 To nPoly
  387.              i_i = s Mod nPoly
  388.              code = Poly(i_i)
  389.              vertexnr = Abs(code)
  390.              If code < 0 Then
  391.                 Poly(i_i) = vertexnr
  392.               Else
  393.                 Call add_linesegment(Poly(s - 1), vertexnr)
  394.              End If
  395.           Next s
  396.    
  397.    
  398. '      // Suddivisione di un poligono in triangoli:
  399.       
  400.       
  401.           code = Triangul(Poly(), nPoly, nrs_tr(), Orient)
  402.           If (code > 0) Then
  403.              If (ntr + code > totntria) Then
  404.                   MsgBox "Errore di programmazione: totntria"
  405.                   End
  406.              End If
  407.              Call LComplete_Triangles(code, ntr, nrs_tr())
  408.              ntr = ntr + code
  409.           End If
  410.       
  411.        End If
  412.     End If
  413.     
  414. Next k
  415.    
  416. Erase Poly
  417. Erase nrs_tr
  418.  
  419.  Call setupscreenlist(Triangles, ntr)
  420.  ReDim trset(maxntrset)
  421.    
  422.  
  423.  '  // Traccia tutti i segmenti finchΘ sono visibili:
  424.    
  425.   For Pnr = MinVertNr To MaxVertNr
  426.       Ptr = VV(Pnr).Connect(0)
  427.       
  428. '    0: Pnr non in uso; NULL: nessun segmento memorizzato
  429. '    Pnr non in uso oppure nessun segmento memorizzato
  430.       
  431.       If Ptr > 0 Then
  432.          Ps = VV(Pnr).Vt
  433.          For iconnect = 1 To Ptr
  434.              Qnr = VV(Pnr).Connect(iconnect)
  435.              Qs = VV(Qnr).Vt
  436.               
  437.       '   Usando le liste video, si costruirα l'insieme
  438.       '   dei triangoli che possono nascondere i punti di PQ:
  439.           
  440.              If (Ps.x < Qs.x Or (Ps.x = Qs.x And Ps.Y < Qs.Y)) Then
  441.                 vLeft = Ps: vRight = Qs
  442.              Else
  443.                 vLeft = Qs: vRight = Ps
  444.              End If
  445.              iLeft = ColNr(vLeft.x)
  446.              iRight = ColNr(vRight.x)
  447.          
  448.              If (iLeft <> iRight) Then
  449.                  deltay = vRight.Y - vLeft.Y
  450.                  deltax = vRight.x - vLeft.x
  451.              End If
  452.          
  453.              jbot = RowNr(vLeft.Y)
  454.              jtop = jbot
  455.              
  456.              For ii = iLeft To iRight
  457.                 If ii = iRight Then
  458.                    jI = RowNr(vRight.Y)
  459.                 Else
  460.                    hh& = vLeft.Y + (xCoord(ii + 1) - vLeft.x) * deltay / deltax
  461.                    If hh& > 32000 Then
  462.                       jI = Nscreen
  463.                    Else
  464.                       jI = RowNr(CInt(hh&))
  465.                    End If
  466.                 End If
  467.              
  468.                 VLOWER(ii) = Min2(jbot, jI)
  469.                 jbot = jI
  470.                 VUPPER(ii) = Max2(jtop, jI)
  471.                 jtop = jI
  472.              
  473.              Next ii
  474.          
  475.          Next iconnect
  476.          
  477.          ntrset = 0
  478.          For i = iLeft To iRight
  479.              For j = VLOWER(i) To VUPPER(i)
  480.                  pNode = VScreen(i, j).idx
  481.               '   Do While pNode <> 0
  482.                     trnr = VScreen(i, j).jtr
  483.                     '  /* Il triangolo trnr sarα memorizzato solo se
  484.                     '     non Φ giα presente nell'array trset (insieme dei
  485.                     '     triangoli)
  486.                     '  */
  487.                      trset(ntrset) = trnr   '  /* sentinella */
  488.                      jtr = 0
  489.                      Do While trset(jtr) <> trnr: jtr = jtr + 1: Loop
  490.                      If (jtr = ntrset) Then
  491.                          ntrset = ntrset + 1 ' // Significa che trnr Φ memorizzato
  492.                          If (ntrset = maxntrset) Then
  493.                           '  P = jtr
  494.                             maxntrset = maxntrset + 200
  495.                             ReDim Preserve trset(maxntrset)
  496.                      
  497.                             For s = 0 To ntrset - 1
  498.                                 trset(s) = trset(jtr + s)
  499.                             Next s
  500.                          End If
  501.                      End If
  502.                     
  503.                      pNode = VScreen(i, j).nextn
  504.                     
  505.                '  Loop ' Pnode <> 0
  506.              
  507.              Next j
  508. '         // Ora trset[0],..., trset[ntrset-1] Φ l'insieme dei
  509. '         // triangoli che possono nascondere i punti di PQ.
  510.          Call linesegment(Pic, SetPoint(Ps, VV(Pnr).Z, Pnr), SetPoint(Qs, VV(Qnr).Z, Qnr), ntrset)
  511.          
  512.          dealwithlinkedstack
  513.          
  514.          Next i
  515.       
  516.       End If ' Ptr = 0
  517.       
  518.    Next Pnr
  519.  
  520. End Sub
  521.  
  522. Sub LComplete_Triangles(n As Integer, offset As Integer, nrs_tr() As Trianrs)
  523.  
  524. ' Completa triangles[offset],..., triangles[offset+n-1].
  525. ' Numeri di vertice: nrs_tr[0],..., nrs_tr[n-1].
  526. ' Questi triangoli appartengono allo stesso poligono. L'equazione
  527. ' del loro piano Φ nx . x + ny . y + nz . z = h.
  528.   
  529.   
  530.   Dim i As Integer
  531.   Dim Anr As Integer
  532.   Dim Bnr As Integer
  533.   Dim Cnr As Integer
  534.   Dim ZA As Integer
  535.   Dim ZB As Integer
  536.   Dim ZC As Integer
  537.  ' Dim zmin As Single
  538.  ' Dim zmax As Single
  539.  
  540.   Dim nx As Double
  541.   Dim ny As Double
  542.   Dim nz As Double
  543.   Dim ux As Double
  544.   Dim uy As Double
  545.   Dim uz As Double
  546.   Dim vx As Double
  547.   Dim vy As Double
  548.   Dim vz As Double
  549.   Dim factor As Double
  550.   Dim h As Double
  551.   Dim Ax As Double
  552.   Dim Ay As Double
  553.   Dim Az As Double
  554.   Dim Bx As Double
  555.   Dim By As Double
  556.   Dim Bz As Double
  557.   Dim Cx As Double
  558.   Dim Cy As Double
  559.   Dim Cz As Double
  560.   
  561.   Dim p As Integer
  562.   Dim q As triadata
  563.   
  564. '   // Se il poligono Φ un'approssimazione di una circonferenza, i
  565. '   // primi tre vertici possono giacere quasi sulla stessa linea,
  566. '   // da cui n/2 invece di 0 nell'istruzione for che segue:
  567.   
  568.   For i = n \ 2 To n
  569.      Anr = nrs_tr(i).a
  570.      Bnr = nrs_tr(i).b
  571.      Cnr = nrs_tr(i).C
  572.      If (orienta(Anr, Bnr, Cnr) > 0) Then Exit For
  573.    Next
  574.  
  575.    ZA = VV(Anr).Z
  576.    ZB = VV(Bnr).Z
  577.    ZC = VV(Cnr).Z
  578.  
  579.    Az = zFloat(ZA)
  580.    Bz = zFloat(ZB)
  581.    Cz = zFloat(ZC)
  582.    Ax = xFloat(VV(Anr).Vt.x) * Az
  583.    Ay = yFloat(VV(Anr).Vt.Y) * Az
  584.    Bx = xFloat(VV(Bnr).Vt.x) * Bz
  585.    By = yFloat(VV(Bnr).Vt.Y) * Bz
  586.    Cx = xFloat(VV(Cnr).Vt.x) * Cz
  587.    Cy = yFloat(VV(Cnr).Vt.Y) * Cz
  588.    ux = Bx - Ax
  589.    uy = By - Ay
  590.    uz = Bz - Az
  591.    vx = Cx - Ax
  592.    vy = Cy - Ay
  593.    vz = Cz - Az
  594.    nx = uy * vz - uz * vy
  595.    ny = uz * vx - ux * vz
  596.    nz = ux * vy - uy * vx
  597.    h = nx * Ax + ny * Ay + nz * Az
  598.    factor = 1 / Sqr(nx * nx + ny * ny + nz * nz)
  599.    q.Normal.x = nx * factor
  600.    q.Normal.Y = ny * factor
  601.    q.Normal.Z = nz * factor
  602.    q.h = h * factor
  603.    For i = 0 To n - 1
  604.       p = offset + i
  605.       Triangles(p).Anr = nrs_tr(i).a
  606.       Triangles(p).Bnr = nrs_tr(i).b
  607.       Triangles(p).Cnr = nrs_tr(i).C
  608.       Triangles(p).PTria = q
  609.    Next
  610.  
  611. End Sub
  612.  
  613.  
  614. Sub linesegment(Pic As PictureBox, p As Point, q As Point, k0 As Integer)
  615.  
  616.  
  617. '   Si deve tracciare il segmento PQ, finchΘ non viene nascosto
  618. '   dai triangoli trset[0],..., trset[k0-1].
  619.    Dim Ps As Vec_Int
  620.    Dim Qs As Vec_Int
  621.    Dim Ass As Vec_Int
  622.    Dim Bs As Vec_Int
  623.    Dim Cs As Vec_Int
  624.    Dim Temp As Vec_Int
  625.    Dim Iss As Vec_Int
  626.    Dim Js As Vec_Int
  627.    
  628.    
  629.    Dim x1 As Single
  630.    Dim x2 As Single
  631.    Dim y1 As Single
  632.    Dim y2 As Single
  633.    Dim xP As Double
  634.    Dim yP As Double
  635.    Dim xQ As Double
  636.    Dim yQ As Double
  637.    Dim zP As Double
  638.    Dim zQ As Double
  639.    Dim xI As Double
  640.    Dim yI As Double
  641.    Dim hP As Double
  642.    Dim hQ As Double
  643.    Dim xJ As Double
  644.    Dim yJ As Double
  645.    Dim lam_min As Double
  646.    Dim lam_max As Double
  647.    Dim lambda As Double
  648.    Dim mu As Double
  649.    Dim hh As Double
  650.    Dim h1 As Double
  651.    Dim h2 As Double
  652.    Dim zI As Double
  653.    Dim zJ As Double
  654.    Dim ZA As Double
  655.    Dim ZB As Double
  656.    Dim ZC As Double
  657.    Dim zmaxPQ As Double
  658.    
  659.    
  660.    Dim Pnr As Integer
  661.    Dim Qnr As Integer
  662.    Dim kk As Integer
  663.    Dim j As Integer
  664.    Dim Anr As Integer
  665.    Dim Bnr As Integer
  666.    Dim Cnr As Integer
  667.    Dim i As Integer
  668.    Dim Poutside As Integer
  669.    Dim Qoutside As Integer
  670.    Dim Pnear As Integer
  671.    Dim Qnear As Integer
  672.    
  673.    Dim APB As Integer
  674.    Dim AQB As Integer
  675.    Dim BPC As Integer
  676.    Dim BQC As Integer
  677.    Dim CPA As Integer
  678.    Dim CQA As Integer
  679.    Dim xminPQ As Integer
  680.    Dim xmaxPQ As Integer
  681.    Dim yminPQ As Integer
  682.    Dim ymaxPQ As Integer
  683.    Dim X_P As Integer
  684.    Dim Y_P As Integer
  685.    Dim X_Q As Integer
  686.    Dim Y_Q As Integer
  687.    Dim u1 As Integer
  688.    Dim U2 As Integer
  689.    
  690.    Dim denom As Long
  691.    Dim v1 As Long
  692.    Dim v2 As Long
  693.    Dim w1 As Long
  694.    Dim w2 As Long
  695.    
  696.    Dim Normal As Vec3
  697.    
  698.    Ps = p.Pntscr
  699.    Qs = q.Pntscr
  700.    
  701.    zP = p.zPnt
  702.    zQ = q.zPnt
  703.    
  704.    Pnr = p.nrPnt
  705.    Qnr = q.nrPnt
  706.    
  707.    X_P = Ps.x
  708.    Y_P = Ps.Y
  709.    X_Q = Qs.x
  710.    Y_Q = Qs.Y
  711.    u1 = X_Q - X_P
  712.    U2 = Y_Q - Y_P
  713.    kk = k0
  714.    
  715.    
  716.    If (X_P < X_Q) Then
  717.       xminPQ = X_P
  718.       xmaxPQ = X_Q
  719.    Else
  720.       xminPQ = X_Q
  721.       xmaxPQ = X_P
  722.    End If
  723.    If (Y_P < Y_Q) Then
  724.       yminPQ = Y_P
  725.       ymaxPQ = Y_Q
  726.    Else
  727.       yminPQ = Y_Q
  728.       ymaxPQ = Y_P
  729.    End If
  730.    
  731.    Do While (kk > 0)
  732.       kk = kk - 1
  733.       j = trset(kk)
  734.       Anr = Triangles(j).Anr
  735.       Bnr = Triangles(j).Bnr
  736.       Cnr = Triangles(j).Cnr
  737.  
  738.  '  Test 1 (3D): PQ Φ uno dei lati del triangolo?
  739.       If ((Pnr = Anr Or Pnr = Bnr Or Pnr = Cnr) And _
  740.           (Qnr = Anr Or Qnr = Bnr Or Qnr = Cnr)) Then GoTo Continua
  741.       
  742.       Ass = VV(Anr).Vt
  743.       Bs = VV(Bnr).Vt
  744.       Cs = VV(Cnr).Vt
  745.  
  746.     '   Test 2 (2D): I test minimax:
  747.       If (xmaxPQ <= Ass.x And xmaxPQ <= Bs.x And xmaxPQ <= Cs.x Or _
  748.           xminPQ >= Ass.x And xminPQ >= Bs.x And xminPQ >= Cs.x Or _
  749.           ymaxPQ <= Ass.Y And ymaxPQ <= Bs.Y And ymaxPQ <= Cs.Y Or _
  750.           yminPQ >= Ass.Y And yminPQ >= Bs.Y And yminPQ >= Cs.Y) Then GoTo Continua
  751.              '  continue; // continue significa: 'visibile'
  752.  
  753.   ' Test 3 (2D): P e Q giacciono in un semipiano definito da
  754.   ' un lato del triangolo ABC (e sono esterni a questo
  755.   ' triangolo)?
  756.       
  757.       APB = orientv(Ass, Ps, Bs)
  758.       AQB = orientv(Ass, Qs, Bs)
  759.       If (APB + AQB > 0) Then GoTo Continua
  760.       BPC = orientv(Bs, Ps, Cs)
  761.       BQC = orientv(Bs, Qs, Cs)
  762.       If (BPC + BQC > 0) Then GoTo Continua
  763.       CPA = orientv(Cs, Ps, Ass)
  764.       CQA = orientv(Cs, Qs, Ass)
  765.       If (CPA + CQA > 0) Then GoTo Continua
  766.  
  767.   ' Test 4 (2D): A, B e C giacciono sullo stesso semipiano
  768.   '               definito da PQ?:
  769.       If (Abs(orientv(Ps, Qs, Ass) + orientv(Ps, Qs, Bs) + orientv(Ps, Qs, Cs)) > 1) Then GoTo Continua
  770.  
  771.   ' Test 5 (3D): Sono sia zP che zQ minori di zA, zB e zC?
  772.       
  773.       ZA = VV(Anr).Z
  774.       ZB = VV(Bnr).Z
  775.       ZC = VV(Cnr).Z
  776.       If zP > zQ Then zmaxPQ = zP Else zmaxPQ = zQ
  777.       
  778.       If (zmaxPQ <= ZA And zmaxPQ <= ZB And zmaxPQ <= ZC) Then GoTo Continua
  779.  
  780.   ' Test 6 (3D): E' vero che nΘ P nΘ Q giacciono dietro il
  781.   '               piano ABC?
  782.       
  783.       Normal = Triangles(j).PTria.Normal
  784.       hh = Triangles(j).PTria.h
  785.       If (hh = 0) Then GoTo Continua    ' Il piano passa per il punto di
  786.                                         ' osservazione
  787.       xP = zP * xFloat(X_P)
  788.       yP = zP * yFloat(Y_P)
  789.       xQ = zQ * xFloat(X_Q)
  790.       yQ = zQ * yFloat(Y_Q)
  791.       hP = Normal.x * xP + Normal.Y * yP + Normal.Z * zP
  792.       hQ = Normal.x * xQ + Normal.Y * yQ + Normal.Z * zQ
  793.       h2 = hh + eps1
  794.       If (hP <= h2 And hQ <= h2) Then GoTo Continua
  795.  
  796.   ' Test 7 (2D) Il triangolo ABC oscura completamente PQ?
  797.   
  798.       Poutside = APB = 1 Or BPC = 1 Or CPA = 1
  799.       Qoutside = AQB = 1 Or BQC = 1 Or CQA = 1
  800.       If (Not Poutside And Not Qoutside) Then Exit Sub
  801.  
  802.   ' Nessuna delle precedenti istruzioni continue Φ stata
  803.   ' eseguita, per cui il segmento PsQs ha dei punti in comune
  804.   ' con il triangolo AsBsCs.
  805.       
  806.       h1 = hh - eps1
  807.       Pnear = hP < h1
  808.       Qnear = hQ < h1
  809.       If (Pnear And Not Poutside Or Qnear And Not Qoutside) Then GoTo Continua
  810.   ' Ora P giace fuori dalla piramide EABC oppure dietro
  811.   ' il triangolo ABC, e lo stesso vale per Q.
  812.  
  813.   ' Ora sono calcolati i punti di intersezione:
  814.       lam_min = 1#
  815.       lam_max = 0#
  816.       For i = 0 To 2
  817.       
  818.          v1 = Bs.x - Ass.x
  819.          v2 = Bs.Y - Ass.Y
  820.          w1 = Ass.x - xP
  821.          w2 = Ass.Y - yP
  822.          denom = u1 * v2 - U2 * v1
  823.          If (denom <> 0) Then       ' PsQs non parallelo ad AsBs
  824.             mu = (U2 * w1 - u1 * w2) / CDbl(denom)
  825.             ' mu = 0 dα A, e mu = 1 dα B.
  826.             If (mu > -0.0001 And mu < 1.0001) Then
  827.                lambda = (v2 * w1 - v1 * w2) / CDbl(denom)
  828.                ' lambda = PI/PQ (I Φ il punto di intersezione)
  829.                If (lambda > -0.0001 And lambda < 1.0001) Then
  830.                   If (Poutside <> Qoutside And _
  831.                   lambda > 0.0001 And lambda < 0.9999) Then
  832.                      lam_min = lam_max = lambda
  833.                      Exit For     '  Un solo punto di intersezione
  834.                   End If
  835.                   If (lambda < lam_min) Then lam_min = lambda
  836.                   If (lambda > lam_max) Then lam_max = lambda
  837.                End If ' lambda ...
  838.             End If ' mu > -...
  839.          End If ' Denom <> 0
  840.          Temp = Ass
  841.          Ass = Bs
  842.          Bs = Cs
  843.          Cs = Temp
  844.       Next i
  845.       
  846.    '  Test 8: I e J sono punti di intersezione.
  847.    '  Verifica se questi punti giacciono di fronte al
  848.    '  triangolo ABC:
  849.       
  850.       If (Poutside And lam_min > 0.01) Then
  851.          Iss.x = Int(xP + lam_min * u1 + 0.5)
  852.          Iss.Y = Int(yP + lam_min * U2 + 0.5)
  853.          zI = 1 / (lam_min / zQ + (1 - lam_min) / zP)
  854.          xI = zI * xFloat(Iss.x)
  855.          yI = zI * yFloat(Iss.Y)
  856.          If (Normal.x * xI + Normal.Y * yI + Normal.Z * zI) < h1 Then GoTo Continua
  857.          Call stack_linesegment(SetPoint(Ps, zP, Pnr), SetPoint(Iss, zI, -1), kk)
  858.       End If ' POutside..
  859.       If (Qoutside And lam_max < 0.99) Then
  860.          Js.x = Int(xP + lam_max * u1 + 0.5)
  861.          Js.Y = Int(yP + lam_max * U2 + 0.5)
  862.          zJ = 1 / (lam_max / zQ + (1 - lam_max) / zP)
  863.          xJ = zJ * xFloat(Js.x)
  864.          yJ = zJ * yFloat(Js.Y)
  865.          If (Normal.x * xJ + Normal.Y * yJ + Normal.Z * zJ) < h1 Then GoTo Continua
  866.          
  867.          Call stack_linesegment(SetPoint(Qs, zQ, Qnr), SetPoint(Js, zJ, -1), kk)
  868.       End If ' Qoutside..
  869.       
  870.       Exit Sub  '  Solo se non Φ stata eseguita nessuna istruzione
  871.                 '  Goto Continua
  872. Continua:
  873.  
  874.    Loop ' While (kk > 0)
  875.    
  876.    x1 = SetX(d * xFloat(X_P) + c1)
  877.    y1 = SetY(d * yFloat(Y_P) + c2)
  878.    x2 = SetX(d * xFloat(X_Q) + c1)
  879.    y2 = SetY(d * yFloat(Y_Q) + c2)
  880.    
  881.    Pic.Line (x1, y1)-(x2, y2)
  882.    
  883. '   Ms = " x1= " & x1 & Chr(10)
  884. '   Ms = Ms & " y1= " & y1 & Chr(10)
  885. '   Ms = Ms & " x2= " & x2 & Chr(10)
  886. '   Ms = Ms & " y2= " & y2
  887. '   MsgBox Ms
  888.    
  889.   ' move(d * xfloat(XP) + c1, d * yfloat(YP) + c2);
  890.   ' draw(d * xfloat(XQ) + c1, d * yfloat(YQ) + c2);
  891.  
  892.  
  893. End Sub
  894.  
  895.  
  896. Function LOrienta(Pnr As Integer, Qnr As Integer, Rnr As Integer) As Integer
  897.  Dim Ps As Vec_Int
  898.  Dim Qs As Vec_Int
  899.  Dim Rs As Vec_Int
  900.  
  901.  Dim u1 As Integer
  902.  Dim U2 As Integer
  903.  Dim v1 As Integer
  904.  Dim v2 As Integer
  905.  
  906.  Dim Det As Long
  907.  
  908.  Ps = VV(Pnr).Vt
  909.  Qs = VV(Qnr).Vt
  910.  Rs = VV(Rnr).Vt
  911.  
  912.  u1 = Qs.x - Ps.x
  913.  U2 = Qs.Y - Ps.Y
  914.  v1 = Rs.x - Ps.x
  915.  v2 = Rs.Y - Ps.Y
  916.  
  917.  Det = CLng(u1) * v2 - CLng(U2) * v1
  918.  
  919.  If Det < -300 Then
  920.     LOrienta = -1
  921.  Else
  922.     LOrienta = Abs(Det > 300)
  923.  End If
  924.  
  925. End Function
  926.  
  927. Function orientv(Ps As Vec_Int, Qs As Vec_Int, Rs As Vec_Int) As Integer
  928.  Dim u1 As Integer
  929.  Dim U2 As Integer
  930.  Dim v1 As Integer
  931.  Dim v2 As Integer
  932.  
  933.  Dim Det As Long
  934.   
  935.  u1 = Qs.x - Ps.x
  936.  U2 = Qs.Y - Ps.Y
  937.  v1 = Rs.x - Ps.x
  938.  v2 = Rs.Y - Ps.Y
  939.  
  940.  Det = CLng(u1) * v2 - CLng(U2) * v1
  941.    
  942.  If Det < -10 Then
  943.     orientv = -1
  944.  Else
  945.     orientv = Det > 10
  946.  End If
  947.  
  948. End Function
  949.  
  950. Function RowNr(Y As Integer) As Integer
  951.          RowNr = (CLng(Y) * Nscreen) / LARGE1
  952. End Function
  953.  
  954.  
  955. Function SetPoint(p As Vec_Int, Z As Double, nr As Integer) As Point
  956.    SetPoint.Pntscr = p
  957.    SetPoint.zPnt = Z
  958.    SetPoint.nrPnt = nr
  959. End Function
  960.  
  961. Sub setupscreenlist(Tr() As Tria, n As Integer)
  962.  
  963. '   Predispone le liste dei triangoli indicati con TR[0],...,
  964. '   TR[n-1].
  965.  Dim i As Integer
  966.  Dim l As Integer
  967.  Dim j As Integer
  968.  Dim iMin As Integer
  969.  Dim iMax As Integer
  970.  Dim j_old As Integer
  971.  Dim jI As Integer
  972.  Dim topcode(2) As Integer
  973.  Dim iLeft As Integer
  974.  Dim iRight As Integer
  975.  Dim LLOWER(Nscreen) As Integer
  976.  Dim LUPPER(Nscreen) As Integer
  977.  
  978.  Dim deltax As Long
  979.  Dim deltay As Long
  980.  
  981.  Dim Ass As Vec_Int
  982.  Dim Bs As Vec_Int
  983.  Dim Cs As Vec_Int
  984.  Dim vLeft(2) As Vec_Int
  985.  Dim vRight(2) As Vec_Int
  986.  Dim Aux As Vec_Int
  987.  
  988.  Dim p As Integer
  989.  Dim p_New As Integer
  990.  Dim p_old As Integer
  991.  
  992.  '  tria huge*p;
  993.  '  node huge*p_new, huge*p_old;
  994.    
  995.  For i = 0 To n - 1
  996.      p = i
  997.      Ass = VV(Tr(p).Anr).Vt
  998.      Bs = VV(Tr(p).Bnr).Vt
  999.      Cs = VV(Tr(p).Cnr).Vt
  1000.      
  1001.    '  MsgBox "Triangolo: " & i
  1002.    '  Ms = "Ass.x= " & Ass.X & Chr(10)
  1003.    '  Ms = Ms & "Ass.y= " & Ass.Y & Chr(10)
  1004.    '  MsgBox Ms
  1005.    '  Ms = "Bs.x= " & Bs.X & Chr(10)
  1006.    '  Ms = Ms & "Bs.y= " & Bs.Y & Chr(10)
  1007.    '  MsgBox Ms
  1008.    '  Ms = "Cs.x= " & Cs.X & Chr(10)
  1009.    '  Ms = Ms & "Cs.y= " & Cs.Y & Chr(10)
  1010.    '  MsgBox Ms
  1011.      
  1012.      topcode(0) = Ass.x > Bs.x  ' // Per l'orientamento positivo
  1013.      topcode(1) = Cs.x > Ass.x
  1014.      topcode(2) = Bs.x > Cs.x
  1015.      vLeft(0) = Ass
  1016.      vRight(0) = Bs
  1017.      vLeft(1) = Ass
  1018.      vRight(1) = Cs
  1019.      vLeft(2) = Bs
  1020.      vRight(2) = Cs
  1021.      For l = 0 To 2 '  // l = numero di lati del triangolo
  1022.         If (vLeft(l).x > vRight(l).x Or _
  1023.            (vLeft(l).x = vRight(l).x And vLeft(l).Y > vRight(l).Y)) Then
  1024.              Aux = vLeft(l)
  1025.              vLeft(l) = vRight(l)
  1026.              vRight(l) = Aux
  1027.         End If
  1028.      Next l
  1029.         
  1030.      iMin = ColNr(Min3(Ass.x, Bs.x, Cs.x))
  1031.      iMax = ColNr(Max3(Ass.x, Bs.x, Cs.x))
  1032.       
  1033.      'iMin = Max2(iMin, 0)
  1034.       
  1035.      For ii = iMin To iMax
  1036.          LLOWER(ii) = 32000
  1037.          LUPPER(ii) = -32000
  1038.      Next ii
  1039.        
  1040.      For l = 0 To 2
  1041.          iLeft = ColNr(vLeft(l).x)
  1042.          iRight = ColNr(vRight(l).x)
  1043.          If (iLeft <> iRight) Then
  1044.            deltay = vRight(l).Y - vLeft(l).Y
  1045.            deltax = vRight(l).x - vLeft(l).x
  1046.          End If
  1047.          j_old = RowNr(vLeft(l).Y)
  1048.          For ii = iLeft To iRight
  1049.              If ii = iRight Then
  1050.                 jI = RowNr(vRight(l).Y)
  1051.              Else
  1052.                 g& = vLeft(l).Y + CLng(xCoord(ii + 1) - vLeft(l).x * deltay / deltax)
  1053.                 If g& > 32000 Then g& = 32000
  1054.                 If g& < 0 Then g& = 0
  1055.                 jI = RowNr(CInt(g&))
  1056.              End If
  1057.             If topcode(l) Then
  1058.                LUPPER(ii) = Max3(j_old, jI, LUPPER(ii))
  1059.             Else
  1060.                LLOWER(ii) = Min3(j_old, jI, LLOWER(ii))
  1061.             End If
  1062.             j_old = jI
  1063.          Next ii
  1064.       
  1065.       Next l
  1066.       
  1067. '      // Per la colonna I del video, il triangolo Φ associato solo
  1068. '      // con i rettangoli delle righe LOWER[I],...,UPPER[I].
  1069.       
  1070.        For ii = iMin To iMax
  1071.           For j = LLOWER(ii) To LUPPER(ii)
  1072.   
  1073.              p_New = p_New + 1
  1074.   
  1075.              p_old = VScreen(ii, j).idx
  1076.   
  1077.              VScreen(ii, j).idx = p_New
  1078.              VScreen(ii, j).jtr = i
  1079.              VScreen(ii, j).nextn = p_old
  1080.   
  1081.           Next j
  1082.        Next ii
  1083.  Next i
  1084.  
  1085.  
  1086. '{  // Predispone le liste dei triangoli indicati con TR[0],...,
  1087. '   // TR[n-1].
  1088. '   int i, l, I, J, Imin, Imax, j_old, jI, topcode[3],
  1089. '      ileft, iright, LOWER[Nscreen], UPPER[Nscreen];
  1090. '   long deltax, deltay;
  1091. '   vec_int As, Bs, Cs, Left[3], Right[3], Aux;
  1092. '   tria huge*p;
  1093. '   node huge*p_new, huge*p_old;
  1094. '   for (i=0; i<n; i++)
  1095. '   {  p = TR + i;
  1096. '      As = V[p->Anr].VT; Bs = V[p->Bnr].VT; Cs = V[p->Cnr].VT;
  1097. '      topcode[0] = As.X > Bs.X; // Per l'orientamento positivo
  1098. '      topcode[1] = Cs.X > As.X;
  1099. '      topcode[2] = Bs.X > Cs.X;
  1100.  
  1101. '      Left[0] = As; Right[0] = Bs;
  1102. '      Left[1] = As; Right[1] = Cs;
  1103. '      Left[2] = Bs; Right[2] = Cs;
  1104. '      for (l=0; l<3; l++)  // l = numero di lati del triangolo
  1105. '         if (Left[l].X > Right[l].X ||
  1106. '         (Left[l].X == Right[l].X && Left[l].Y > Right[l].Y))
  1107. '         {  Aux = Left[l]; Left[l] = Right[l]; Right[l] = Aux;
  1108. '         }
  1109. '      Imin = colnr(min3(As.X, Bs.X, Cs.X));
  1110. '      Imax = colnr(max3(As.X, Bs.X, Cs.X));
  1111. '      for (I = Imin; I<=Imax; I++)
  1112. '      {  LOWER[I] = INT_MAX; UPPER[I] = INT_MIN;
  1113. '      }
  1114. '      for (l=0; l<3; l++)
  1115. '      {  ileft = colnr(Left[l].X); iright = colnr(Right[l].X);
  1116. '         if (ileft != iright)
  1117. '         { deltay = Right[l].Y - Left[l].Y;
  1118. '           deltax = Right[l].X - Left[l].X;
  1119. '         }
  1120. '         j_old = rownr(Left[l].Y);
  1121. '         for (I=ileft; I<=iright; I++)
  1122. '         {  jI = (I == iright ? rownr(Right[l].Y) : rownr(Left[l].Y
  1123. '                  + (Xcoord(I+1) - Left[l].X) * deltay / deltax));
  1124. '            if (topcode[l])
  1125. '                UPPER[I] = max3(j_old, jI, UPPER[I]);
  1126. '            else LOWER[I] = min3(j_old, jI, LOWER[I]);
  1127. '            j_old = jI;
  1128. '         }
  1129. '      }
  1130. '      // Per la colonna I del video, il triangolo è associato solo
  1131. '      // con i rettangoli delle righe LOWER[I],...,UPPER[I].
  1132. '      for (I=Imin; I<=Imax; I++)
  1133. '      for (J=LOWER[I]; J<=UPPER[I]; J++)
  1134. '      {  p_old = SCREEN[I][J];
  1135. '         SCREEN[I][J] = p_new = AllocMem1(node);
  1136. '         if (p_new == NULL) memproblem('G');
  1137. '         p_new->jtr = i; p_new->next = p_old;
  1138. '      }
  1139. '   }
  1140. '}
  1141.  
  1142. End Sub
  1143.  
  1144.  
  1145. Function SetX(x As Double) As Integer
  1146.     x = Int(density * (x - x_min))
  1147.     If (x < 0) Then
  1148.        x = 0
  1149.        outside = 1
  1150.     End If
  1151.     If (x > X__max) Then
  1152.       x = X__max
  1153.       outside = 1
  1154.     End If
  1155.    SetX = x
  1156. End Function
  1157.  
  1158. Function SetY(Y As Double) As Integer
  1159.  
  1160.    Y = Y__max - Int(density * (Y - y_min))
  1161.    If (Y < 0) Then
  1162.       Y = 0
  1163.       outside = 1
  1164.    End If
  1165.    
  1166.    If (Y > Y__max) Then
  1167.       Y = Y__max
  1168.       outside = 1
  1169.    End If
  1170.    
  1171.    SetY = Y
  1172.  
  1173. End Function
  1174.  
  1175.  
  1176. Sub stack_linesegment(p As Point, q As Point, k0 As Integer)
  1177.  
  1178.   Dim Pt As Integer
  1179.   Dim xP As Integer
  1180.   Dim yP As Integer
  1181.   Dim xQ As Integer
  1182.   Dim yQ As Integer
  1183.   xP = p.Pntscr.x
  1184.   yP = p.Pntscr.Y
  1185.   xQ = q.Pntscr.x
  1186.   yQ = q.Pntscr.Y
  1187.   If (Abs(xP - xQ) + Abs(yP - yQ) < 50) Then Exit Sub ' Non conviene
  1188.   
  1189.  ' Pt = UBound(stptr) + 1
  1190.  ' ReDim Preserve stptr(Pt)
  1191.   
  1192.   stptr(Pt).p = p
  1193.   stptr(Pt).q = q
  1194.   stptr(Pt).k0 = k0
  1195.   
  1196. End Sub
  1197.  
  1198.  
  1199. Function xCoord(nr As Integer) As Integer
  1200.   xCoord = (CLng(nr) * LARGE) / Nscreen
  1201. End Function
  1202.  
  1203. Function xFloat(x As Integer) As Double
  1204.       xFloat = (x / xfactor) + xmin
  1205. End Function
  1206.  
  1207. Function zFloat(Z As Integer) As Double
  1208.       zFloat = Z / zfactor + zmin
  1209. End Function
  1210.  
  1211.  
  1212. Function xIntScr(x As Double, xxMin As Double) As Integer
  1213.    xIntScr = (x - xxMin) * xfactor + 1 '0.5
  1214. End Function
  1215.  
  1216. Function yFloat(Y As Integer) As Double
  1217.    yFloat = (Y / yfactor) + ymin
  1218. End Function
  1219.  
  1220. Function yIntScr(Y As Double, yyMin As Double) As Integer
  1221.    yIntScr = (Y - yyMin) * yfactor + 1 '  0.5
  1222. End Function
  1223.  
  1224.