Panda3D
eggNurbsCurve.cxx
1 // Filename: eggNurbsCurve.cxx
2 // Created by: drose (15Feb00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "eggNurbsCurve.h"
16 
17 #include "indent.h"
18 
19 TypeHandle EggNurbsCurve::_type_handle;
20 
21 ////////////////////////////////////////////////////////////////////
22 // Function: EggNurbsCurve::setup
23 // Access: Public
24 // Description: Prepares a new curve definition with the indicated
25 // order and number of knots. This also implies a
26 // particular number of vertices as well (the number of
27 // knots minus the order), but it is up to the user to
28 // add the correct number of vertices to the curve by
29 // repeatedly calling push_back().
30 ////////////////////////////////////////////////////////////////////
31 void EggNurbsCurve::
32 setup(int order, int num_knots) {
33  _order = order;
34  _knots.clear();
35 
36  int i;
37  _knots.reserve(num_knots);
38  for (i = 0; i < num_knots; i++) {
39  _knots.push_back((double)i);
40  }
41 }
42 
43 ////////////////////////////////////////////////////////////////////
44 // Function: EggNurbsCurve::set_num_knots
45 // Access: Public
46 // Description: Directly changes the number of knots. This will
47 // either add zero-valued knots onto the end, or
48 // truncate knot values from the end, depending on
49 // whether the list is being increased or decreased. If
50 // possible, it is preferable to use the setup() method
51 // instead of directly setting the number of knots, as
52 // this may result in an invalid curve.
53 ////////////////////////////////////////////////////////////////////
54 void EggNurbsCurve::
55 set_num_knots(int num) {
56  if ((int)_knots.size() >= num) {
57  // Truncate knot values at the end.
58  _knots.erase(_knots.begin() + num, _knots.end());
59  } else {
60  // Append knot values to the end.
61  _knots.reserve(num);
62  for (int i = _knots.size(); i < num; i++) {
63  _knots.push_back(0.0);
64  }
65  }
66 }
67 
68 ////////////////////////////////////////////////////////////////////
69 // Function: EggNurbsCurve::is_valid
70 // Access: Public
71 // Description: Returns true if the NURBS parameters are all
72 // internally consistent (e.g. it has the right number
73 // of vertices to match its number of knots and order in
74 // each dimension), or false otherwise.
75 ////////////////////////////////////////////////////////////////////
76 bool EggNurbsCurve::
77 is_valid() const {
78  if (_order < 1 || _order > 4) {
79  // Invalid order.
80  return false;
81  }
82 
83  if (get_num_cvs() != (int)size()) {
84  // Wrong number of CV's.
85  return false;
86  }
87 
88  // Do all the knot values monotonically increase?
89  int i;
90  for (i = 1; i < get_num_knots(); i++) {
91  if (get_knot(i) < get_knot(i - 1)) {
92  return false;
93  }
94  }
95 
96  // Everything's looking good!
97  return true;
98 }
99 
100 ////////////////////////////////////////////////////////////////////
101 // Function: EggNurbsCurve::is_closed
102 // Access: Public
103 // Description: Returns true if the curve appears to be closed.
104 // Since the Egg syntax does not provide a means for
105 // explicit indication of closure, this has to be
106 // guessed at by examining the curve itself.
107 ////////////////////////////////////////////////////////////////////
108 bool EggNurbsCurve::
109 is_closed() const {
110  // Technically, the curve is closed if the CV's at the end are
111  // repeated from the beginning. We'll do a cheesy test for
112  // expediency's sake: the curve is closed if the first n knots are
113  // not repeated. I think this will catch all the normal curves
114  // we're likely to see.
115 
116  int i;
117  for (i = 1; i < get_order(); i++) {
118  if (get_knot(i) != get_knot(i-1)) {
119  return true;
120  }
121  }
122  return false;
123 }
124 
125 ////////////////////////////////////////////////////////////////////
126 // Function: EggNurbsCurve::write
127 // Access: Public, Virtual
128 // Description: Writes the nurbsCurve to the indicated output stream in
129 // Egg format.
130 ////////////////////////////////////////////////////////////////////
131 void EggNurbsCurve::
132 write(ostream &out, int indent_level) const {
133  write_header(out, indent_level, "<NurbsCurve>");
134 
135  if (get_curve_type() != CT_none) {
136  indent(out, indent_level + 2)
137  << "<Char*> type { " << get_curve_type() << " }\n";
138  }
139  if (get_subdiv() != 0) {
140  indent(out, indent_level + 2)
141  << "<Scalar> subdiv { " << get_subdiv() << " }\n";
142  }
143  indent(out, indent_level + 2)
144  << "<Order> { " << get_order() << " }\n";
145  indent(out, indent_level + 2)
146  << "<Knots> {\n";
147  write_long_list(out, indent_level+4, _knots.begin(), _knots.end(), "",
148  "", 72);
149  indent(out, indent_level + 2)
150  << "}\n";
151 
152  write_body(out, indent_level+2);
153  indent(out, indent_level) << "}\n";
154 }
void setup(int order, int num_knots)
Prepares a new curve definition with the indicated order and number of knots.
int get_order() const
Returns the order of the curve.
Definition: eggNurbsCurve.I:89
CurveType get_curve_type() const
Returns the indicated type of the curve.
Definition: eggCurve.I:99
void set_num_knots(int num)
Directly changes the number of knots.
bool is_closed() const
Returns true if the curve appears to be closed.
int get_subdiv() const
Returns the requested number of subdivisions, or 0 if no particular subdivisions have been requested...
Definition: eggCurve.I:76
double get_knot(int k) const
Returns the nth knot value defined.
int get_num_knots() const
Returns the number of knots.
void write_header(ostream &out, int indent_level, const char *egg_keyword) const
Writes the first line of the egg object, e.g.
virtual void write(ostream &out, int indent_level) const
Writes the nurbsCurve to the indicated output stream in Egg format.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
int get_num_cvs() const
Returns the total number of control vertices that should* be defined for the curve.
bool is_valid() const
Returns true if the NURBS parameters are all internally consistent (e.g.