00001 // Filename: eggNurbsCurve.cxx 00002 // Created by: drose (15Feb00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "eggNurbsCurve.h" 00020 00021 #include <indent.h> 00022 00023 TypeHandle EggNurbsCurve::_type_handle; 00024 00025 //////////////////////////////////////////////////////////////////// 00026 // Function: EggNurbsCurve::setup 00027 // Access: Public 00028 // Description: Prepares a new curve definition with the indicated 00029 // order and number of knots. This also implies a 00030 // particular number of vertices as well (the number of 00031 // knots minus the order), but it is up to the user to 00032 // add the correct number of vertices to the curve by 00033 // repeatedly calling push_back(). 00034 //////////////////////////////////////////////////////////////////// 00035 void EggNurbsCurve:: 00036 setup(int order, int num_knots) { 00037 _order = order; 00038 _knots.clear(); 00039 00040 int i; 00041 _knots.reserve(num_knots); 00042 for (i = 0; i < num_knots; i++) { 00043 _knots.push_back((double)i); 00044 } 00045 } 00046 00047 //////////////////////////////////////////////////////////////////// 00048 // Function: EggNurbsCurve::set_num_knots 00049 // Access: Public 00050 // Description: Directly changes the number of knots. This will 00051 // either add zero-valued knots onto the end, or 00052 // truncate knot values from the end, depending on 00053 // whether the list is being increased or decreased. If 00054 // possible, it is preferable to use the setup() method 00055 // instead of directly setting the number of knots, as 00056 // this may result in an invalid curve. 00057 //////////////////////////////////////////////////////////////////// 00058 void EggNurbsCurve:: 00059 set_num_knots(int num) { 00060 if ((int)_knots.size() >= num) { 00061 // Truncate knot values at the end. 00062 _knots.erase(_knots.begin() + num, _knots.end()); 00063 } else { 00064 // Append knot values to the end. 00065 _knots.reserve(num); 00066 for (int i = _knots.size(); i < num; i++) { 00067 _knots.push_back(0.0); 00068 } 00069 } 00070 } 00071 00072 //////////////////////////////////////////////////////////////////// 00073 // Function: EggNurbsCurve::is_valid 00074 // Access: Public 00075 // Description: Returns true if the NURBS parameters are all 00076 // internally consistent (e.g. it has the right number 00077 // of vertices to match its number of knots and order in 00078 // each dimension), or false otherwise. 00079 //////////////////////////////////////////////////////////////////// 00080 bool EggNurbsCurve:: 00081 is_valid() const { 00082 if (_order < 1 || _order > 4) { 00083 // Invalid order. 00084 return false; 00085 } 00086 00087 if (get_num_cvs() != (int)size()) { 00088 // Wrong number of CV's. 00089 return false; 00090 } 00091 00092 // Do all the knot values monotonically increase? 00093 int i; 00094 for (i = 1; i < get_num_knots(); i++) { 00095 if (get_knot(i) < get_knot(i - 1)) { 00096 return false; 00097 } 00098 } 00099 00100 // Everything's looking good! 00101 return true; 00102 } 00103 00104 //////////////////////////////////////////////////////////////////// 00105 // Function: EggNurbsCurve::is_closed 00106 // Access: Public 00107 // Description: Returns true if the curve appears to be closed. 00108 // Since the Egg syntax does not provide a means for 00109 // explicit indication of closure, this has to be 00110 // guessed at by examining the curve itself. 00111 //////////////////////////////////////////////////////////////////// 00112 bool EggNurbsCurve:: 00113 is_closed() const { 00114 // Technically, the curve is closed if the CV's at the end are 00115 // repeated from the beginning. We'll do a cheesy test for 00116 // expediency's sake: the curve is closed if the first n knots are 00117 // not repeated. I think this will catch all the normal curves 00118 // we're likely to see. 00119 00120 int i; 00121 for (i = 1; i < get_order(); i++) { 00122 if (get_knot(i) != get_knot(i-1)) { 00123 return true; 00124 } 00125 } 00126 return false; 00127 } 00128 00129 //////////////////////////////////////////////////////////////////// 00130 // Function: EggNurbsCurve::write 00131 // Access: Public, Virtual 00132 // Description: Writes the nurbsCurve to the indicated output stream in 00133 // Egg format. 00134 //////////////////////////////////////////////////////////////////// 00135 void EggNurbsCurve:: 00136 write(ostream &out, int indent_level) const { 00137 write_header(out, indent_level, "<NurbsCurve>"); 00138 00139 if (get_curve_type() != CT_none) { 00140 indent(out, indent_level + 2) 00141 << "<Char*> type { " << get_curve_type() << " }\n"; 00142 } 00143 if (get_subdiv() != 0) { 00144 indent(out, indent_level + 2) 00145 << "<Scalar> subdiv { " << get_subdiv() << " }\n"; 00146 } 00147 indent(out, indent_level + 2) 00148 << "<Order> { " << get_order() << " }\n"; 00149 indent(out, indent_level + 2) 00150 << "<Knots> {\n"; 00151 write_long_list(out, indent_level+4, _knots.begin(), _knots.end(), "", 00152 "", 72); 00153 indent(out, indent_level + 2) 00154 << "}\n"; 00155 00156 write_body(out, indent_level+2); 00157 indent(out, indent_level) << "}\n"; 00158 }