home *** CD-ROM | disk | FTP | other *** search
/ PSION CD 2 / PsionCDVol2.iso / Programs / 1169 / Shade3D.txt < prev   
Encoding:
Text File  |  2001-04-10  |  18.0 KB  |  543 lines

  1. DECLARE EXTERNAL
  2.  
  3. EXTERNAL DivisionIndex%:(XDivisionNum%,YDivisionNum%,NumXDivisions%,NumYDivisions%)
  4. EXTERNAL DrawLine:
  5. EXTERNAL F:(X,Y)
  6.  
  7. PROC Plot3D:
  8.   GLOBAL BoxX1%
  9.   GLOBAL BoxX2%
  10.   GLOBAL BoxY1%
  11.   GLOBAL InterceptCountMod2%
  12.   LOCAL AspectRatio
  13.   LOCAL Bias
  14.   LOCAL BoxDeltaX
  15.   LOCAL BoxDeltaY
  16.   LOCAL BoxNum1%
  17.   LOCAL BoxNum2%
  18.   LOCAL BoxX%(4)
  19.   LOCAL BoxXIntercept
  20.   LOCAL BoxY%(4)
  21.   LOCAL BoxYMax%
  22.   LOCAL BoxYMin%
  23.   LOCAL BoxYOffset
  24.   LOCAL Color%(1000)
  25.   LOCAL ColorMax%
  26.   LOCAL ColorMin%
  27.   LOCAL ColorNum%
  28.   LOCAL CosRotation
  29.   LOCAL CosTilt
  30.   LOCAL DarkestGray%
  31.   LOCAL DeltaX
  32.   LOCAL DeltaY
  33.   LOCAL DeltaZ
  34.   LOCAL DivIndex%
  35.   LOCAL Finished%
  36.   LOCAL Fraction
  37.   LOCAL idPlot%
  38.   LOCAL KeyIndex1%
  39.   LOCAL KeyIndex2%
  40.   LOCAL Largest
  41.   LOCAL LightestGray%
  42.   LOCAL LightX
  43.   LOCAL LightY
  44.   LOCAL LightZ
  45.   LOCAL Magnitude
  46.   LOCAL MaxYOut%
  47.   LOCAL MaxZOut%
  48.   LOCAL NormalX
  49.   LOCAL NormalY
  50.   LOCAL NormalZ
  51.   LOCAL NumXDivisions%
  52.   LOCAL NumXPrimes%
  53.   LOCAL NumYDivisions%
  54.   LOCAL PixelsPerUnit
  55.   LOCAL Response$(1)
  56.   LOCAL Radians
  57.   LOCAL RadiansPerDegree
  58.   LOCAL Rotation
  59.   LOCAL SinRotation
  60.   LOCAL SinTilt
  61.   LOCAL Smallest
  62.   LOCAL SortLeft%
  63.   LOCAL SortRight%
  64.   LOCAL SortT1
  65.   LOCAL SortT2%
  66.   LOCAL SortT3%
  67.   LOCAL Tilt
  68.   LOCAL VertexX(4)
  69.   LOCAL VertexY(4)
  70.   LOCAL VertexZ(4)
  71.   LOCAL X
  72.   LOCAL XDivisionIndex%(1000)
  73.   LOCAL XDivisionNum%
  74.   LOCAL XEye
  75.   LOCAL XMax
  76.   LOCAL XMin
  77.   LOCAL XPrime(1000)
  78.   LOCAL XPrimeMax
  79.   LOCAL XPrimeNum%
  80.   LOCAL XRotated
  81.   LOCAL Y
  82.   LOCAL YCenter
  83.   LOCAL YDivisionIndex%(1000)
  84.   LOCAL YDivisionNum%
  85.   LOCAL YMax
  86.   LOCAL YMin
  87.   LOCAL YOffset
  88.   LOCAL YOutMax
  89.   LOCAL YPrime(1000)
  90.   LOCAL YPrimeMax
  91.   LOCAL YPrimeMin
  92.   LOCAL Z
  93.   LOCAL ZCenter
  94.   LOCAL ZOffset
  95.   LOCAL ZOutMax
  96.   LOCAL ZPrime(1000)
  97.   LOCAL ZPrimeMax
  98.   LOCAL ZPrimeMin
  99.   CLS
  100.   MaxYOut%=639
  101.   MaxZOut%=239
  102.   PRINT "                             Three Dimensional Plot"
  103.   PRINT
  104.   PRINT
  105.   PRINT
  106.   PRINT "Smallest value for x? ";
  107.   INPUT XMin
  108.   PRINT "Largest value for x? ";
  109.   INPUT XMax
  110.   PRINT "Smallest value for y? ";
  111.   INPUT YMin
  112.   PRINT "Largest value for y? ";
  113.   INPUT YMax
  114.   DO
  115.     PRINT "Number of divisions for x? ";
  116.     INPUT NumXDivisions%
  117.     IF NumXDivisions% <= 1 OR NumXDivisions% > 1000
  118.       PRINT "? there must be at least 2 and no more than 1000 divisions"
  119.     ENDIF
  120.   UNTIL NumXDivisions% > 1 AND NumXDivisions% <= 1000
  121.   DO
  122.     PRINT "Number of divisions for y? ";
  123.     INPUT NumYDivisions%
  124.     IF NumYDivisions% <= 1 OR NumYDivisions% > 1000/NumXDivisions%
  125.       PRINT "? there must be at least 2 and no more than ";1000/NumXDivisions%;" divisions"
  126.     ENDIF
  127.   UNTIL NumYDivisions% > 1 AND NumYDivisions% <= 1000/NumXDivisions%
  128.   DO
  129.     PRINT "Rotation about the z-axis (degrees)? ";
  130.     INPUT Rotation
  131.     PRINT "Tilt about the resulting y-axis (degrees)? ";
  132.     INPUT Tilt
  133.     PRINT "After the plot is displayed, press a key to continue."
  134.     PRINT "Evaluating function..."
  135.     RadiansPerDegree=ATAN(1.0)/45.0
  136.     Radians=Tilt*RadiansPerDegree
  137.     CosTilt=COS(Radians)
  138.     SinTilt=SIN(Radians)
  139.     Rotation=-(Rotation+90)
  140.     Radians=Rotation*RadiansPerDegree
  141.     CosRotation=COS(Radians)
  142.     SinRotation=SIN(Radians)
  143.     X=XMin
  144.     Y=YMin
  145.     Z=F:(X,Y)
  146.     XRotated=XMin*CosRotation+YMin*SinRotation
  147.     YPrimeMin=-XMin*SinRotation+YMin*CosRotation
  148.     ZPrimeMin=-XRotated*SinTilt+Z*CosTilt
  149.     YPrimeMax=YPrimeMin
  150.     ZPrimeMax=ZPrimeMin
  151.     XPrimeMax=XRotated*CosTilt+Z*SinTilt
  152.     DeltaX=NumXDivisions%
  153.     DeltaX=(XMax-XMin)/DeltaX
  154.     DeltaY=NumYDivisions%
  155.     DeltaY=(YMax-YMin)/DeltaY
  156.     X=XMin
  157.     NumXPrimes%=0
  158.     XDivisionNum%=1
  159.     WHILE XDivisionNum% <= NumXDivisions%
  160.       Y=YMin
  161.       YDivisionNum%=1
  162.       WHILE YDivisionNum% <= NumYDivisions%
  163.         Z=F:(X,Y)
  164.         NumXPrimes%=NumXPrimes%+1
  165.         XDivisionIndex%(NumXPrimes%)=XDivisionNum%
  166.         YDivisionIndex%(NumXPrimes%)=YDivisionNum%
  167.         XRotated=X*CosRotation+Y*SinRotation
  168.         YPrime(NumXPrimes%)=-X*SinRotation+Y*CosRotation
  169.         XPrime(NumXPrimes%)=XRotated*CosTilt+Z*SinTilt
  170.         ZPrime(NumXPrimes%)=-XRotated*SinTilt+Z*CosTilt
  171.         IF XPrime(NumXPrimes%) > XPrimeMax
  172.           XPrimeMax=XPrime(NumXPrimes%)
  173.         ENDIF
  174.         IF YPrime(NumXPrimes%) < YPrimeMin
  175.           YPrimeMin=YPrime(NumXPrimes%)
  176.         ENDIF
  177.         IF YPrime(NumXPrimes%) > YPrimeMax
  178.           YPrimeMax=YPrime(NumXPrimes%)
  179.         ENDIF
  180.         IF ZPrime(NumXPrimes%) < ZPrimeMin
  181.           ZPrimeMin=ZPrime(NumXPrimes%)
  182.         ENDIF
  183.         IF ZPrime(NumXPrimes%) > ZPrimeMax
  184.           ZPrimeMax=ZPrime(NumXPrimes%)
  185.         ENDIF
  186.         Y=Y+DeltaY
  187.         YDivisionNum%=YDivisionNum%+1
  188.       ENDWH
  189.       X=X+DeltaX
  190.       XDivisionNum%=XDivisionNum%+1
  191.     ENDWH
  192.     PRINT "Shading..."
  193.     LightX=1.0
  194.     LightY=-1.0
  195.     LightZ=1.0
  196.     Magnitude=SQR(LightX*LightX+LightY*LightY+LightZ*LightZ)
  197.     LightX=LightX/Magnitude
  198.     LightY=LightY/Magnitude
  199.     LightZ=LightZ/Magnitude
  200.     ColorMin%=255
  201.     ColorMax%=0
  202.     NumXPrimes%=0
  203.     XDivisionNum%=1
  204.     WHILE XDivisionNum% <= NumXDivisions%
  205.       YDivisionNum%=1
  206.       WHILE YDivisionNum% <= NumYDivisions%
  207.         NumXPrimes%=NumXPrimes%+1
  208.         VertexX(1)=XPrime(NumXPrimes%)
  209.         VertexY(1)=YPrime(NumXPrimes%)
  210.         VertexZ(1)=ZPrime(NumXPrimes%)
  211.         IF XDivisionNum% < NumXDivisions%
  212.           IF YDivisionNum% < NumYDivisions%
  213.             NumXPrimes%=NumXPrimes%+NumYDivisions%
  214.             VertexX(2)=XPrime(NumXPrimes%)
  215.             VertexY(2)=YPrime(NumXPrimes%)
  216.             VertexZ(2)=ZPrime(NumXPrimes%)
  217.             NumXPrimes%=NumXPrimes%+1
  218.             VertexX(3)=XPrime(NumXPrimes%)
  219.             VertexY(3)=YPrime(NumXPrimes%)
  220.             VertexZ(3)=ZPrime(NumXPrimes%)
  221.             NumXPrimes%=NumXPrimes%-NumYDivisions%
  222.             VertexX(4)=XPrime(NumXPrimes%)
  223.             VertexY(4)=YPrime(NumXPrimes%)
  224.             VertexZ(4)=ZPrime(NumXPrimes%)
  225.             NumXPrimes%=NumXPrimes%-1
  226.           ELSE
  227.             NumXPrimes%=NumXPrimes%-1
  228.             VertexX(2)=XPrime(NumXPrimes%)
  229.             VertexY(2)=YPrime(NumXPrimes%)
  230.             VertexZ(2)=ZPrime(NumXPrimes%)
  231.             NumXPrimes%=NumXPrimes%+NumYDivisions%
  232.             VertexX(3)=XPrime(NumXPrimes%)
  233.             VertexY(3)=YPrime(NumXPrimes%)
  234.             VertexZ(3)=ZPrime(NumXPrimes%)
  235.             NumXPrimes%=NumXPrimes%+1
  236.             VertexX(4)=XPrime(NumXPrimes%)
  237.             VertexY(4)=YPrime(NumXPrimes%)
  238.             VertexZ(4)=ZPrime(NumXPrimes%)
  239.             NumXPrimes%=NumXPrimes%-NumYDivisions%
  240.           ENDIF
  241.         ELSE
  242.           IF YDivisionNum% < NumYDivisions%
  243.             NumXPrimes%=NumXPrimes%+1
  244.             VertexX(2)=XPrime(NumXPrimes%)
  245.             VertexY(2)=YPrime(NumXPrimes%)
  246.             VertexZ(2)=ZPrime(NumXPrimes%)
  247.             NumXPrimes%=NumXPrimes%-NumYDivisions%
  248.             VertexX(3)=XPrime(NumXPrimes%)
  249.             VertexY(3)=YPrime(NumXPrimes%)
  250.             VertexZ(3)=ZPrime(NumXPrimes%)
  251.             NumXPrimes%=NumXPrimes%-1
  252.             VertexX(4)=XPrime(NumXPrimes%)
  253.             VertexY(4)=YPrime(NumXPrimes%)
  254.             VertexZ(4)=ZPrime(NumXPrimes%)
  255.             NumXPrimes%=NumXPrimes%+NumYDivisions%
  256.           ELSE
  257.             NumXPrimes%=NumXPrimes%-NumYDivisions%
  258.             VertexX(2)=XPrime(NumXPrimes%)
  259.             VertexY(2)=YPrime(NumXPrimes%)
  260.             VertexZ(2)=ZPrime(NumXPrimes%)
  261.             NumXPrimes%=NumXPrimes%-1
  262.             VertexX(3)=XPrime(NumXPrimes%)
  263.             VertexY(3)=YPrime(NumXPrimes%)
  264.             VertexZ(3)=ZPrime(NumXPrimes%)
  265.             NumXPrimes%=NumXPrimes%+NumYDivisions%
  266.             VertexX(4)=XPrime(NumXPrimes%)
  267.             VertexY(4)=YPrime(NumXPrimes%)
  268.             VertexZ(4)=ZPrime(NumXPrimes%)
  269.             NumXPrimes%=NumXPrimes%+1
  270.           ENDIF
  271.         ENDIF
  272.         REM Compute the normal to a quadrilateral by averaging the
  273.         REM normals to each vertex of the quadrilateral.
  274.         NormalX=(VertexY(2)-VertexY(1))*(VertexZ(4)-VertexZ(1))
  275.         NormalX=NormalX-(VertexY(4)-VertexY(1))*(VertexZ(2)-VertexZ(1))
  276.         NormalX=NormalX+(VertexY(3)-VertexY(2))*(VertexZ(1)-VertexZ(2))
  277.         NormalX=NormalX-(VertexY(1)-VertexY(2))*(VertexZ(3)-VertexZ(2))
  278.         NormalX=NormalX+(VertexY(4)-VertexY(3))*(VertexZ(2)-VertexZ(3))
  279.         NormalX=NormalX-(VertexY(2)-VertexY(3))*(VertexZ(4)-VertexZ(3))
  280.         NormalX=NormalX+(VertexY(1)-VertexY(4))*(VertexZ(3)-VertexZ(4))
  281.         NormalX=NormalX-(VertexY(3)-VertexY(4))*(VertexZ(1)-VertexZ(4))
  282.         NormalY=(VertexX(4)-VertexX(1))*(VertexZ(2)-VertexZ(1))
  283.         NormalY=NormalY-(VertexX(2)-VertexX(1))*(VertexZ(4)-VertexZ(1))
  284.         NormalY=NormalY+(VertexX(1)-VertexX(2))*(VertexZ(3)-VertexZ(2))
  285.         NormalY=NormalY-(VertexX(3)-VertexX(2))*(VertexZ(1)-VertexZ(2))
  286.         NormalY=NormalY+(VertexX(2)-VertexX(3))*(VertexZ(4)-VertexZ(3))
  287.         NormalY=NormalY-(VertexX(4)-VertexX(3))*(VertexZ(2)-VertexZ(3))
  288.         NormalY=NormalY+(VertexX(3)-VertexX(4))*(VertexZ(1)-VertexZ(4))
  289.         NormalY=NormalY-(VertexX(1)-VertexX(4))*(VertexZ(3)-VertexZ(4))
  290.         NormalZ=(VertexX(2)-VertexX(1))*(VertexY(4)-VertexY(1))
  291.         NormalZ=NormalZ-(VertexX(4)-VertexX(1))*(VertexY(2)-VertexY(1))
  292.         NormalZ=NormalZ+(VertexX(3)-VertexX(2))*(VertexY(1)-VertexY(2))
  293.         NormalZ=NormalZ-(VertexX(1)-VertexX(2))*(VertexY(3)-VertexY(2))
  294.         NormalZ=NormalZ+(VertexX(4)-VertexX(3))*(VertexY(2)-VertexY(3))
  295.         NormalZ=NormalZ-(VertexX(2)-VertexX(3))*(VertexY(4)-VertexY(3))
  296.         NormalZ=NormalZ+(VertexX(1)-VertexX(4))*(VertexY(3)-VertexY(4))
  297.         NormalZ=NormalZ-(VertexX(3)-VertexX(4))*(VertexY(1)-VertexY(4))
  298.         Magnitude=SQR(NormalX*NormalX+NormalY*NormalY+NormalZ*NormalZ)
  299.         IF Magnitude = 0.0
  300.           ColorMin%=0
  301.           Color%(NumXPrimes%)=0
  302.         ELSE
  303.           ColorNum%=INT((256.0/2.0)*(1.0+(LightX*NormalX+LightY*NormalY+LightZ*NormalZ)/Magnitude))
  304.           IF ColorNum% > 255
  305.             ColorNum%=255
  306.           ENDIF
  307.           Color%(NumXPrimes%)=ColorNum%
  308.           IF ColorNum% < ColorMin%
  309.             ColorMin%=ColorNum%
  310.           ENDIF
  311.           IF ColorNum% > ColorMax%
  312.             ColorMax%=ColorNum%
  313.           ENDIF
  314.         ENDIF
  315.         YDivisionNum%=YDivisionNum%+1
  316.       ENDWH
  317.       XDivisionNum%=XDivisionNum%+1
  318.     ENDWH
  319.     PRINT "Adjusting perspective..."
  320.     IF YPrimeMax-YPrimeMin > ZPrimeMax-ZPrimeMin
  321.       XEye=2.0*(YPrimeMax-YPrimeMin)+XPrimeMax
  322.     ELSE
  323.       XEye=2.0*(ZPrimeMax-ZPrimeMin)+XPrimeMax
  324.     ENDIF
  325.     IF ZPrimeMax <> ZPrimeMin
  326.       YCenter=(YPrimeMax+YPrimeMin)/2.0
  327.       ZCenter=(ZPrimeMax+ZPrimeMin)/2.0
  328.       NumXPrimes%=0
  329.       XDivisionNum%=1
  330.       WHILE XDivisionNum% <= NumXDivisions%
  331.         Y=YMin
  332.         YDivisionNum%=1
  333.         WHILE YDivisionNum% <= NumYDivisions%
  334.           NumXPrimes%=NumXPrimes%+1
  335.           X=XPrime(NumXPrimes%)
  336.           Y=YPrime(NumXPrimes%)
  337.           Z=ZPrime(NumXPrimes%)
  338.           DeltaX=X-XEye
  339.           DeltaY=Y-YCenter
  340.           DeltaZ=Z-ZCenter
  341.           XPrime(NumXPrimes%)=SQR(DeltaX*DeltaX+DeltaY*DeltaY+DeltaZ*DeltaZ)
  342.           YPrime(NumXPrimes%)=YCenter+(Y-YCenter)*(XEye-XPrimeMax)/(XEye-X)
  343.           ZPrime(NumXPrimes%)=ZCenter+(Z-ZCenter)*(XEye-XPrimeMax)/(XEye-X)
  344.           YDivisionNum%=YDivisionNum%+1
  345.         ENDWH
  346.         XDivisionNum%=XDivisionNum%+1
  347.       ENDWH
  348.     ENDIF
  349.     PRINT "Sorting points..."
  350.     SortLeft%=NumXPrimes%/2
  351.     SortLeft%=SortLeft%+1
  352.     SortRight%=NumXPrimes%
  353.     SortT1=XPrime(1)
  354.     SortT2%=XDivisionIndex%(1)
  355.     SortT3%=YDivisionIndex%(1)
  356.     WHILE SortRight% > 1
  357.       IF SortLeft% > 1
  358.         SortLeft%=SortLeft%-1
  359.         SortT1=XPrime(SortLeft%)
  360.         SortT2%=XDivisionIndex%(SortLeft%)
  361.         SortT3%=YDivisionIndex%(SortLeft%)
  362.       ELSE
  363.         SortT1=XPrime(SortRight%)
  364.         SortT2%=XDivisionIndex%(SortRight%)
  365.         SortT3%=YDivisionIndex%(SortRight%)
  366.         XPrime(SortRight%)=XPrime(1)
  367.         XDivisionIndex%(SortRight%)=XDivisionIndex%(1)
  368.         YDivisionIndex%(SortRight%)=YDivisionIndex%(1)
  369.         SortRight%=SortRight%-1
  370.       ENDIF
  371.       IF SortRight% > 1
  372.         KeyIndex2%=SortLeft%
  373.         Finished%=0
  374.         WHILE Finished% = 0
  375.           KeyIndex1%=KeyIndex2%
  376.           KeyIndex2%=2*KeyIndex2%
  377.           IF KeyIndex2% > SortRight%
  378.             Finished%=-1
  379.           ELSE
  380.             IF KeyIndex2% <> SortRight%
  381.               IF XPrime(KeyIndex2%) > XPrime(KeyIndex2%+1)
  382.                 KeyIndex2%=KeyIndex2%+1
  383.               ENDIF
  384.             ENDIF
  385.             IF SortT1 <= XPrime(KeyIndex2%)
  386.               Finished%=-1
  387.             ELSE
  388.               XPrime(KeyIndex1%)=XPrime(KeyIndex2%)
  389.               XDivisionIndex%(KeyIndex1%)=XDivisionIndex%(KeyIndex2%)
  390.               YDivisionIndex%(KeyIndex1%)=YDivisionIndex%(KeyIndex2%)
  391.             ENDIF
  392.           ENDIF
  393.         ENDWH
  394.         XPrime(KeyIndex1%)=SortT1
  395.         XDivisionIndex%(KeyIndex1%)=SortT2%
  396.         YDivisionIndex%(KeyIndex1%)=SortT3%
  397.       ENDIF
  398.     ENDWH
  399.     XPrime(1)=SortT1
  400.     XDivisionIndex%(1)=SortT2%
  401.     YDivisionIndex%(1)=SortT3%
  402.     idPlot%=GCREATE(0,0,640,240,1,2)
  403.     REM AspectRatio=1.0/(4.0*(240.0/640.0)/3.0)
  404.     AspectRatio=1.0/(54.0*(240.0/640.0)/21.0)
  405.     YOutMax=MaxYOut%
  406.     ZOutMax=MaxZOut%
  407.     IF AspectRatio*ZOutMax*(YPrimeMax-YPrimeMin) <= YOutMax*(ZPrimeMax-ZPrimeMin)
  408.       IF AspectRatio*ZOutMax*(YPrimeMax-YPrimeMin) >= YOutMax*(ZPrimeMax-ZPrimeMin)
  409.         PixelsPerUnit=1.0
  410.         YOffset=YOutMax/2.0
  411.         ZOffset=-ZOutMax/2.0
  412.       ELSE
  413.         PixelsPerUnit=ZOutMax/(ZPrimeMax-ZPrimeMin)
  414.         YOffset=(YOutMax-AspectRatio*PixelsPerUnit*(YPrimeMax-YPrimeMin))/2.0
  415.         ZOffset=0.0
  416.       ENDIF
  417.     ELSE
  418.       PixelsPerUnit=YOutMax/(AspectRatio*(YPrimeMax-YPrimeMin))
  419.       YOffset=0.0
  420.       ZOffset=-(ZOutMax-PixelsPerUnit*(ZPrimeMax-ZPrimeMin))/2.0
  421.     ENDIF
  422.     Bias=1.0
  423.     LightestGray%=240
  424.     DarkestGray%=19
  425.     XPrimeNum%=1
  426.     WHILE XPrimeNum% <= NumXPrimes%
  427.       XDivisionNum%=XDivisionIndex%(XPrimeNum%)
  428.       IF XDivisionNum% <> NumXDivisions%
  429.         YDivisionNum%=YDivisionIndex%(XPrimeNum%)
  430.         IF YDivisionNum% <> NumYDivisions%
  431.           DivIndex%=DivisionIndex%:(XDivisionNum%,YDivisionNum%,NumXDivisions%,NumYDivisions%)
  432.           BoxX%(1)=INT(YOffset+PixelsPerUnit*AspectRatio*(YPrime(DivIndex%)-YPrimeMin))
  433.           BoxY%(1)=INT(ZOffset+ZOutMax-PixelsPerUnit*(ZPrime(DivIndex%)-ZPrimeMin))
  434.           BoxX%(2)=INT(YOffset+PixelsPerUnit*AspectRatio*(YPrime(DivIndex%+NumYDivisions%)-YPrimeMin))
  435.           BoxY%(2)=INT(ZOffset+ZOutMax-PixelsPerUnit*(ZPrime(DivIndex%+NumYDivisions%)-ZPrimeMin))
  436.           BoxX%(3)=INT(YOffset+PixelsPerUnit*AspectRatio*(YPrime(DivIndex%+NumYDivisions%+1)-YPrimeMin))
  437.           BoxY%(3)=INT(ZOffset+ZOutMax-PixelsPerUnit*(ZPrime(DivIndex%+NumYDivisions%+1)-ZPrimeMin))
  438.           BoxX%(4)=INT(YOffset+PixelsPerUnit*AspectRatio*(YPrime(DivIndex%+1)-YPrimeMin))
  439.           BoxY%(4)=INT(ZOffset+ZOutMax-PixelsPerUnit*(ZPrime(DivIndex%+1)-ZPrimeMin))
  440.           BoxYMin%=BoxY%(1)
  441.           BoxYMax%=BoxYMin%
  442.           BoxNum1%=2
  443.           WHILE BoxNum1% <= 4
  444.             IF BoxY%(BoxNum1%) < BoxYMin%
  445.               BoxYMin%=BoxY%(BoxNum1%)
  446.             ENDIF
  447.             IF BoxY%(BoxNum1%) > BoxYMax%
  448.               BoxYMax%=BoxY%(BoxNum1%)
  449.             ENDIF
  450.             BoxNum1%=BoxNum1%+1
  451.           ENDWH
  452.           ColorNum%=Color%(DivIndex%)
  453.           Fraction=FLT(ColorNum%-ColorMin%)/FLT(ColorMax%-ColorMin%)
  454.           IF Fraction > 0.0
  455.             Fraction=EXP(Bias*LN(Fraction))
  456.             ColorNum%=INT(FLT(LightestGray%-DarkestGray%)*Fraction+FLT(DarkestGray%))
  457.           ELSE
  458.             ColorNum%=DarkestGray%
  459.           ENDIF
  460.           GCOLOR ColorNum%,ColorNum%,ColorNum%
  461.           BoxY1%=BoxYMin%
  462.           WHILE BoxY1% <= BoxYMax%
  463.             InterceptCountMod2%=0
  464.             BoxNum2%=2
  465.             BoxNum1%=1
  466.             WHILE BoxNum1% <= 4
  467.               IF BoxY%(BoxNum1%) >= BoxY1%
  468.                 IF BoxY1% > BoxY%(BoxNum2%)
  469.                   BoxDeltaY=BoxY%(BoxNum2%)-BoxY%(BoxNum1%)
  470.                   BoxDeltaX=BoxX%(BoxNum2%)-BoxX%(BoxNum1%)
  471.                   BoxYOffset=BoxY1%-BoxY%(BoxNum1%)
  472.                   BoxXIntercept=BoxX%(BoxNum1%)
  473.                   BoxX1%=INT(BoxDeltaX*BoxYOffset/BoxDeltaY+BoxXIntercept)
  474.                   DrawLine:
  475.                   InterceptCountMod2%=1-InterceptCountMod2%
  476.                 ENDIF
  477.               ELSE
  478.                 IF BoxY1% <= BoxY%(BoxNum2%)
  479.                   BoxDeltaY=BoxY%(BoxNum2%)-BoxY%(BoxNum1%)
  480.                   BoxDeltaX=BoxX%(BoxNum2%)-BoxX%(BoxNum1%)
  481.                   BoxYOffset=BoxY1%-BoxY%(BoxNum1%)
  482.                   BoxXIntercept=BoxX%(BoxNum1%)
  483.                   BoxX1%=INT(BoxDeltaX*BoxYOffset/BoxDeltaY+BoxXIntercept)
  484.                   DrawLine:
  485.                   InterceptCountMod2%=1-InterceptCountMod2%
  486.                 ENDIF
  487.               ENDIF
  488.               BoxNum2%=BoxNum2%+1
  489.               IF BoxNum2% > 4
  490.                 BoxNum2%=1
  491.               ENDIF
  492.               BoxNum1%=BoxNum1%+1
  493.             ENDWH
  494.             BoxY1%=BoxY1%+1
  495.           ENDWH
  496.         ENDIF
  497.       ENDIF
  498.       XPrimeNum%=XPrimeNum%+1
  499.     ENDWH
  500.     Response$=GET$
  501.     GCLOSE idPlot%
  502.     CLS
  503.     PRINT "                             Three Dimensional Plot"
  504.     PRINT
  505.     PRINT
  506.     PRINT
  507.     PRINT "Again (y or n)? ";
  508.     Response$=GET$
  509.     PRINT
  510.   UNTIL Response$ <> "Y" AND Response$ <> "y"
  511. ENDP
  512.  
  513. PROC DrawLine:
  514.   EXTERNAL BoxX1%
  515.   EXTERNAL BoxX2%
  516.   EXTERNAL BoxY1%
  517.   EXTERNAL InterceptCountMod2%
  518.   IF InterceptCountMod2% = 0
  519.     BoxX2%=BoxX1%
  520.   ELSE
  521.     GAT BoxX1%,BoxY1%
  522.     GLINETO BoxX2%,BoxY1%
  523.     GLINEBY 0,0
  524.   ENDIF
  525. ENDP
  526.  
  527. PROC DivisionIndex%:(XDivisionNum%,YDivisionNum%,NumXDivisions%,NumYDivisions%)
  528.   RETURN NumYDivisions%*(XDivisionNum%-1)+YDivisionNum%
  529. ENDP
  530.  
  531. PROC F:(X,Y)
  532.   REM     This function plots a circular wave in three dimensions.
  533.   REM Try plotting -1 <= x <= 1 and -1 <= y <= 1 with 30 divisions
  534.   REM along each axis, a rotation of 30 degrees, and a tilt of 20
  535.   REM degrees.
  536.   LOCAL T1
  537.   LOCAL T2
  538.   T1=X*X+Y*Y
  539.   T2=COS(7.0*SQR(T1))
  540.   RETURN 2*T2*T2/(1.0+30.0*T1)
  541. ENDP
  542.  
  543.