001/* 002 * Entity112_ParSplineCurve -- An entity representing a Parametric Spline Curve Entity. 003 * 004 * Copyright (C) 2013-2016, Joseph A. Huwaldt. 005 * All rights reserved. 006 * 007 * part library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * part library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public License 018 * along with part program; if not, write to the Free Software 019 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 020 * Or visit: http://www.gnu.org/licenses/lgpl.html 021 */ 022package geomss.geom.reader.iges; 023 024import geomss.geom.GeomElement; 025import geomss.geom.Transformable; 026import geomss.geom.nurbs.BasicNurbsCurve; 027import geomss.geom.nurbs.ControlPoint; 028import geomss.geom.nurbs.KnotVector; 029import geomss.geom.nurbs.NurbsCurve; 030import java.io.IOException; 031import java.io.RandomAccessFile; 032import java.text.MessageFormat; 033import java.util.ArrayList; 034import java.util.List; 035import javax.measure.unit.Unit; 036import org.jscience.mathematics.vector.Float64Matrix; 037 038/** 039 * <b><i>PARAMETRIC SPLINE CURVE ENTITY</i></b> - This entity represents a Parametric 040 * Spline Curve that may be isolated or used as a component of a Composite Curve Entity or 041 * a Subfigure Entity. The parametric spline curve is a sequence of parametric polynomial 042 * segments. 043 * 044 * <p> 045 * This entity, when read from an IGES file, is converted to a NURBS curve. This entity 046 * type can not be written out to an IGES file. The spline parameters are stored in the 047 * user data with the prefix "IGES_112_" followed by the parameter name. 048 * </p> 049 * 050 * <p> Modified by: Joseph A. Huwaldt </p> 051 * 052 * @author Joseph A. Huwaldt, Date: March 9, 2013 053 * @version September 13, 2016 054 */ 055public class Entity112_ParSplineCurve extends GeomSSEntity { 056 057 private int ctype = 3; // 1=linear, 2=quadratic, 3=cubic, 4=Wilson-Fowler, 5=Modified Wilson-Fowler, 6=B-spline 058 private int H = 1; // Degree of continuity with respect to arc length 059 private int NDIM = 3; // Number of dimemsions (2=planar, 3=non-planar) 060 private int N = 1; // Number of segments 061 private double[] T = null; // Break points of piecewise polynomial 062 private double[][] A = null; // Polynomial in each direction for each segment 063 private double[][] B = null; 064 private double[][] C = null; 065 private double[][] D = null; 066 private double TP[][] = null; 067 068 private static final double[][] Bmat 069 = {{1., 0., 0., 0.}, 070 {1., 1. / 3., 0., 0.}, 071 {1., 2. / 3., 1. / 3., 0.}, 072 {1., 1., 1., 1.}}; 073 private static final Float64Matrix Bm = Float64Matrix.valueOf(Bmat); 074 075 private NurbsCurve curve; // The GeomSS curve this entity represents. 076 077 /** 078 * Default constructor. 079 * 080 * @param p part to which this entity is contained 081 * @param de Directory Entry for this entity 082 */ 083 public Entity112_ParSplineCurve(Part p, DirEntry de) { 084 super(p, de); 085 086 if (Constants.DEBUG) { 087 System.out.println("Entity112 constructor called"); 088 } 089 090 } 091 092 /** 093 * Checks to see if the entity is correct. The following restrictions are imposed: 094 * 095 * - The Label Display Pointer shall be 0 096 */ 097 @Override 098 public void check() { 099 DirEntry DE = getDirectoryEntry(); 100 101 // DE LblDsp shall be 0 102 if (DE.getLblDsp() != 0) { 103 String msg = MessageFormat.format(RESOURCES.getString("labelDisplay"), DE.getLblDsp()); 104 addErrorMessage(getWarningString(msg)); 105 } 106 107 } 108 109 /** 110 * Read the Parameter Data from the String read in by the superclass. 111 * 112 * @param in input file 113 * @throws java.io.IOException 114 */ 115 @Override 116 public void read(RandomAccessFile in) throws IOException { 117 118 if (Constants.DEBUG) { 119 System.out.println("Entity112.read() called"); 120 } 121 122 super.read(in); 123 String s = getPDString(); 124 125 if (Constants.DEBUG) { 126 System.out.println("PD String = \"" + s + "\""); 127 } 128 129 ctype = getInt(s); // Spline Type before conversion to Type 112 130 H = getInt(s); // Degree of continuity with respect to arc length 131 NDIM = getInt(s); // Number of dimensions 132 N = getInt(s); // Number of segments 133 134 // Read in breakpoints of piecewise polynomial 135 T = new double[N + 1]; // Allocate storage for the breakpoints 136 for (int i = 0; i <= N; ++i) { 137 double u = getReal(s); 138 T[i] = u; 139 } 140 141 // Allocate memory for the polynomial segment coefficients. 142 A = new double[N][NDIM]; 143 B = new double[N][NDIM]; 144 C = new double[N][NDIM]; 145 D = new double[N][NDIM]; 146 147 // Loop over each segment. 148 for (int i = 0; i < N; ++i) { 149 // Read in the coefficients in each coordinate direction. 150 for (int j = 0; j < NDIM; ++j) { 151 A[i][j] = getReal(s); 152 B[i][j] = getReal(s); 153 C[i][j] = getReal(s); 154 D[i][j] = getReal(s); 155 } 156 } 157 158 // Read in the remaining evaluation points. 159 TP = new double[NDIM][4]; 160 for (int i = 0; i < NDIM; ++i) { 161 for (int j = 0; j < 4; ++j) { 162 TP[i][j] = getReal(s); 163 } 164 } 165 166 super.read_additional(); 167 } 168 169 /** 170 * The GeomSS geometry element is created from the IGES parameters when this method is 171 * called. 172 */ 173 @Override 174 void createGeometry() throws IOException { 175 176 // Convert from polynomial coefficient form to B-Spline control points. 177 // Reference: Handbook of Grid Generation, Chapter 30, Section 30.3.0. 178 179 // Bezier control polygon: bmat[0..3] = Bm*Cmat 180 final int degree = 3; 181 final int order = degree + 1; 182 List<ControlPoint> cps = new ArrayList(); 183 double[][] Cmat = new double[order][NDIM]; 184 boolean firstPass = true; 185 for (int i = 0; i < N; ++i) { 186 187 // Calculate the reparameterization factor. 188 double h = T[i + 1] - T[i]; 189 double h2 = h * h; 190 double h3 = h2 * h; 191 192 // Build up the polynomial coefficient matrix. 193 for (int j = 0; j < NDIM; ++j) { 194 Cmat[0][j] = A[i][j]; 195 Cmat[1][j] = B[i][j] * h; 196 Cmat[2][j] = C[i][j] * h2; 197 Cmat[3][j] = D[i][j] * h3; 198 } 199 200 // bmat = Bmat*Cmat 201 Float64Matrix Cm = Float64Matrix.valueOf(Cmat); 202 Float64Matrix bm = Bm.times(Cm); 203 204 // Convert bm into a list of control points. 205 List<ControlPoint> cpList = cpMatrix2ControlPoints(bm, Constants.unit); 206 if (firstPass) { 207 // Only add the 1st control point on the 1st segment. 208 firstPass = false; 209 cps.add(cpList.get(0)); 210 } 211 for (int j = 1; j < order; ++j) { 212 cps.add(cpList.get(j)); 213 } 214 } 215 216 // Create a knot list and put a degree+1 touple knot at the start. 217 List<Double> knots = new ArrayList(); 218 for (int i = 0; i <= degree; i++) { 219 knots.add(ZERO); 220 } 221 222 // Add degree+1 touple knots where each Bezier segment is joined. 223 double ds = 1. / N; 224 double sv = 0; 225 for (int j = 1; j < N; ++j) { 226 sv += ds; 227 for (int i = 0; i < degree; i++) { 228 knots.add(sv); 229 } 230 } 231 232 // Add a degree+1 touble set of knots at the end. 233 for (int i = 0; i <= degree; i++) { 234 knots.add(ONE); 235 } 236 237 // Create the knot vector. 238 KnotVector kv = KnotVector.newInstance(degree, knots); 239 240 // Create the curve. 241 curve = BasicNurbsCurve.newInstance(cps, kv); 242 243 } 244 245 /** 246 * Method used to apply IGES meta-data to GeomSS elements. This implementation stores 247 * in the user data, in addition to the header info, all the parameter information for 248 * this entity type prefixed by "IGES_112_". 249 */ 250 @Override 251 protected void applyMetaData(GeomElement element) { 252 super.applyMetaData(element); 253 element.putUserData("IGES_112_CTYPE", ctype); 254 element.putUserData("IGES_112_H", H); 255 element.putUserData("IGES_112_N", N); 256 element.putUserData("IGES_112_T", T); 257 element.putUserData("IGES_112_A", A); 258 element.putUserData("IGES_112_B", B); 259 element.putUserData("IGES_112_C", C); 260 element.putUserData("IGES_112_D", D); 261 element.putUserData("IGES_112_TP", TP); 262 element.putUserData("IGES_U0", T[0]); 263 element.putUserData("IGES_U1", T[N]); 264 } 265 266 /** 267 * Return a list of control points from the input matrix of control point coordinates 268 * (points in rows, dimensions in columns). 269 * 270 */ 271 private static List<ControlPoint> cpMatrix2ControlPoints(Float64Matrix Pmat, Unit units) { 272 273 // Create a list of control points from the matrix of control point positions. 274 List<ControlPoint> cpList = new ArrayList(); 275 int numPoints = Pmat.getNumberOfRows(); 276 for (int i = 0; i < numPoints; i++) { 277 ControlPoint pnt = ControlPoint.valueOf(Pmat.getRow(i), 1., units); 278 cpList.add(pnt); 279 } 280 281 return cpList; 282 } 283 284 /** 285 * Return a reference to the Transformable GeomElement contained in this IGES Entity. 286 * 287 * @return A reference to the Transformable GeomElement contained in this IGES Entity. 288 */ 289 @Override 290 protected Transformable getGeomElement() { 291 return curve; 292 } 293 294 /** 295 * Returns a short String describing this Entity object's type. 296 * 297 * @return A short String describing this Entity object's type. 298 */ 299 @Override 300 public String getTypeString() { 301 return "Entity112 - Parametric Spline Curve"; 302 } 303 304 /** 305 * Dump to String. 306 * 307 * @return String containing the resulting text. 308 */ 309 @Override 310 public String toString() { 311 StringBuilder outStr = new StringBuilder(super.toString()); 312 outStr.append("\n"); 313 314 return outStr.toString(); 315 } 316 317}