home *** CD-ROM | disk | FTP | other *** search
/ Late Night VRML 2.0 with Java CD-ROM / code.zip / Ch15 / NURBS / ControlNet.java < prev    next >
Encoding:
Java Source  |  1997-01-29  |  10.4 KB  |  314 lines

  1. /*
  2.  * Copyright (c) 1997 ORC Incorporated.  All Rights Reserved.
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software
  5.  * and its documentation for NON-COMMERCIAL purposes and without
  6.  * fee is hereby granted provided that this copyright notice
  7.  * appears in all copies. Please contact <info@ocnus.com> for
  8.  * further information regarding copyright and licensing.
  9.  * This code is provided without warranty, either expressed or implied.
  10.  */
  11. /* 
  12.  * Portions of this code appear in the book
  13.  * "Late Night VRML 2.0 with Java", Ziff-Davis Press, 1997
  14.  *
  15.  * ControlNet.java
  16.  *
  17.  * author   Timothy F. Rohaly
  18.  * version  1.0, 01/15/97
  19.  */
  20.  
  21. package nurbs;
  22.  
  23.  
  24. /**
  25.  * Representation of a network of control points for a
  26.  * NURBS curve or surface.
  27.  * @author   Timothy F. Rohaly
  28.  * @version  1.0, 1/15/97
  29.  */
  30. public class ControlNet implements Cloneable {
  31.  
  32.     protected int        numUControlPoints;
  33.     protected int        numVControlPoints;
  34.     protected Point4[][] controlPoints;
  35.  
  36.  
  37.     /* 
  38.      * Private constructor defined so that super.clone() will
  39.      * be able to copy member variables.
  40.      */
  41.     private ControlNet() {
  42.     }
  43.  
  44.  
  45.     /**
  46.      * Constructs a ControlNet from the specified Point4 array.
  47.      * @param numUControlPoints the number of control points in the U
  48.      *        direction
  49.      * @param numVControlPoints the number of control points in the V
  50.      *        direction
  51.      * @param controlPoints the array of Point4 control points
  52.      */
  53.     public ControlNet(int numUControlPoints, int numVControlPoints,
  54.                       Point4[][] controlPoints) {
  55.         this.numUControlPoints = numUControlPoints;
  56.         this.numVControlPoints = numVControlPoints;
  57.         this.controlPoints = controlPoints;
  58.     }
  59.  
  60.  
  61.     /**
  62.      * Constructs a ControlNet with the specified U, V dimensions.
  63.      * @param numUControlPoints the number of control points in the U
  64.      *        direction
  65.      * @param numVControlPoints the number of control points in the V
  66.      *        direction
  67.      */
  68.     public ControlNet(int numUControlPoints, int numVControlPoints) {
  69.         this(numUControlPoints, numVControlPoints,
  70.              new Point4[numUControlPoints][numVControlPoints]);
  71.     }
  72.  
  73.  
  74.     /**
  75.      * Transpose the control points by swapping U and V.
  76.      */
  77.     public void transpose() {
  78.         Point4[][] newPoints = new Point4[numVControlPoints][numUControlPoints];
  79.         for (int i=0; i<numUControlPoints; i++) {
  80.             for (int j=0; j<numVControlPoints; j++) {
  81.                 newPoints[j][i] = controlPoints[i][j];
  82.             }
  83.         }
  84.         controlPoints = newPoints;
  85.         int itemp = numUControlPoints;
  86.         numUControlPoints = numVControlPoints;
  87.         numVControlPoints = itemp;
  88.     }
  89.  
  90.  
  91.     /**
  92.      * Scale the control points.
  93.      * @param scale the scale
  94.      */
  95.     public void scale(float scale) {
  96.         for (int i=0; i<numUControlPoints; i++) {
  97.             for (int j=0; j<numVControlPoints; j++) {
  98.                 controlPoints[i][j].scale(scale);
  99.             }
  100.         }
  101.     }
  102.  
  103.  
  104.     /**
  105.      * Scale the control points.
  106.      * @param scale the scale
  107.      */
  108.     public void scale(float xscale, float yscale, float zscale) {
  109.         for (int i=0; i<numUControlPoints; i++) {
  110.             for (int j=0; j<numVControlPoints; j++) {
  111.                 controlPoints[i][j].scale(xscale, yscale, zscale);
  112.             }
  113.         }
  114.     }
  115.  
  116.  
  117.     /**
  118.      * Translate the control points.
  119.      * @param x the translation in x
  120.      * @param y the translation in y
  121.      * @param z the translation in z
  122.      */
  123.     public void translate(float x, float y, float z) {
  124.         for (int i=0; i<numUControlPoints; i++) {
  125.             for (int j=0; j<numVControlPoints; j++) {
  126.                 controlPoints[i][j].translate(x, y, z);
  127.             }
  128.         }
  129.     }
  130.  
  131.  
  132.     /**
  133.      * Rotate the control points.
  134.      * @param x the x component of the rotation axis
  135.      * @param y the y component of the rotation axis
  136.      * @param z the z component of the rotation axis
  137.      * @param theta the rotation in radians
  138.      */
  139.     public void rotate(float x, float y, float z, float theta) {
  140.         for (int i=0; i<numUControlPoints; i++) {
  141.             for (int j=0; j<numVControlPoints; j++) {
  142.                 controlPoints[i][j].rotate(x, y, z, theta);
  143.             }
  144.         }
  145.     }
  146.  
  147.  
  148.     /**
  149.      * Performs a deep copy of this ControlNet.
  150.      */
  151.     public Object clone() {
  152.         try {
  153.             ControlNet newnet = (ControlNet) super.clone();
  154.             System.arraycopy(controlPoints, 0, newnet.controlPoints, 0,
  155.                              numUControlPoints*numVControlPoints);
  156.             return newnet;
  157.         }
  158.         catch (CloneNotSupportedException e) {
  159.             String errorString = getClass().getName() + ":  " +
  160.                                  "CloneNotSupportedException " +
  161.                                  "for a Cloneable class";
  162.             throw new InternalError(errorString);  // this should never happen
  163.         }
  164.     }
  165.  
  166.  
  167.     /**
  168.      * Creates a String representation for the ControlNet
  169.      * in the form of a VRML IndexedFaceSet node.
  170.      * @return a string representation of the ControlNet
  171.      */
  172.     public String toVRMLString() {
  173.         StringBuffer buffer = new StringBuffer(256);
  174.         if (numVControlPoints >1)
  175.             buffer.append("IndexedFaceSet {\n");
  176.         else
  177.             buffer.append("IndexedLineSet {\n");
  178.         buffer.append("coord Coordinate {\n\tpoint[\n");
  179.         //
  180.         // Really, really need to sort through controlPoint
  181.         // list here and eliminate duplicate points.  Otherwise
  182.         // automatic normal generation gets screwed up.
  183.         //
  184.         for (int i=0; i<numUControlPoints; i++) {
  185.             for (int j=0; j<numVControlPoints; j++) {
  186.                 buffer.append("\t\t" +
  187.                                controlPoints[i][j].x/controlPoints[i][j].w +
  188.                                " " +
  189.                                controlPoints[i][j].y/controlPoints[i][j].w +
  190.                                " " +
  191.                                controlPoints[i][j].z/controlPoints[i][j].w +
  192.                                ",\n");
  193.             }
  194.         }
  195.         buffer.append("\t]\n}\n");
  196.         buffer.append("\tcoordIndex [\n");
  197.         for (int j=0; j<numUControlPoints-1; j++) {
  198.             if (numVControlPoints >1) {
  199.                 for (int i=0; i<numVControlPoints-1; i++) {
  200.                     int index = i + j*numVControlPoints;
  201.                     buffer.append("" + index                       + ", "     +
  202.                                        (index+1)                   + ", "     +
  203.                                        (index+numVControlPoints)   + ", -1, " + 
  204.                                        (index+numVControlPoints)   + ", "     + 
  205.                                        (index+1)                   + ", "     +
  206.                                        (index+1+numVControlPoints) + ", -1,\n" );
  207.                 }
  208.             }
  209.             else {
  210.                     buffer.append("" + j + ", ");
  211.             }
  212.         }
  213.         if (numVControlPoints >1) {
  214.             buffer.append("\t]\n");
  215.             buffer.append("    solid       FALSE\n");
  216.             buffer.append("    ccw         TRUE\n");
  217.             buffer.append("    convex      TRUE\n");
  218.             buffer.append("    creaseAngle 0.5\n");
  219.         }
  220.         else {
  221.             buffer.append("" + (numUControlPoints-1) + ", -1, ]\n");
  222.         }
  223.         buffer.append("}");
  224.  
  225.         return buffer.toString();
  226.     }
  227.  
  228.  
  229.     /**
  230.      * Creates a String representation for the ControlNet
  231.      * in the form of a VRML IndexedFaceSet node.
  232.      * @return a string representation of the ControlNet
  233.      */
  234.     public int[] toVRMLCoordIndex() {
  235.         int[] indices = null;
  236.         if (numVControlPoints > 1) {
  237.             indices  = new int[8*(numUControlPoints-1)*(numVControlPoints-1)];
  238.         }
  239.         else {
  240.             indices  = new int[numUControlPoints*numVControlPoints+1];
  241.         }
  242.         int   position = 0;
  243.         for (int j=0; j<numUControlPoints-1; j++) {
  244.             if (numVControlPoints >1) {
  245.                 for (int i=0; i<numVControlPoints-1; i++) {
  246.                     int index = i + j*numVControlPoints;
  247.                     indices[position++] = index;
  248.                     indices[position++] = index+1;
  249.                     indices[position++] = index+numVControlPoints;
  250.                     indices[position++] = -1;
  251.                     indices[position++] = index+numVControlPoints;
  252.                     indices[position++] = index+1;
  253.                     indices[position++] = index+1+numVControlPoints;
  254.                     indices[position++] = -1;
  255.                 }
  256.             }
  257.             else {
  258.                 indices[j] = j;
  259.             }
  260.         }
  261.         if (numVControlPoints >1) {
  262.             // Do nothing
  263.         }
  264.         else {
  265.             indices[indices.length-2] = numUControlPoints-1;
  266.             indices[indices.length-1] = -1;
  267.         }
  268.         return indices;
  269.     }
  270.  
  271.  
  272.     /**
  273.      * Creates a String representation for the ControlNet
  274.      * in the form of a VRML IndexedFaceSet node.
  275.      * @return a string representation of the ControlNet
  276.      */
  277.     public String toVRMLCoordinateNode() {
  278.         StringBuffer buffer = new StringBuffer(256);
  279.         buffer.append("Coordinate {\n\tpoint[\n");
  280.         for (int i=0; i<numUControlPoints; i++) {
  281.             for (int j=0; j<numVControlPoints; j++) {
  282.                 buffer.append("\t\t" +
  283.                               controlPoints[i][j].x/controlPoints[i][j].w +
  284.                               " " +
  285.                               controlPoints[i][j].y/controlPoints[i][j].w +
  286.                               " " +
  287.                               controlPoints[i][j].z/controlPoints[i][j].w +
  288.                               ",\n");
  289.             }
  290.         }
  291.         buffer.append("\t]\n}\n");
  292.         return buffer.toString();
  293.     }
  294.  
  295.  
  296.     /**
  297.      * Creates a String representation for the ControlNet
  298.      * @return a string representation of the ControlNet
  299.      */
  300.     public String toString() {
  301.         StringBuffer buffer = new StringBuffer(1024);
  302.         buffer.append(getClass().getName() + ": ");
  303.         buffer.append("numUControlPoints=" + numUControlPoints + ", " +
  304.                       "numVControlPoints=" + numVControlPoints);
  305.         for (int j=0; j<numVControlPoints; j++) {
  306.             for (int i=0; i<numUControlPoints; i++) {
  307.                 buffer.append("\n[" + i + "][" + j + "]=" +
  308.                               controlPoints[i][j].toString());
  309.             }
  310.         }
  311.         return buffer.toString();
  312.     }
  313. }
  314.