1 // This is gel/vtol/vtol_edge_2d.cxx
2 #include "vtol_edge_2d.h"
3 //:
4 // \file
5 
6 #include <vtol/vtol_zero_chain.h>
7 #include <vsol/vsol_curve_2d.h>
8 #include <vsol/vsol_line_2d.h>
9 #include <vdgl/vdgl_digital_curve.h>
10 #include <cassert>
11 #ifdef _MSC_VER
12 #  include "vcl_msvc_warnings.h"
13 #endif
14 
15 //***************************************************************************
16 // Initialization
17 //***************************************************************************
18 
19 //---------------------------------------------------------------------------
20 //: Constructor from the two endpoints `new_v1', `new_v2' and from a curve `new_curve'.
21 //  If `new_curve' is 0, a line is created from `new_v1' and `new_v2'.
22 //---------------------------------------------------------------------------
vtol_edge_2d(vtol_vertex_2d_sptr const & new_v1,vtol_vertex_2d_sptr const & new_v2,vsol_curve_2d_sptr const & new_curve)23 vtol_edge_2d::vtol_edge_2d(vtol_vertex_2d_sptr const& new_v1,
24                            vtol_vertex_2d_sptr const& new_v2,
25                            vsol_curve_2d_sptr const& new_curve)
26 {
27   assert(new_v1!=nullptr); v1_=new_v1->cast_to_vertex();
28   assert(new_v2!=nullptr); v2_=new_v2->cast_to_vertex();
29   if (!new_curve)
30     curve_=new vsol_line_2d(new_v1->point(),new_v2->point());
31   else
32     curve_=new_curve;
33 
34   link_inferior(new vtol_zero_chain(v1_,v2_));
35 }
36 
vtol_edge_2d(vtol_vertex_sptr const & new_v1,vtol_vertex_sptr const & new_v2,vsol_curve_2d_sptr const & new_curve)37 vtol_edge_2d::vtol_edge_2d(vtol_vertex_sptr const& new_v1,
38                            vtol_vertex_sptr const& new_v2,
39                            vsol_curve_2d_sptr const& new_curve)
40 {
41   assert(new_v1->cast_to_vertex_2d()); v1_=new_v1;
42   assert(new_v2->cast_to_vertex_2d()); v2_=new_v2;
43   if (!new_curve)
44     curve_=new vsol_line_2d(v1_->cast_to_vertex_2d()->point(),
45                             v2_->cast_to_vertex_2d()->point());
46   else
47     curve_=new_curve;
48 
49   link_inferior(new vtol_zero_chain(v1_,v2_));
50 }
51 
52 //---------------------------------------------------------------------------
53 //: Pseudo copy constructor. Deep copy.
54 //---------------------------------------------------------------------------
vtol_edge_2d(vtol_edge_2d_sptr const & other)55 vtol_edge_2d::vtol_edge_2d(vtol_edge_2d_sptr const& other)
56   : curve_(nullptr)
57 {
58   topology_list::const_iterator i;
59   for (i=other->inferiors()->begin();i!=other->inferiors()->end();++i)
60   {
61     link_inferior((*i)->clone()->cast_to_topology_object()->cast_to_zero_chain());
62   }
63   set_vertices_from_zero_chains();
64 
65   if (other->curve())
66   {
67     curve_ = other->curve()->clone()->cast_to_curve();
68     // make sure the geometry and Topology are in sync
69     if (v1_)
70     {
71       if (v1_->cast_to_vertex_2d())
72       {
73         curve_->set_p0(v1_->cast_to_vertex_2d()->point());
74         curve_->touch();
75       }
76     }
77     if (v2_)
78     {
79       if (v1_->cast_to_vertex_2d())
80       {
81         curve_->set_p1(v2_->cast_to_vertex_2d()->point());
82         curve_->touch();
83       }
84     }
85   }
86   touch();
87 }
88 
89 //---------------------------------------------------------------------------
90 //: Constructor from a zero-chain.
91 //---------------------------------------------------------------------------
92 //
93 // Constructor for a vtol_edge_2d. If the vtol_zero_chain has two vertices , then the
94 // first and last vertices of the vtol_zero_chain are used for endpoints and
95 // an ImplicitLine is assumed to be the curve.  Otherwise, the all data
96 // (v1_, v2_, curve_) are set to NULL.  The vtol_zero_chain, newchain, becomes
97 // the Inferior of the vtol_edge_2d.
98 
vtol_edge_2d(vtol_zero_chain_sptr const & new_zero_chain)99 vtol_edge_2d::vtol_edge_2d(vtol_zero_chain_sptr const& new_zero_chain)
100 {
101   link_inferior(new_zero_chain);
102   set_vertices_from_zero_chains();
103   if (new_zero_chain->numinf()==2 && v1_->cast_to_vertex_2d() && v2_->cast_to_vertex_2d())
104     // Safe to assume that it is a vsol_line_2d.
105     curve_=new vsol_line_2d(v1_->cast_to_vertex_2d()->point(),
106                             v2_->cast_to_vertex_2d()->point());
107   else
108     // User must set the type of curve needed.
109     // Since guessing could get confusing.
110     // So NULL indicates an edge of unknown type.
111     curve_=nullptr;
112   touch();
113 }
114 
115 //: Constructor for a vtol_edge_2d from a list of zero-chains.
116 // The list of zero-chains, newchains, is
117 // assumed to be ordered along an edge. This method assigns the first
118 // vertex in the chain list to v1_, and assigns the last vertex in the
119 // chain list to v2_. No assumptions are made as to the curve type. The
120 // data member, curve_ is left to be NULL.
121 
vtol_edge_2d(zero_chain_list const & newchains)122 vtol_edge_2d::vtol_edge_2d(zero_chain_list const& newchains)
123 {
124   // 1) Link the inferiors.
125 
126   for (const auto & newchain : newchains)
127     link_inferior(newchain);
128 
129   // 2) Set v1_ and v2_;
130 
131   set_vertices_from_zero_chains();
132   curve_=nullptr;
133 }
134 
135 //: Constructor for a linear vtol_edge_2d.
136 // The coordinates, (x1, y1, z1), determine vtol_vertex_2d, v1_.
137 // The coordinates, (x2, y2, z2), determine v2_.
138 // If curve is NULL, a vsol_line_2d is generated for the vtol_edge_2d.
139 
vtol_edge_2d(double x1,double y1,double x2,double y2,const vsol_curve_2d_sptr & curve)140 vtol_edge_2d::vtol_edge_2d(double x1, double y1,
141                            double x2, double y2,
142                            const vsol_curve_2d_sptr& curve)
143 {
144   v1_=new vtol_vertex_2d(x1,y1);
145   v2_=new vtol_vertex_2d(x2,y2);
146   if (!curve) {
147     if (v1_->cast_to_vertex_2d() && v2_->cast_to_vertex_2d())
148       curve_=new vsol_line_2d(v1_->cast_to_vertex_2d()->point(),
149                               v2_->cast_to_vertex_2d()->point());
150   }
151   else
152     curve_=curve->clone()->cast_to_curve();
153 
154   link_inferior(new vtol_zero_chain(v1_,v2_));
155 }
156 
157 //: Constructor for a vtol_edge_2d from a vsol_curve_2d.
158 // If edgecurve is of vsol_line_2d
159 // type, vertex locations for endpoints, v1_ and v2_, are computed from
160 // the vsol_line_2d parameters.  If edgecurve is of any other type, v1_
161 // and v2_ are retrieved from the end points of the curve.
162 
vtol_edge_2d(vsol_curve_2d & edgecurve)163 vtol_edge_2d::vtol_edge_2d(vsol_curve_2d &edgecurve)
164 {
165   v1_ = new vtol_vertex_2d(*(edgecurve.p0()));
166   v2_ = new vtol_vertex_2d(*(edgecurve.p1()));
167   link_inferior(new vtol_zero_chain(v1_,v2_));
168 }
169 
170 //---------------------------------------------------------------------------
171 //: Clone `this': creation of a new object and initialization
172 // See Prototype pattern
173 //---------------------------------------------------------------------------
clone() const174 vsol_spatial_object_2d* vtol_edge_2d::clone() const
175 {
176   return new vtol_edge_2d(vtol_edge_2d_sptr(const_cast<vtol_edge_2d*>(this)));
177 }
178 
179 //---------------------------------------------------------------------------
180 //: Set the curve with `new_curve'
181 //---------------------------------------------------------------------------
set_curve(vsol_curve_2d & new_curve)182 void vtol_edge_2d::set_curve(vsol_curve_2d &new_curve)
183 {
184   curve_=&new_curve;
185   touch(); //Update timestamp
186 }
187 
188 // ******************************************************
189 //
190 //    Operators
191 //
192 
operator ==(const vtol_edge_2d & other) const193 bool vtol_edge_2d::operator==(const vtol_edge_2d &other) const
194 {
195   if (this==&other) return true;
196 
197   if ( (curve() && !other.curve()) ||
198        (!curve() && other.curve()) )
199     return false;
200 
201   if (curve() && (*curve())!=(*other.curve()))
202     return false;
203 
204   if (!(*v1_==*(other.v1_)) || !(*v2_==*(other.v2_)))
205     return false;
206 
207   vtol_zero_chain_sptr zc1=zero_chain();
208   vtol_zero_chain_sptr zc2=other.zero_chain();
209   if (!zc1||!zc2)
210     return false;
211   return *zc1==*zc2;
212 }
213 
214 //: edge equality
operator ==(const vtol_edge & other) const215 bool vtol_edge_2d::operator==(const vtol_edge &other) const
216 {
217   return other.cast_to_edge_2d() && *this == *other.cast_to_edge_2d();
218 }
219 
220 //: spatial object equality
operator ==(const vsol_spatial_object_2d & obj) const221 bool vtol_edge_2d::operator==(const vsol_spatial_object_2d& obj) const
222 {
223   return
224    obj.cast_to_topology_object() &&
225    obj.cast_to_topology_object()->cast_to_edge() &&
226    *this == *obj.cast_to_topology_object()->cast_to_edge();
227 }
228 
229 // ******************************************************
230 //
231 //    Inferior/Superior Accessor Functions
232 //
233 // ******************************************************
234 //
235 //    I/O methods
236 //
237 
238 //:
239 // This method outputs all edge information to the std::ostream, strm.  It
240 // indents various levels of output by the number given in blanking.
describe(std::ostream & strm,int blanking) const241 void vtol_edge_2d::describe(std::ostream &strm,
242                             int blanking) const
243 {
244   for (int i1=0; i1<blanking; ++i1) strm << ' ';
245   print(strm);
246   for (int i2=0; i2<blanking; ++i2) strm << ' ';
247   if (v1_) {
248     v1_->print(strm);
249   }
250   else {
251     strm << "Null vertex 1\n";
252   }
253   for (int i3=0; i3<blanking; ++i3) strm << ' ';
254   if (v2_) {
255     v2_->print(strm);
256   }
257   else {
258     strm << "Null vertex 2\n";
259   }
260 }
261 
262 //:
263 // This method outputs a brief vtol_edge_2d info with vtol_edge_2d object address.
print(std::ostream & strm) const264 void vtol_edge_2d::print(std::ostream &strm) const
265 {
266    strm<<"<vtol_edge_2d "<<(void const *)this <<"> with id "<<get_id()<<'\n';
267 }
268 
269 //: copy the geometry
270 
copy_geometry(const vtol_edge & other)271 void vtol_edge_2d::copy_geometry(const vtol_edge &other)
272 {
273   if (other.cast_to_edge_2d())
274     curve_ = other.cast_to_edge_2d()->curve();
275 }
276 
compare_geometry(const vtol_edge & other) const277 bool vtol_edge_2d::compare_geometry(const vtol_edge &other) const
278 {
279   // we want to compare geometry
280 
281   if (other.cast_to_edge_2d())
282     return (*curve()) == *(other.cast_to_edge_2d()->curve());
283   else
284     return false;
285 }
286 
compute_bounding_box() const287 void vtol_edge_2d::compute_bounding_box() const
288 {
289   this->empty_bounding_box();
290   vsol_curve_2d_sptr c = this->curve();
291   if (c && c->cast_to_vdgl_digital_curve())
292     this->set_bounding_box(c->cast_to_vdgl_digital_curve()->get_bounding_box());
293   else // the geometry is either a line segment or unknown
294     vtol_topology_object::compute_bounding_box();
295 }
296