home *** CD-ROM | disk | FTP | other *** search
/ DTP Toolbox / DTPToolbox.iso / utilities / propage_pdraw / donsgenies / prodrawgenies.lha / GEO.Export.pdrx < prev    next >
Encoding:
Text File  |  1994-08-30  |  12.6 KB  |  375 lines

  1. /*
  2. Routine to export ASCII GEO files as per Videoscape for loading into Modeller 3D. Polygons may need to be flipped (or their surfaces made double-sided) before being used in Lightwave, and holes in letters  will have to be cut out by transferring the hole polygons to a background layer and using the drill tunnel function (for 2D objects) or Boolean subtract (for 3D).
  3. Open-ended curves will be closed by Modeller.
  4. Written by Don Cox, August 94, derived from my ISHAPEexport. Copyright. Not Public Domain.
  5. */
  6.  
  7. /* $VER: GEO.Export Aug 94 */
  8.  
  9. /*call open("STDERR","ram:trace","W")
  10. trace r*/
  11.  
  12. msg = PDSetup.rexx(2,0) /* load gdarexxsupport.library */
  13. units = getclip(pds_units)
  14. if msg ~= 1 then exit_msg(msg)
  15. call pdm_SetWireFrame(1)
  16. call pdm_SetUnits(1) /* inches - for easy conversion of point sizes */
  17. numeric digits 5
  18.  
  19.  
  20. /* rexxmathlib.library is needed to work around the square root bug in gdarexxsupport.library  */
  21. if ~show("l", "rexxmathlib.library") then
  22.     if ~addlib("rexxmathlib.library", 0, -30,0) then do
  23.         call ppm_Inform(1,"Please install the rexxmathlib.library in your libs: directory before running this Genie.")
  24.     end
  25.  
  26.  
  27. cr = '0a'x
  28.  
  29. shapefile = pdm_GetFilename("Select file for saving", "3D:Objects")
  30. if shapefile = "" then exit_msg("No file selected")
  31.  
  32. call pdm_ShowStatus("  Analysing objects...")
  33. success = open("Output2",shapefile,"W")
  34. if success = 0 then exit_msg("File "shapefile" could not be opened")
  35. success = open("Output","ram:tempfile","W")
  36. if success = 0 then exit_msg("Temporary file could not be opened")
  37.  
  38. pos1 = lastpos("/",shapefile)
  39. if pos1 = 0 then pos1 = lastpos(":",shapefile)
  40. fileonly = substr(shapefile,pos1+1)
  41.  
  42. string = "3DG1"||cr
  43.  
  44. /* First go through getting rough size, for setting point intervals for curve conversion */
  45. object = pdm_SelFirstObj()
  46. objectnumber = 1
  47. totalpoints = 0
  48. psize = pdm_GetPageSize()
  49. pagewidth = word(psize,1)
  50. pageheight = word(psize,2)
  51.  
  52. if object = 0 then exit_msg("No objects selected")
  53. do until object = 0
  54.     if pdm_IsEllipse(object) = 1 then call pdm_EllipseToGraphic(object)
  55. /*    if pdm_IsText(object) = 1 then do
  56.         textobject = pdm_SelectObj(object)
  57.         call pdm_TextToGraphic()
  58.         end*/
  59. /* Text-to-Bezier seems to be unnecessary, but ellipse-to-Bezier is necessary */
  60.     if pdm_IsBezier(object)=1 then do
  61.         numpoints = pdm_GetObjOrder(object)
  62.         totalpoints = totalpoints+numpoints
  63.         VisSize = pdm_GetObjVisSize(object)
  64.         VisPos = pdm_GetObjVisPosn(object)
  65.         parse var VisSize VisWidth VisHeight
  66.         width.objectnumber = VisWidth/pagewidth
  67.         height.objectnumber = VisHeight/pagewidth /* both ref to width to keep proportions */
  68.         parse var VisPos Xcoord Ycoord
  69.         Xpos.objectnumber = Xcoord/pagewidth
  70.         Ypos.objectnumber = (pageheight-Ycoord)/pagewidth
  71.         if objectnumber = 1 then do
  72.             smallestY = Ycoord /* pick up first Y value in file */
  73.             smallestX = Xcoord
  74.             biggestX = Xcoord
  75.             biggestY = Ycoord
  76.             end
  77.         if Ycoord>biggestY then biggestY = Ycoord
  78.         if Ycoord<smallestY then smallestY = Ycoord
  79.         if Xcoord>biggestX then biggestX = Xcoord
  80.         if Xcoord<smallestX then smallestX = Xcoord
  81.  
  82.         Ycoord = Ycoord+VisHeight /* Look at bottom right corner */
  83.         Xcoord = Xcoord+VisWidth
  84.         if Ycoord>biggestY then biggestY = Ycoord
  85.         if Ycoord<smallestY then smallestY = Ycoord
  86.         if Xcoord>biggestX then biggestX = Xcoord
  87.         if Xcoord<smallestX then smallestX = Xcoord
  88.  
  89.         end
  90.  
  91.  
  92.     object = pdm_SelNextObj(object)
  93.     objectnumber = objectnumber+1
  94.     end
  95.  
  96. if objectnumber = 1 then exit_msg("No objects selected")
  97. totalobjects = objectnumber-1
  98. string = string||totalpoints||cr
  99.  
  100. /* The sqrt function in the gdarexxsupport.library doesn't work, so remove it. */
  101. removed = remlib("gdarexxsupport.library")
  102. if removed~=1 then call ppm_Inform(1,"Could not remove gdarexxsupport.library - curves may be faulty","Resume")
  103. totalpoints2 = trunc(sqrt(totalpoints)*12) /* arbitrary formula for suggested number*/
  104.  
  105.  
  106. if totalpoints2>300 then totalpoints2=300 /* arbitrary limits */
  107. if totalpoints2<20 then totalpoints2=20
  108.  
  109. /* The curve resolution is the approximate number of points across the width of the objects - the higher the number, the finer the detail */
  110.  
  111. outheight = getclip(pdusoutheight)
  112. if outheight = "" then outheight = 1
  113.  
  114. thickness = getclip(pdusthickness)
  115. if thickness = "" then thickness = 0.2
  116.  
  117. form = "Resolution number :"totalpoints2 ||cr|| "Object Height (m):"outheight ||cr|| "Thickness (m):"thickness ||cr|| "Multicolor?(Y/N) :N"
  118.  
  119. form = pdm_GetForm("Set curve point resolution", 10,form)
  120. parse var form resolution "0a"x outheight "0a"x thickness "0a"x multicolor
  121. if ~datatype(resolution,n) then resolution = 60
  122. if upper(multicolor)~="Y" then multicolor="N" /* different surface for each polygon */
  123. if ~datatype(outheight,n) then outheight = 1
  124. call setclip(pdusoutheight,outheight)
  125. if ~datatype(thickness,n) then thickness = outheight/5
  126. thickness = abs(thickness)
  127. call setclip(pdusthickness,thickness)
  128. color=15 /* white */
  129. backcolor = 14 /* yellow */
  130. sidecolor = 13 /* light purple */
  131.  
  132. /* This time, convert curves and get accurate size */
  133. totalsize = (biggestX-smallestX)+(biggestY-smallestY)
  134. oldControl2X = 0
  135. oldControl2Y = 0
  136. oldXcoord = 0
  137. oldYcoord = 0
  138.  
  139. object = pdm_SelFirstObj()
  140. objectnumber = 1
  141. gridflag = 0 /* grid as lines or dots requester flag  */
  142.  
  143.  
  144. do until object = 0
  145.     objects.objectnumber = object
  146.     if pdm_IsBezier(object)=1 then do
  147.         closed = pdm_IsClosed(object) /* Closed objects have an extra point at start=end. Function returns 1 if closed.*/
  148.         numpoints = pdm_GetObjOrder(object)
  149.         point0info = ""
  150.         objects.objectnumber.objorder = numpoints
  151.  
  152.         do pointnumber = 0 to (numpoints-1) /* point numbering starts at 0 */
  153.             pointinfo = pdm_GetPoint(object, pointnumber)
  154.             parse var pointinfo Xcoord Ycoord control1X control1Y control2X control2Y
  155.             pointinfo = Xcoord" "Ycoord  /* default for straight lines */
  156.             /* Check for coincident points - common in type */
  157.  
  158.             if pointinfo=point0info then do
  159.                 totalpoints=totalpoints-1
  160.                 pointinfo = ""
  161.                 objects.objectnumber.objorder = objects.objectnumber.objorder-1
  162.                 end
  163.             if pointnumber=0 then point0info=pointinfo
  164.  
  165.             /* See if it's a curved line and add points if so */
  166.             XNS=0
  167.             if ((control1X~=0 | control1Y~=0 | oldControl2X~=0 | oldControl2Y~=0) & pointnumber ~=0 & resolution~=0) then XNS = Bezier2()
  168.             objects.objectnumber.objorder = objects.objectnumber.objorder + XNS /* add in new points */
  169.             totalpoints = totalpoints+XNS
  170.             oldControl2X = control2X
  171.             oldControl2Y = control2Y
  172.             oldXcoord = Xcoord
  173.             oldYcoord = Ycoord
  174.             string = string||pointinfo||cr
  175.             if length(string)>20000 then do
  176.                 call writech("Output",string) /* Output is temp file */
  177.                 string = ""
  178.                 end
  179.             end
  180.         end
  181.  
  182.     object = pdm_SelNextObj(object)
  183.     objectnumber = objectnumber+1
  184.  
  185.     end
  186.  
  187.  
  188. call writech("Output",string)
  189. call finalize
  190.  
  191. exit_msg("Finished")
  192.  
  193. /* +++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++ */
  194.  
  195. exit_msg()
  196.  
  197. exit_msg: procedure expose units
  198. do
  199.     parse arg message
  200.  
  201.     if message ~= '' then call pdm_Inform(1,message,)
  202.     call pdm_ClearStatus()
  203.     call pdm_SetUnits(units)
  204.     call pdm_AutoUpdate(1)
  205.     exit
  206. end
  207.  
  208.  
  209. /* ++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++ */
  210.  
  211. Bezier2:
  212. /* Bezier2.SUB              
  213. From Fundamentals of Interactive Computer Graphics
  214. From article by Steve Enns in Byte, Dec. '86
  215. (2D version only)
  216.  
  217. Calculates cubic parametric freeform Bezier curves
  218.  
  219. XC.,YC. are the coords of the 4 hull points, which are the current and previous points and their inner control points. */
  220.  
  221. XC.1 = oldXcoord
  222. XC.2 = oldControl2X+oldXcoord /* control handle coords are relative */
  223. XC.3 = control1X+Xcoord
  224. XC.4 = Xcoord
  225. YC.1 = oldYcoord
  226. YC.2 = oldControl2Y+oldYcoord
  227. YC.3 = control1Y+Ycoord
  228. YC.4 = Ycoord
  229. curvesize = abs(Xcoord-oldXcoord)+abs(Ycoord-oldYcoord)
  230. curveratio = curvesize/totalsize
  231. increment = 1/(resolution * curveratio)
  232. if increment>0.5 then increment = 0.5 /* just put 1 in the middle */
  233.  
  234. /* Returns CurveXcoord. and CurveYcoord. as the points
  235. Returns XNS as the number of added curve points
  236. */
  237.  
  238. IS=1
  239. Bezpointinfo = ""
  240.  
  241. do T=increment to 0.98 by increment /* 0.98 so as not to do a point right at the end of the curve, too close to first point of next curve */
  242.     T2=T*T
  243.     T3=T2*T
  244.     NC1=1-3*T+3*T2-T3
  245.     NC2=3*T3-6*T2+3*T
  246.     NC3=3*T2-3*T3
  247.     NC4=T3
  248.     CurveXcoord=(NC1*XC.1)+(NC2*XC.2)+(NC3*XC.3)+(NC4*XC.4)
  249.     CurveYcoord=(NC1*YC.1)+(NC2*YC.2)+(NC3*YC.3)+(NC4*YC.4)
  250.     Bezpointinfo = Bezpointinfo||CurveXcoord" "CurveYcoord||cr
  251.     IS=IS+1
  252.     end
  253.  
  254. pointinfo = Bezpointinfo || pointinfo
  255. XNS = IS-1 /* number of points */
  256.  
  257. RETURN XNS
  258.  
  259. /* +++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++ */
  260.  
  261. gridexpand:  /* do the other points of a grid */
  262.  
  263. return
  264.  
  265. /* ++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++ */
  266.  
  267. finalize:  /* Normalize and invert Y values, save to output file. */
  268.  
  269. call pdm_ShowStatus("  Constructing .GEO file...")
  270. call seek("Output",0,"B") /* Read from temp file */
  271. outstring = ""
  272. Yrange = abs(biggestY-smallestY)
  273. Yrange2 = Yrange/2 /* for centring */
  274. scale = outheight/Yrange /* single scale for X and Y */
  275. Xrange = abs(biggestX-smallestX)
  276. Xrange2 = Xrange/2
  277. thickness2 = thickness/2
  278.  
  279. if thickness~=0 then totalpoints=totalpoints*2 /* make back faces */
  280.  
  281. do until eof("Output")
  282.     do forever until eof("Output")
  283.         numbers = readln("Output")
  284.         if numbers~="" then break
  285.         end
  286.  
  287.     parse var numbers Xnumber Ynumber
  288.     if Xnumber = "3DG1" then do
  289.         numbers = readln("Output") /* second line is number of points - update it */
  290.         outstring = Xnumber||cr||totalpoints||cr
  291.         numbers = readln("Output") /* get some actual numbers */
  292.         parse var numbers Xnumber Ynumber
  293.         end
  294.  
  295.     if datatype(Xnumber,n) & datatype(Ynumber,n) then do
  296.         Ynumber = Ynumber-smallestY  /* put baseline at zero */
  297.         Ynumber = Yrange-Ynumber  /* and invert */
  298.         Ynumber = (Ynumber-Yrange2)*scale /* scale & centre */
  299.         Xnumber = Xnumber - smallestX /* also set left side to zero */
  300.         Xnumber = (Xnumber-Xrange2)*scale
  301.         numbers = Xnumber" "Ynumber
  302.         end
  303.  
  304.     if numbers = "" then break
  305.     outstring = outstring||numbers||" "||(0-thickness2)||cr
  306.     if thickness~=0 then outstring = outstring||numbers||" "thickness2||cr
  307.     if length(outstring)>20000 then do
  308.         call writech("Output2",outstring)
  309.         outstring = ""
  310.         end
  311.     end
  312.  
  313.  
  314. frontpoint = 0
  315. backpoint = 1 /* counter for back faces */
  316. increm = 1
  317. if thickness ~=0 then increm = 2
  318. line2 = ""
  319.  
  320.  
  321. do i=1 to totalobjects /* list polygons and their points */
  322.     numpoints = objects.i.objorder
  323.     pointlist = ""
  324.     lastpoint = frontpoint+(numpoints*increm)
  325.     do k=frontpoint to lastpoint-1 by increm
  326.         pointlist = pointlist||k" "
  327.         end
  328.     sidepoint = frontpoint /* counter for sides */
  329.     frontpoint = lastpoint
  330.  
  331.     pointlist2 = "" /* back polys */
  332.     if thickness~=0 then do
  333.         do k=backpoint to lastpoint-1 by 2
  334.             pointlist2 = k" "||pointlist2 /* note reverse order */
  335.             end
  336.         backpoint = lastpoint+1
  337.         end
  338.  
  339.     if multicolor = "Y" then color = (i//144)-1 /* GEO allows 144 colors */
  340.     line1 = numpoints" "pointlist||color||cr
  341.     if thickness~=0 then line2 = numpoints" "pointlist2||backcolor ||cr
  342.     outstring = outstring|| line1 || line2 
  343.  
  344.     if length(outstring)>20000 then do
  345.          call writech("Output2",outstring)
  346.          outstring = ""
  347.          end
  348.  
  349.     if thickness~=0 then do k= 0 to numpoints-1
  350.         /* points for side polys, sets of 4. 0132 gives the anti-clockwise order, sidepoint is the starting poiint for this object, and 2*k increments you around the front (even-numbered) point-pairs. */
  351.         sidepoints.1 = 0+(2*k)+sidepoint
  352.         sidepoints.2 = 1+(2*k)+sidepoint
  353.         sidepoints.3 = 3+(2*k)+sidepoint
  354.         sidepoints.4 = 2+(2*k)+sidepoint
  355.         if sidepoints.3>lastpoint then sidepoints.3 = sidepoint+1 /* back to start */
  356.         if sidepoints.4>(lastpoint-1) then sidepoints.4 = sidepoint
  357.         sideline = 4|| " "sidepoints.1" "sidepoints.2" "sidepoints.3" "sidepoints.4" "sidecolor||cr
  358.         outstring = outstring||sideline
  359.         if length(outstring)>20000 then do
  360.              call writech("Output2",outstring)
  361.              outstring = ""
  362.              end
  363.         end
  364.  
  365.     end
  366. call writech("Output2",outstring)
  367.  
  368. call close("Output2")
  369. call close("Output")
  370. address command
  371. 'delete "ram:tempfile" quiet'
  372. return
  373.  
  374.  
  375.