1 // This is gel/vtol/vtol_face_2d.cxx
2 #include "vtol_face_2d.h"
3 //:
4 // \file
5
6 #include <cassert>
7 #ifdef _MSC_VER
8 # include "vcl_msvc_warnings.h"
9 #endif
10 #include <vtol/vtol_topology_object.h>
11 #include <vtol/vtol_edge_2d.h>
12 #include <vtol/vtol_one_chain.h>
13 #include <vsol/vsol_region_2d.h>
14 #include <vsol/vsol_rectangle_2d.h>
15 #include <vsol/vsol_point_2d.h>
16
17 //---------------------------------------------------------------------------
18 //: Pseudo copy constructor. Deep copy.
19 //---------------------------------------------------------------------------
vtol_face_2d(vtol_face_2d_sptr const & other)20 vtol_face_2d::vtol_face_2d(vtol_face_2d_sptr const& other)
21 : surface_(nullptr)
22 {
23 edge_list edgs; other->edges(edgs);
24 vertex_list verts; other->vertices(verts);
25
26 topology_list newedges(edgs.size());
27 topology_list newverts(verts.size());
28
29 int i=0;
30 for (auto vi=verts.begin();vi!=verts.end();++vi,++i)
31 {
32 vtol_vertex_sptr v=(*vi);
33 newverts[i]=v->clone()->cast_to_topology_object();
34 v->set_id(i);
35 }
36 int j=0;
37 for (auto ei=edgs.begin();ei!= edgs.end();++ei,++j)
38 {
39 vtol_edge_sptr e=(*ei);
40
41 vtol_topology_object_sptr V1 = newverts[e->v1()->get_id()];
42 vtol_topology_object_sptr V2 = newverts[e->v2()->get_id()];
43 if (!V1 || !V2)
44 {
45 std::cerr << "Inconsistent topology in vtol_face_2d pseudo copy constructor\n";
46 link_inferior(new vtol_one_chain);
47 return;
48 }
49 // make the topology and geometry match
50 vtol_edge_sptr newedge=new vtol_edge_2d(V1->cast_to_vertex(),
51 V2->cast_to_vertex());
52
53 newedges[j]=newedge->cast_to_topology_object();
54 e->set_id(j);
55 }
56
57 // This is a deep copy of the vtol_face_2d.
58 topology_list::const_iterator ii;
59 for (ii=other->inferiors()->begin();ii!= other->inferiors()->end();++ii)
60 link_inferior((*ii)->cast_to_one_chain()->copy_with_arrays(newverts,newedges));
61 set_surface(nullptr);
62 if (other->surface_)
63 set_surface(other->surface_->clone()->cast_to_region());
64 }
65
66 //---------------------------------------------------------------------------
67 //: Clone `this': creation of a new object and initialization.
68 // See Prototype pattern
69 //---------------------------------------------------------------------------
clone() const70 vsol_spatial_object_2d* vtol_face_2d::clone() const
71 {
72 return new vtol_face_2d(vtol_face_2d_sptr(const_cast<vtol_face_2d*>(this)));
73 }
74
surface() const75 vsol_region_2d_sptr vtol_face_2d::surface() const
76 {
77 return surface_;
78 }
79
80 //: copy with an array
81
82 vtol_face *
copy_with_arrays(topology_list & verts,topology_list & edges) const83 vtol_face_2d::copy_with_arrays(topology_list &verts,
84 topology_list &edges) const
85 {
86 auto *newface=new vtol_face_2d();
87 topology_list::const_iterator i;
88 for (i=newface->inferiors()->begin();i!= newface->inferiors()->end();++i )
89 newface->unlink_inferior((*i)->cast_to_one_chain());
90 newface->inferiors()->clear();
91 for (i=inferiors()->begin();i!=inferiors()->end();++i)
92 {
93 vtol_one_chain *onech=(*i)->cast_to_one_chain()->copy_with_arrays(verts,edges);
94 assert(*onech == *(*i));
95 newface->link_inferior(onech);
96 }
97 if (surface_)
98 newface->set_surface(surface_->clone()->cast_to_region());
99 return newface;
100 }
101
102 //---------------------------------------------------------------------------
103 //: Copy with no links. Only copy the surface if it exists
104 //---------------------------------------------------------------------------
shallow_copy_with_no_links() const105 vtol_face *vtol_face_2d::shallow_copy_with_no_links() const
106 {
107 vtol_face_2d *result;
108 result=new vtol_face_2d;
109 result->set_surface(nullptr);
110 if (surface_)
111 result->set_surface(surface_->clone()->cast_to_region());
112 return result;
113 }
114
115 //: Constructor for a planar vtol_face_2d from an ordered list of vertices.
116 // Edges are constructed by connecting vtol_vertex_2d[i] to vtol_vertex_2d[(i+1)mod L].
117 // L is the length of the vertex list, verts, and i goes from 0 to L.
118 // Require: verts.size()>2
119
vtol_face_2d(vertex_list const & verts)120 vtol_face_2d::vtol_face_2d(vertex_list const& verts)
121 :surface_(nullptr)
122 {
123 // require
124 assert(verts.size()>2);
125
126 double xmin=0;
127 double ymin=0;
128 double xmax=1;
129 double ymax=1;
130
131 set_surface(new vsol_rectangle_2d(new vsol_point_2d(xmin,ymin),
132 new vsol_point_2d(xmax,ymin),
133 new vsol_point_2d(xmax,ymax),
134 new vsol_point_2d(xmin,ymax)));
135
136 //generate a list of edges for edge loop
137 bool done=false;
138 auto vi=verts.begin();
139 vtol_vertex_sptr v01=(*vi);
140 edge_list elist;
141 std::vector<signed char> directions;
142
143 while (!done)
144 {
145 // if no next vertex, then use the first vertex by calling
146 // verts->end() again to wrap around This will close the loop
147 ++vi;
148
149 if (vi==verts.end())
150 {
151 vi=verts.begin();
152 done=true;
153 }
154
155 vtol_vertex_sptr v02=(*vi); // get the next vertex (may be first)
156
157 vtol_edge_sptr newedge=v01->new_edge(v02);
158 elist.push_back(newedge);
159
160 if (*v02 == *(newedge->v2()))
161 directions.push_back((signed char)1);
162 else
163 directions.push_back((signed char)(-1));
164 v01=v02; // in the next go around v1 is v2 of the last
165 }
166
167 link_inferior(new vtol_one_chain(elist,directions,true));
168 }
169
170 //: Constructor for a planar face from a list of one_chains.
171 // This method assumes that the first vtol_one_chain on the list is the outside
172 // boundary vtol_one_chain. The remaining one_chains are holes boundaries
173 // on the face.
174
vtol_face_2d(one_chain_list const & onechs)175 vtol_face_2d::vtol_face_2d(one_chain_list const& onechs)
176 :surface_(nullptr)
177 {
178 // 1) Add one chains to the inferiors list.
179 // Assume that the first vtol_one_chain on the
180 // list is the outside boundary...the
181 // remaining one_chains are holes.
182
183 if (!onechs.empty())
184 link_inferior(onechs[0]);
185
186 vtol_one_chain_sptr onech=get_boundary_cycle();
187
188 // 2) This constructor will assume that the
189 // surface is an ImplicitPlane().
190
191 double xmin=0;
192 double ymin=0;
193 double xmax=1;
194 double ymax=1;
195
196 set_surface(new vsol_rectangle_2d(new vsol_point_2d(xmin,ymin),
197 new vsol_point_2d(xmax,ymin),
198 new vsol_point_2d(xmax,ymax),
199 new vsol_point_2d(xmin,ymax)));
200
201 if (onech)
202 for (unsigned int i = 1; i < onechs.size(); ++i)
203 onech->link_chain_inferior(onechs[i]);
204 }
205
206 //: Constructor of a Planar face from a vtol_one_chain.
207 // This method uses the vtol_one_chain, edgeloop, as the outside boundary of the face.
208
vtol_face_2d(vtol_one_chain_sptr const & edgeloop)209 vtol_face_2d::vtol_face_2d(vtol_one_chain_sptr const& edgeloop)
210 : surface_(nullptr)
211 {
212 link_inferior(edgeloop);
213
214 // TODO - surface is set to bounding box rectangle, which is often too large
215 set_surface(new vsol_rectangle_2d(new vsol_point_2d(get_min_x(),get_min_y()),
216 new vsol_point_2d(get_max_x(),get_min_y()),
217 new vsol_point_2d(get_max_x(),get_max_y()),
218 new vsol_point_2d(get_min_x(),get_max_y())));
219 }
220
221 //: Constructor requiring only the underlying geometric surface
vtol_face_2d(vsol_region_2d & facesurf)222 vtol_face_2d::vtol_face_2d (vsol_region_2d &facesurf)
223 : surface_(nullptr)
224 {
225 set_surface(&facesurf);
226
227 // not much, but at least it's a start...
228 }
229
230 //: Set the underlying geometric surface.
set_surface(vsol_region_2d_sptr const & newsurf)231 void vtol_face_2d::set_surface(vsol_region_2d_sptr const& newsurf)
232 {
233 surface_=newsurf;
234 touch();
235 }
236
operator ==(const vtol_face_2d & other) const237 bool vtol_face_2d::operator==(const vtol_face_2d &other) const
238 {
239 if (this==&other) return true;
240
241 if (numinf()!=other.numinf())
242 return false;
243
244 if ( (surface_ && ! other.surface_) ||
245 (other.surface_ && ! surface_))
246 return false;
247
248 if (surface_ && *surface_!=*(other.surface_))
249 return false;
250
251 topology_list::const_iterator ti1;
252 topology_list::const_iterator ti2;
253
254 for (ti1=inferiors()->begin(),ti2=other.inferiors()->begin();
255 ti1!=inferiors()->end(); ++ti1,++ti2)
256 if (!(*(*ti1)== *(*ti2)))
257 return false;
258
259 return true;
260 }
261
operator ==(const vtol_face & other) const262 bool vtol_face_2d::operator==(const vtol_face &other) const
263 {
264 if (! other.cast_to_face_2d() )
265 return false;
266 else
267 return *this == (vtol_face_2d const&) other;
268 }
269
270 //: spatial object equality
271
operator ==(const vsol_spatial_object_2d & obj) const272 bool vtol_face_2d::operator==(const vsol_spatial_object_2d& obj) const
273 {
274 return
275 obj.cast_to_topology_object() &&
276 obj.cast_to_topology_object()->cast_to_face() &&
277 obj.cast_to_topology_object()->cast_to_face()->cast_to_face_2d() &&
278 *this == *obj.cast_to_topology_object()->cast_to_face()->cast_to_face_2d();
279 }
280
281 //:
282 // This method describes the data members of the vtol_face_2d including the
283 // Inferiors. The blanking argument is used to indent the output in
284 // a clear fashion.
285
describe(std::ostream & strm,int blanking) const286 void vtol_face_2d::describe(std::ostream &strm,
287 int blanking) const
288 {
289 for (int j=0; j<blanking; ++j) strm << ' ';
290 print(strm);
291 for (unsigned int i=0;i<inferiors()->size();++i)
292 {
293 if ((inferiors_[i])->cast_to_one_chain()!=nullptr)
294 inferiors_[i]->cast_to_one_chain()->describe(strm,blanking);
295 else
296 strm << "*** Odd inferior for a face\n";
297 }
298 }
299
300 //:
301 // This method prints out a simple text representation for the vtol_face_2d which
302 // includes its address in memory.
print(std::ostream & strm) const303 void vtol_face_2d::print(std::ostream &strm) const
304 {
305 strm << "<vtol_face_2d ";
306
307 topology_list::const_iterator ii;
308 for (ii=inferiors()->begin();ii!= inferiors()->end();++ii)
309 {
310 strm << ' ' << (*ii)->inferiors()->size();
311 }
312 strm << " " << (void const *) this << ">\n";
313 }
314
315 //: copy the geometry
316
copy_geometry(const vtol_face & other)317 void vtol_face_2d::copy_geometry(const vtol_face &other)
318 {
319 if (other.cast_to_face_2d())
320 surface_ = other.cast_to_face_2d()->surface();
321 }
322
323 //: provide a mechanism to compare geometry
324
compare_geometry(const vtol_face & other) const325 bool vtol_face_2d::compare_geometry(const vtol_face &other) const
326 {
327 if (other.cast_to_face_2d())
328 return (*surface_)== *(other.cast_to_face_2d()->surface());
329 else
330 return false;
331 }
332