001/*
002 *   Entity102_CompositeCurve  -- Entity that represents a composite curve made up of other curve segments.
003 *
004 *   Copyright (C) 2011-2016, Joseph A. Huwaldt.
005 *   All rights reserved.
006 *   
007 *   This 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 *   This 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 this 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 *
022 *   Based on, but heavily modified from, IGESView ( http://ts.nist.gov/Standards/IGES/igesTools.cfm )
023 */
024package geomss.geom.reader.iges;
025
026import geomss.geom.*;
027import geomss.geom.nurbs.CurveUtils;
028import geomss.geom.nurbs.NurbsCurve;
029import jahuwaldt.js.param.Parameter;
030import java.io.IOException;
031import java.io.PrintWriter;
032import java.io.RandomAccessFile;
033import java.util.ArrayList;
034import java.util.List;
035import javax.measure.quantity.Length;
036
037/**
038 * <b><i>COMPOSITE CURVE ENTITY</i></b> - This entity defines an associativity
039 * relationship between an ordered list of curve segments. A composite curve is defined as
040 * an ordered list of entities consisting of a point, connect point and parameterized
041 * curve entities.
042 * 
043 * <p>
044 * This entity, when read from an IGES file, is converted to a single NurbsCurve with the
045 * original segments stored in the list "IGES_102_CCSegs" in the user data of the curve.
046 * This entity type can be written out to an IGES file.</p>
047 *
048 * <p> Modified by: Joseph A. Huwaldt </p>
049 * 
050 * @author Joseph A. Huwaldt, Date: November 16, 2011
051 * @version December 24, 2013
052 */
053public class Entity102_CompositeCurve extends GeomSSEntity {
054
055    protected List<Integer> pointers = new ArrayList();     //  List of entity DE numbers.
056
057    private NurbsCurve curve = null;                        //  The NURBS curve that will represent the composit curve.
058
059    /**
060     * Default constructor.
061     *
062     * @param p  part to which this entity is contained
063     * @param de Directory Entry for this entity
064     */
065    public Entity102_CompositeCurve(Part p, DirEntry de) {
066        super(p, de);
067
068        if (Constants.DEBUG) {
069            System.out.println("Entity102 constructor called");
070        }
071    }
072
073    /**
074     * Create this entity from the specified list of pointers to the curve segment DEs.
075     *
076     * @param part      The Part to which this entity is contained.
077     * @param DEnum     The line count from the start of the Directory Entry Section for
078     *                  this entry (odd number).
079     * @param name      The GeomSS name for this entity or <code>null</code> for none.
080     * @param segDEPtrs A list of pointers to the DE each segment of the curve in order
081     *                  from start to end.
082     */
083    public Entity102_CompositeCurve(Part part, int DEnum, String name, List<Integer> segDEPtrs) {
084        super(part, new DirEntry(102, 0, DEnum, 0, name));
085
086        pointers.addAll(segDEPtrs);
087    }
088
089    /**
090     * Checks to see if the entity is correct. No restrictions are imposed.
091     */
092    @Override
093    public void check() { }
094
095    /**
096     * Read the Parameter Data from the String read in by the superclass.
097     *
098     * @param in input file
099     * @throws java.io.IOException
100     */
101    @Override
102    public void read(RandomAccessFile in) throws IOException {
103        super.read(in);
104        String s = getPDString();
105
106        if (Constants.DEBUG) {
107            System.out.println("PD String = \"" + s + "\"");
108        }
109
110        int n = getInt(s);
111        for (int i = 0; i < n; ++i)
112            pointers.add(getInt(s));
113
114        super.read_additional();
115    }
116
117    /**
118     * The GeomSS geometry element is created from the IGES parameters when this method is
119     * called.
120     */
121    @Override
122    void createGeometry() {
123        Part part = getPart();
124
125        //  Loop over all the entities in this association.
126        GeomList<GeomElement> geom = GeomList.newInstance();
127        int n = pointers.size();
128        for (int i = 0; i < n; ++i) {
129            int deNum = pointers.get(i);
130            Entity entity = part.getEntity(deNum);
131
132            if (entity instanceof GeomSSEntity) {
133                //  Found a GeomSS geometry Entity.
134                GeomSSEntity geomEntity = (GeomSSEntity)entity;
135                geomEntity.setUsedInList(true); //  Indicate that the entity is used by this association.
136                GeomElement element = geomEntity.getGeomElement(GTransform.IDENTITY);
137                geom.add(element);
138            }
139        }
140
141        //  Convert all the non-degenerate elements into NURBS curves.
142        Parameter<Length> tol = Parameter.valueOf(Constants.Grain, Constants.unit);
143        GeomList<NurbsCurve> crvSegs = convert2NurbsSegs(geom, tol);
144
145        //  Concatentate all the curve segments together.
146        curve = CurveUtils.connectCurves(crvSegs);
147        GeomList.recycle(crvSegs);
148
149        //  TODO:  Remove unnecessary knots to return the minimal curve that matches the original.
150        curve.putUserData("IGES_102_CCSegs", geom);
151
152    }
153
154    /**
155     * Converts all the non-degenerate Curve elements in the specified geometry list into
156     * NurbsCurves.
157     *
158     * @param crvs The list of geometry elements to be converted.
159     * @param tol  The tolerance for the conversion to NURBS curves.
160     * @return A list of non-degenerate NURBS curve versions of each element in "crvs".
161     */
162    private GeomList<NurbsCurve> convert2NurbsSegs(GeomList<GeomElement> crvs, Parameter<Length> tol) {
163        GeomList<NurbsCurve> nurbsSegs = GeomList.newInstance();
164        for (GeomElement elem : crvs) {
165            if (elem instanceof Curve) {
166                NurbsCurve nurbs = ((Curve)elem).toNurbs(tol);
167                if (!nurbs.isDegenerate(tol))
168                    nurbsSegs.add(nurbs);
169            }
170        }
171        return nurbsSegs;
172    }
173
174    /**
175     * Return a reference to the Transformable GeomElement contained in this IGES Entity.
176     *
177     * @return A reference to the Transformable GeomElement contained in this IGES Entity.
178     */
179    @Override
180    protected Transformable getGeomElement() {
181        return curve;
182    }
183
184    /**
185     * Returns <code>true</code> if the Entity can be written to an exchange file.
186     *
187     * @return true
188     */
189    @Override
190    public boolean canWrite() {
191        return true;
192    }
193
194    /**
195     * Write this entity object's parameter data to the specified PrintWriter.
196     *
197     * @param writer The PrintWriter to write the parameter data for this entity to.
198     * @param PDnum  The starting Parameter Data row index number.
199     * @return The Parameter Data row index number for the next row.
200     * @throws java.io.IOException
201     */
202    @Override
203    public int write(PrintWriter writer, int PDnum) throws IOException {
204        int numSegs = pointers.size();
205
206        //  Build up the parameter data string.
207        StringBuilder buffer = new StringBuilder();
208        buffer.append(102);             buffer.append(Constants.Delim);
209        buffer.append(numSegs);         buffer.append(Constants.Delim);
210        buffer.append(pointers.get(0));
211        for (int i = 1; i < numSegs; ++i) {
212            buffer.append(Constants.Delim);
213            buffer.append(pointers.get(i));
214        }
215        buffer.append(Constants.Term);
216
217        //  Write it out.
218        int oldPDnum = PDnum;
219        PDnum = Constants.writeSection(writer, PDnum, Constants.makeSequenceNumber(getDENum()),
220                'P', buffer);
221
222        //  Store the PD line number and line count in the directory entry.
223        getDirectoryEntry().setPDNumber(oldPDnum, PDnum - oldPDnum);
224
225        return PDnum;
226    }
227
228    /**
229     * Dump to String.
230     *
231     * @return String containing the resulting text.
232     */
233    @Override
234    public String toString() {
235        StringBuilder outStr = new StringBuilder(super.toString());
236        outStr.append("\n");
237
238        int n = pointers.size();
239        outStr.append("n  = "); outStr.append(n);   outStr.append("\n");
240
241        for (int i = 0; i < n; i++) {
242            outStr.append("curve(");
243            outStr.append(i);
244            outStr.append(") = ");
245            outStr.append(pointers.get(i));
246            outStr.append("\n");
247        }
248
249        return outStr.toString();
250    }
251
252    /**
253     * Returns a short String describing this Entity object's type.
254     *
255     * @return A short String describing this Entity object's type.
256     */
257    @Override
258    public String getTypeString() {
259        return "Entity102 - Composite Curve";
260    }
261
262}