001/*
002 *   Entity100_CircularArc  -- Entity that defines a circle or circular arc.
003 *
004 *   Copyright (C) 2010-2025, Joseph A. Huwaldt. All rights reserved.
005 *   
006 *   This library is free software; you can redistribute it and/or
007 *   modify it under the terms of the GNU Lesser General Public
008 *   License as published by the Free Software Foundation; either
009 *   version 2.1 of the License, or (at your option) any later version.
010 *   
011 *   This library is distributed in the hope that it will be useful,
012 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
013 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 *   Lesser General Public License for more details.
015 *
016 *   You should have received a copy of the GNU Lesser General Public License
017 *   along with this program; if not, write to the Free Software
018 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
019 *   Or visit:  http://www.gnu.org/licenses/lgpl.html
020 *
021 *   Based on, but heavily modified from, IGESView ( http://ts.nist.gov/Standards/IGES/igesTools.cfm )
022 */
023package geomss.geom.reader.iges;
024
025import geomss.geom.*;
026import geomss.geom.nurbs.CurveFactory;
027import jahuwaldt.js.param.Parameter;
028import java.io.IOException;
029import java.io.RandomAccessFile;
030import javax.measure.quantity.Angle;
031import javax.measure.quantity.Dimensionless;
032import javax.measure.quantity.Length;
033import javax.measure.unit.SI;
034import static javolution.lang.MathLib.*;
035
036/**
037 * <b><i>CIRCULAR ARC ENTITY</i></b> - This entity defines a circle or a portion of a
038 * circle which may be isolated or used as a component of a Composite Curve Entity or a
039 * subfigure. The definition space coordinate system is always chosen so that the circular
040 * arc remains in a plane either coincident with or parallel to the XT, YT plane.
041 *
042 * <p>
043 * This entity, when read from an IGES file, is converted to a NURBS curve of degree 2
044 * (IGES type 126, Form 2, Degree 2). This entity type can not be written out to an IGES
045 * file. All circular arc parameters are stored in the user data with the prefix
046 * "IGES_100_" followed by the parameter name.
047 * </p>
048 *
049 * <p> Modified by: Joseph A. Huwaldt </p>
050 * 
051 * @author JDN, Version 1.0
052 * @version February 22, 2025
053 */
054public class Entity100_CircularArc extends GeomSSEntity {
055
056    private double zt; // Parallel ZT displacement of arc from XT, YT plane
057    private double x1; // Arc center abcissa
058    private double y1; // Arc center ordinate
059    private double x2; // Start point abcissa
060    private double y2; // Start point ordinate
061    private double x3; // Terminate point abcissa
062    private double y3; // Terminate point ordinate
063
064    private double r;       // Radius
065    private double angle1;  // Start angle
066    private double angle2;  // Terminate angle
067    private boolean circle; // Full circle?
068
069    private Curve curve;    //  The GeomSS curve represented by this element.
070
071    /**
072     * Default constructor.
073     *
074     * @param p  part to which this entity is contained
075     * @param de Directory Entry for this entity
076     */
077    public Entity100_CircularArc(Part p, DirEntry de) {
078        super(p, de);
079
080        if (Constants.DEBUG) {
081            System.out.println("Entity100 constructor called");
082        }
083    }
084
085    /**
086     * Checks to see if the entity is correct. The following restrictions are imposed:
087     *
088     * - The length must be greater than 0.0
089     */
090    @Override
091    public void check() {
092        DirEntry DE = getDirectoryEntry();
093
094        // Radius must be greater than 0.0
095        double rad1 = Constants.dist(x1, y1, x2, y2);
096        double rad2 = Constants.dist(x1, y1, x3, y3);
097        if ((abs(rad1) < Constants.Grain) || (abs(rad2) < Constants.Grain)) {
098            String msg = RESOURCES.getString("zeroRadiusArc");
099            addErrorMessage(getWarningString(msg));
100        }
101
102        // Length must be greater than 0.0
103        if (abs(angle2 - angle1) < Constants.Grain) {
104            String msg = RESOURCES.getString("zeroLengthArc");
105            addErrorMessage(getWarningString(msg));
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 if the parameter could not be read in.
114     */
115    @Override
116    public void read(RandomAccessFile in) throws IOException {
117        if (Constants.DEBUG) {
118            System.out.println("Entity100.read() called");
119        }
120
121        super.read(in);
122        String s = getPDString();
123
124        if (Constants.DEBUG) {
125            System.out.println("PD String = \"" + s + "\"");
126        }
127
128        zt = getReal(s);
129        if (abs(zt) < Constants.Grain)
130            zt = 0;
131        x1 = getReal(s);
132        if (abs(x1) < Constants.Grain)
133            x1 = 0;
134        y1 = getReal(s);
135        if (abs(y1) < Constants.Grain)
136            y1 = 0;
137        x2 = getReal(s);
138        if (abs(x2) < Constants.Grain)
139            x2 = 0;
140        y2 = getReal(s);
141        if (abs(y2) < Constants.Grain)
142            y2 = 0;
143        x3 = getReal(s);
144        if (abs(x3) < Constants.Grain)
145            x3 = 0;
146        y3 = getReal(s);
147        if (abs(y3) < Constants.Grain)
148            y3 = 0;
149
150        super.read_additional();
151
152        double dx = x2 - x1;
153        double dy = y2 - y1;
154        r = sqrt(dx * dx + dy * dy);
155
156        angle1 = atan2(dy, dx);
157        angle2 = atan2(y3 - y1, x3 - x1);
158
159        circle = (abs(angle2 - angle1) < Constants.Grain);
160
161        while (angle1 < 0.0) {
162            angle1 += TWO_PI;
163        }
164
165        while (angle2 <= angle1) {
166            angle2 += TWO_PI;
167        }
168
169    }
170
171    /**
172     * The GeomSS geometry element is created from the IGES parameters when this method is
173     * called.
174     */
175    @Override
176    void createGeometry() throws IOException {
177
178        //  Define some inputs required.
179        Point center = Point.valueOf(x1, y1, zt, Constants.unit);
180        Parameter<Length> radius = Parameter.valueOf(r, Constants.unit);
181        Vector<Dimensionless> normal = Vector.valueOf(0, 0, 1).toUnitVector();
182
183        if (circle) {
184            //  We have a full circle.
185            curve = CurveFactory.createCircle(center, radius, normal);
186
187        } else {
188            //  We have an arc.
189            Parameter<Angle> thetaS = Parameter.valueOf(angle1, SI.RADIAN);
190            Parameter<Angle> thetaE = Parameter.valueOf(angle2, SI.RADIAN);
191            curve = CurveFactory.createCircularArc(center, radius, normal, thetaS, thetaE);
192        }
193
194    }
195
196    /**
197     * Method used to apply IGES meta-data to GeomSS elements. This implementation stores
198     * in the user data, in addition to the header info, all the parameter information for
199     * this entity type prefixed by "IGES_100_".
200     */
201    @Override
202    protected void applyMetaData(GeomElement element) {
203        super.applyMetaData(element);
204        element.putUserData("IGES_100_ZT", zt);
205        element.putUserData("IGES_100_X1", x1);
206        element.putUserData("IGES_100_Y1", y1);
207        element.putUserData("IGES_100_X2", x2);
208        element.putUserData("IGES_100_Y2", y2);
209        element.putUserData("IGES_100_X3", x3);
210        element.putUserData("IGES_100_Y3", y3);
211    }
212
213    /**
214     * Return a reference to the Transformable GeomElement contained in this IGES Entity.
215     *
216     * @return A reference to the Transformable GeomElement contained in this IGES Entity.
217     */
218    @Override
219    protected Transformable getGeomElement() {
220        return curve;
221    }
222
223    /**
224     * Returns a short String describing this Entity object's type.
225     *
226     * @return A short String describing this Entity object's type.
227     */
228    @Override
229    public String getTypeString() {
230        return "Entity100 - Circular Arc";
231    }
232
233    /**
234     * Dump to String.
235     *
236     * @return String containing the resulting text.
237     */
238    @Override
239    public String toString() {
240        StringBuilder outStr = new StringBuilder(super.toString());
241        outStr.append("\n");
242
243                outStr.append("zt = "); outStr.append(zt);      outStr.append("\n");
244                outStr.append("x1 = "); outStr.append(x1);      outStr.append("\n");
245                outStr.append("y1 = "); outStr.append(y1);      outStr.append("\n");
246                outStr.append("x2 = "); outStr.append(x2);      outStr.append("\n");
247                outStr.append("y2 = "); outStr.append(y2);      outStr.append("\n");
248                outStr.append("x3 = "); outStr.append(x3);      outStr.append("\n");
249                outStr.append("y3 = "); outStr.append(y3);
250
251        return outStr.toString();
252    }
253
254}