home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / DXF2HSH.ZIP / DXF2HSH.C next >
C/C++ Source or Header  |  1994-05-16  |  10KB  |  383 lines

  1. /*----------------------------------------------------------------------
  2.  
  3.                  DXF2HSH
  4.         DXF polyline to DXF 3DFace converter
  5.              by Vance Gloster    May 1994
  6.                 based on
  7.                  DXF2TRI
  8.         DXF polyline/polygon to triangle converter
  9.              by Tim Riley   Aug 1993
  10.                 based on
  11.         POLY2TRI - a polygon to triangle converter
  12.              by Steve Anger Jan 1993
  13.  
  14. This program is commited to the public domain. Feel free to use all or part
  15. of this code in your own programs.
  16.  
  17. This is a utility that extracts polyline shapes from a DXF file and breaks
  18. them down into individual triangles. The polylines are assumed to be closed,
  19. planar (2D) polygons. This program only deals with POLYLINE entities and
  20. ignores all other entities in the DXF file. All properties (color, line type)
  21. are ignored. 
  22.  
  23. The input DXF file consists of one or more polylines with no more than 2000
  24. vertices. This limit is rather arbitrary and can be changed if necessary (by
  25. changing POLYMAX).
  26.  
  27. The program uses the following syntax:
  28.     DXF2TRI infile[.DXF] outfile[.DXF] [xy]
  29.  
  30. The output is a DXF file that uses the 3DFace objects Animation Master can read
  31. instead of polyline objects which is what most packages use.
  32.  
  33. -----------------------------------------------------------------------*/
  34.  
  35. #include <math.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39.  
  40. typedef struct {
  41.     float x, y, z;
  42. } Vector;
  43.  
  44. int remove_triangle (Vector *poly, int *polysize, Vector *v1, Vector *v2, Vector *v3);
  45. int poly_inside (Vector *poly, int polysize, Vector *v);
  46. void vect_init (Vector *v, float x, float y, float z);
  47. void vect_copy (Vector *v1, Vector *v2);
  48. void vect_add (Vector *v1, Vector *v2, Vector *v3);
  49. void vect_sub (Vector *v1, Vector *v2, Vector *v3);
  50. void vect_scale (Vector *v, float k);
  51. float vect_mag (Vector *v);
  52. float dot_prod (Vector *v1, Vector *v2);
  53. void cross_prod (Vector *v1, Vector *v2, Vector *v3);
  54. float vect_angle (Vector *v1, Vector *v2);
  55. void add_ext (char *fname, char *ext, int force);
  56. void pr_error (void);
  57. void option (char *string, int *extrude, int *back);
  58.  
  59. #define POLYMAX 2000
  60. #define M_PI    3.1415926535
  61.  
  62. int main (int argc, char *argv[])
  63. {
  64.     FILE *fp_in, *fp_out;
  65.     char infile[20] = "", outfile[20] = "", string[80];
  66.     int polysize, i, extrude = 0, back = 0, dimension_code;
  67.     float temp1, temp2;
  68.     Vector v[POLYMAX], v1, v2, v3;
  69.  
  70.     if (argc < 3) pr_error ();
  71.  
  72.     strcpy (infile, argv[1]);
  73.     strcpy (outfile, argv[2]);
  74.     add_ext (infile, "dxf", 0);
  75.     add_ext (outfile, "dxf", 0);
  76.  
  77.     if((argc > 3) && (!strcmp(argv[3], "xy") || !strcmp(argv[3], "XY")))
  78.         dimension_code = 20;
  79.     else
  80.         dimension_code = 30;
  81.     
  82.     if ((fp_in=fopen(infile,"r")) == NULL) {
  83.         printf ("Cannot open input file '%s'\n", infile);
  84.         exit (EXIT_FAILURE);
  85.     }
  86.  
  87.     if ((fp_out=fopen(outfile,"w")) == NULL) {
  88.         printf ("Cannot open output file '%s'\n", outfile);
  89.         exit (EXIT_FAILURE);
  90.     }
  91.     fprintf(fp_out, "0\nSECTION\n2\nENTITIES\n");
  92.     do {
  93.         fscanf (fp_in, "%s", &string);
  94.     } while (strcmp (string, "ENTITIES") != 0);
  95.  
  96.     while (1) {
  97.         do {
  98.             fscanf (fp_in, "%s", &string);
  99.         } while (strcmp (string, "POLYLINE") != 0 &&
  100.              strcmp (string, "ENDSEC") != 0);
  101.         if (strcmp (string, "ENDSEC") == 0) break;
  102.  
  103.         polysize = 0;
  104.         while (1) {
  105.             do{
  106.                 fscanf (fp_in, "%s", &string);
  107.             }while (strcmp (string, "VERTEX") != 0 &&
  108.                  strcmp (string, "SEQEND") != 0);
  109.             if (strcmp (string, "SEQEND") == 0) break;
  110.             do {
  111.                 fscanf (fp_in, "%f", &temp1);
  112.                 fscanf (fp_in, "%f", &temp2);
  113.             } while (temp1 != 10);
  114.             v[polysize].x = temp2;
  115.             do {
  116.                 fscanf (fp_in, "%f", &temp1);
  117.                 fscanf (fp_in, "%f", &temp2);
  118.             } while (temp1 != dimension_code);
  119.             v[polysize].y = temp2;
  120.             v[polysize++].z = (float) 0.0;
  121.                 if (polysize >= POLYMAX) {
  122.                 printf ("Too many vertices. Break up into smaller sections & try again.\n");
  123.                 fclose (fp_in);
  124.                 fclose (fp_out);
  125.                 exit (1);
  126.               }
  127.         }
  128.         /* Extrude 1 unit deep along the z axis */
  129.         /* extrusion is currently disabled */
  130.         if (extrude == 1) {
  131.             for (i=0; i<polysize; i++) {
  132.                 if (i<polysize-1) {
  133.                         fprintf (fp_out, "%f %f %f %f %f %f %f %f %f \n",
  134.                          v[i].x, v[i].y, v[i].z,
  135.                          v[i+1].x, v[i+1].y, v[i+1].z,
  136.                          v[i+1].x, v[i+1].y, v[i+1].z+1);
  137.                     fprintf (fp_out, "%f %f %f %f %f %f %f %f %f \n",
  138.                          v[i].x, v[i].y, v[i].z,
  139.                          v[i+1].x, v[i+1].y, v[i+1].z+1,
  140.                          v[i].x, v[i].y, v[i].z+1);
  141.                 }
  142.                 else {
  143.                     fprintf (fp_out, "%f %f %f %f %f %f %f %f %f \n",
  144.                          v[i].x, v[i].y, v[i].z,
  145.                          v[0].x, v[0].y, v[0].z,
  146.                          v[0].x, v[0].y, v[0].z+1);
  147.                     fprintf (fp_out, "%f %f %f %f %f %f %f %f %f \n",
  148.                          v[i].x, v[i].y, v[i].z,
  149.                          v[0].x, v[0].y, v[0].z+1,
  150.                          v[i].x, v[i].y, v[i].z+1);
  151.                 }
  152.             }
  153.         }
  154.  
  155.         /* Remove triangles from the polygon until there's nothing left */
  156.         while (remove_triangle (v, &polysize, &v1, &v2, &v3)) {
  157.             fprintf(fp_out, "0\n3DFACE\n8\n2\n10\n%f\n20\n%f\n30\n%f\n",
  158.                 v1.x, v1.y, v1.z);
  159.             fprintf(fp_out, "11\n%f\n21\n%f\n31\n%f\n12\n%f\n22\n%f\n32\n%f\n13\n%f\n23\n%f\n33\n%f\n",
  160.                 v2.x, v2.y, v2.z, v3.x, v3.y, v3.z, v3.x, v3.y, v3.z);
  161.         }
  162.     }
  163.     fprintf(fp_out, "0\nENDSEC\n0\nEOF\n");
  164.     fclose (fp_in);
  165.     fclose (fp_out);
  166.     return 0;
  167. }
  168.  
  169. void pr_error ()
  170. {
  171.     printf ("Usage: infile[.dxf] outfile[.dxf] [xy]\n\n");
  172.     exit (1);
  173. }
  174.  
  175. void option (char *string, int *extrude, int *back)
  176. {
  177.     if (string[0] != '-') pr_error();
  178.     if (string[1] == 'e' || string[1] == 'E') *extrude =1;
  179.     if (string[1] == 'b' || string[1] == 'B') *back =1;
  180. }
  181.  
  182. /* Removes a triangle from the specified polygon. */
  183. /* The size of the polygon is reduced */
  184. int remove_triangle (Vector *poly, int *polysize,
  185.              Vector *v1, Vector *v2, Vector *v3)
  186. {
  187.     Vector tri[3], center;
  188.     int    i, j, a, b, c;
  189.  
  190.     if (*polysize < 3)
  191.     return 0; /* No triangle found */
  192.  
  193.     /* This simplest case */
  194.     if (*polysize == 3) {
  195.     vect_copy (v1, &poly[0]);
  196.     vect_copy (v2, &poly[1]);
  197.     vect_copy (v3, &poly[2]);
  198.  
  199.     *polysize = 0;
  200.  
  201.     return 1;  /* Ok */
  202.     }
  203.  
  204.     for (i = 0; i < *polysize; i++) {
  205.     a = i;
  206.     b = (i + 1) % *polysize;
  207.     c = (i + 2) % *polysize;
  208.  
  209.     /* Select a candidate triangle */
  210.     vect_copy (&tri[0], &poly[a]);
  211.     vect_copy (&tri[1], &poly[b]);
  212.     vect_copy (&tri[2], &poly[c]);
  213.  
  214.     /* Calculate the center of the triangle */
  215.     vect_init (¢er, (float) 0.0, (float) 0.0, (float) 0.0);
  216.     vect_add (¢er, ¢er, &tri[0]);
  217.     vect_add (¢er, ¢er, &tri[1]);
  218.     vect_add (¢er, ¢er, &tri[2]);
  219.     vect_scale (¢er, (float) (1.0/3.0) );
  220.  
  221.     /* Is the center of the triangle inside the original polygon? */
  222.     /* If not skip this triangle */
  223.     if (!poly_inside (poly, *polysize, ¢er))
  224.         continue;
  225.  
  226.     /* Are any of the polygons other vertices inside the triangle */
  227.     /* If so skip this triangle */
  228.     for (j = 0; j < *polysize; j++) {
  229.         if (j != a && j != b && j != c && poly_inside (tri, 3, &poly[j]))
  230.         break;
  231.     }
  232.  
  233.     if (j < *polysize)
  234.         continue;
  235.  
  236.     /* This is the one */
  237.     vect_copy (v1, &tri[0]);
  238.     vect_copy (v2, &tri[1]);
  239.     vect_copy (v3, &tri[2]);
  240.  
  241.     /* Remove this triangle from the polygon */
  242.     (*polysize)--;
  243.     for (j = b; j < *polysize; j++)
  244.         vect_copy (&poly[j], &poly[j+1]);
  245.  
  246.     return 1; /* Ok */
  247.     }
  248.  
  249.     return 0; /* No triangle found */
  250. }
  251.  
  252.  
  253. /* Determines if the specified point 'v' is inside the polygon. */
  254. /* Uses a convoluted version of the sum of angles approach */
  255. int poly_inside (Vector *poly, int polysize, Vector *v)
  256. {
  257.     Vector sum, cross, v1, v2;
  258.     float  magcross;
  259.     int    i;
  260.  
  261.     vect_init (&sum, (float) 0.0, (float) 0.0, (float) 0.0);
  262.  
  263.     for (i = 0; i < polysize; i++) {
  264.     vect_sub (&v1, v, &poly[i]);
  265.     vect_sub (&v2, v, &poly[(i+1) % polysize]);
  266.  
  267.     cross_prod (&cross, &v1, &v2);
  268.     magcross = vect_mag (&cross);
  269.  
  270.     if (magcross > 0.0)
  271.         vect_scale (&cross, (float) 1.0/magcross);
  272.  
  273.     vect_scale (&cross, vect_angle (&v1, &v2));
  274.     vect_add (&sum, &sum, &cross);
  275.     }
  276.  
  277.     return (vect_mag (&sum) > M_PI);
  278. }
  279.  
  280.  
  281. void vect_init (Vector *v, float  x, float  y, float  z)
  282. {
  283.     v->x = x;
  284.     v->y = y;
  285.     v->z = z;
  286. }
  287.  
  288.  
  289. void vect_copy (Vector *v1, Vector *v2)
  290. {
  291.     v1->x = v2->x;
  292.     v1->y = v2->y;
  293.     v1->z = v2->z;
  294. }
  295.  
  296.  
  297. void vect_add (Vector *v1, Vector *v2, Vector *v3)
  298. {
  299.     v1->x = v2->x + v3->x;
  300.     v1->y = v2->y + v3->y;
  301.     v1->z = v2->z + v3->z;
  302. }
  303.  
  304.  
  305. void vect_sub (Vector *v1, Vector *v2, Vector *v3)
  306. {
  307.     v1->x = v2->x - v3->x;
  308.     v1->y = v2->y - v3->y;
  309.     v1->z = v2->z - v3->z;
  310. }
  311.  
  312.  
  313. void vect_scale (Vector *v, float  k)
  314. {
  315.     v->x = k * v->x;
  316.     v->y = k * v->y;
  317.     v->z = k * v->z;
  318. }
  319.  
  320.  
  321. float vect_mag (Vector *v)
  322. {
  323.     float mag;
  324.     if (v->x==0.0 && v->y==0.0 && v->z==0.0) return (float) 0.0;
  325.     mag = (float) sqrt(v->x*v->x + v->y*v->y + v->z*v->z);
  326.  
  327.     return mag;
  328. }
  329.  
  330.  
  331. float dot_prod (Vector *v1, Vector *v2)
  332. {
  333.     return (v1->x*v2->x + v1->y*v2->y + v1->z*v2->z);
  334. }
  335.  
  336.  
  337. void cross_prod (Vector *v1, Vector *v2, Vector *v3)
  338. {
  339.     v1->x = (v2->y * v3->z) - (v2->z * v3->y);
  340.     v1->y = (v2->z * v3->x) - (v2->x * v3->z);
  341.     v1->z = (v2->x * v3->y) - (v2->y * v3->x);
  342. }
  343.  
  344.  
  345. /* Return the angle (rads) between two vectors */
  346. float vect_angle (Vector *v1, Vector *v2)
  347. {
  348.     float  mag1, mag2, angle, cos_theta;
  349.  
  350.     mag1 = vect_mag(v1);
  351.     mag2 = vect_mag(v2);
  352.  
  353.     if (mag1 * mag2 == 0.0)
  354.     angle = (float) 0.0;
  355.     else {
  356.     cos_theta = dot_prod(v1,v2) / (mag1 * mag2);
  357.  
  358.     if (cos_theta <= -1.0)
  359.         angle = (float) M_PI;
  360.     else if (cos_theta >= +1.0)
  361.         angle = (float) 0.0;
  362.     else
  363.         angle = (float) acos(cos_theta);
  364.     }
  365.  
  366.     return angle;
  367. }
  368.  
  369. void add_ext (char *fname, char *ext, int force)
  370. {
  371.     int i;
  372.  
  373.     for (i = 0; i < (int) strlen (fname); i++)
  374.     if (fname[i] == '.') break;
  375.  
  376.     if (fname[i] == '\0' || force) {
  377.     if (strlen (ext) > 0)
  378.         fname[i++] = '.';
  379.  
  380.     strcpy (&fname[i], ext);
  381.     }
  382. }
  383.