BRL-CAD
Subsurface.cpp
Go to the documentation of this file.
1 /* S U B S U R F A C E . C P P
2  * BRL-CAD
3  *
4  * Copyright (c) 2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #include "common.h"
22 #include "brep.h"
23 
24 Subsurface::Subsurface()
25  : m_surf(NULL), m_isplanar(false)
26 {
27  m_children[0] = m_children[1] = m_children[2] = m_children[3] = NULL;
28 }
29 
30 Subsurface::Subsurface(ON_Surface *surf)
31 {
32  m_surf = surf;
33  if (surf) {
34  SetBBox(surf->BoundingBox());
35  m_u = surf->Domain(0);
36  m_v = surf->Domain(1);
37  m_isplanar = surf->IsPlanar();
38  } else {
39  m_isplanar = false;
40  }
41  m_children[0] = m_children[1] = m_children[2] = m_children[3] = NULL;
42 }
43 
44 Subsurface::Subsurface(const Subsurface &_ssurf)
45 {
46  m_surf = _ssurf.m_surf->Duplicate();
47  m_u = _ssurf.m_u;
48  m_v = _ssurf.m_v;
49  m_isplanar = _ssurf.m_isplanar;
50  m_children[0] = m_children[1] = m_children[2] = m_children[3] = NULL;
51  SetBBox(_ssurf.m_node);
52 }
53 
54 Subsurface::~Subsurface()
55 {
56  for (int i = 0; i < 4; i++) {
57  if (m_children[i]) {
58  delete m_children[i];
59  }
60  }
61  delete m_surf;
62 }
63 
64 int
65 Subsurface::Split()
66 {
67  if (m_children[0] && m_children[1] && m_children[2] && m_children[3]) {
68  return 0;
69  }
70 
71  for (int i = 0; i < 4; i++) {
72  m_children[i] = new Subsurface();
73  }
74  ON_Surface *temp_surf1 = NULL, *temp_surf2 = NULL;
75  ON_BOOL32 ret = true;
76  ret = m_surf->Split(0, m_surf->Domain(0).Mid(), temp_surf1, temp_surf2);
77  if (!ret) {
78  delete temp_surf1;
79  delete temp_surf2;
80  return -1;
81  }
82 
83  ret = temp_surf1->Split(1, m_surf->Domain(1).Mid(), m_children[0]->m_surf, m_children[1]->m_surf);
84  delete temp_surf1;
85  if (!ret) {
86  delete temp_surf2;
87  return -1;
88  }
89  m_children[0]->m_u = ON_Interval(m_u.Min(), m_u.Mid());
90  m_children[0]->m_v = ON_Interval(m_v.Min(), m_v.Mid());
91  m_children[0]->SetBBox(m_children[0]->m_surf->BoundingBox());
92  m_children[0]->m_isplanar = m_children[0]->m_surf->IsPlanar();
93  m_children[1]->m_u = ON_Interval(m_u.Min(), m_u.Mid());
94  m_children[1]->m_v = ON_Interval(m_v.Mid(), m_v.Max());
95  m_children[1]->SetBBox(m_children[1]->m_surf->BoundingBox());
96  m_children[1]->m_isplanar = m_children[1]->m_surf->IsPlanar();
97 
98  ret = temp_surf2->Split(1, m_v.Mid(), m_children[2]->m_surf, m_children[3]->m_surf);
99  delete temp_surf2;
100  if (!ret) {
101  return -1;
102  }
103  m_children[2]->m_u = ON_Interval(m_u.Mid(), m_u.Max());
104  m_children[2]->m_v = ON_Interval(m_v.Min(), m_v.Mid());
105  m_children[2]->SetBBox(m_children[2]->m_surf->BoundingBox());
106  m_children[2]->m_isplanar = m_children[2]->m_surf->IsPlanar();
107  m_children[3]->m_u = ON_Interval(m_u.Mid(), m_u.Max());
108  m_children[3]->m_v = ON_Interval(m_v.Mid(), m_v.Max());
109  m_children[3]->SetBBox(m_children[3]->m_surf->BoundingBox());
110  m_children[3]->m_isplanar = m_children[3]->m_surf->IsPlanar();
111 
112  return 0;
113 }
114 
115 void
116 Subsurface::GetBBox(ON_3dPoint &min, ON_3dPoint &max)
117 {
118  min = m_node.m_min;
119  max = m_node.m_max;
120 }
121 
122 void
123 Subsurface::SetBBox(const ON_BoundingBox &bbox)
124 {
125  m_node = bbox;
126  /* Make sure that each dimension of the bounding box is greater than
127  * ON_ZERO_TOLERANCE.
128  * It does the same work as building the surface tree when ray tracing
129  */
130  for (int i = 0; i < 3; i++) {
131  double d = m_node.m_max[i] - m_node.m_min[i];
132  if (ON_NearZero(d, ON_ZERO_TOLERANCE)) {
133  m_node.m_min[i] -= 0.001;
134  m_node.m_max[i] += 0.001;
135  }
136  }
137 }
138 
139 bool
140 Subsurface::IsPointIn(const ON_3dPoint &pt, double tolerance /* = 0.0 */)
141 {
142  ON_3dVector vtol(tolerance, tolerance, tolerance);
143  ON_BoundingBox new_bbox(m_node.m_min - vtol, m_node.m_max + vtol);
144  return new_bbox.IsPointIn(pt);
145 }
146 
147 bool
148 Subsurface::Intersect(
149  const Subcurve &curve,
150  double tolerance /* = 0.0 */,
151  ON_BoundingBox *intersection /* = NULL */) const
152 {
153  ON_3dVector vtol(tolerance, tolerance, tolerance);
154  ON_BoundingBox new_bbox(m_node.m_min - vtol, m_node.m_max + vtol);
155  ON_BoundingBox box;
156  bool ret = box.Intersection(new_bbox, curve.m_node);
157  if (intersection != NULL) {
158  *intersection = box;
159  }
160  return ret;
161 }
162 
163 bool
164 Subsurface::Intersect(
165  const Subsurface &surf,
166  double tolerance /* = 0.0 */,
167  ON_BoundingBox *intersection /* = NULL */) const
168 {
169  ON_3dVector vtol(tolerance, tolerance, tolerance);
170  ON_BoundingBox new_bbox(m_node.m_min - vtol, m_node.m_max + vtol);
171  ON_BoundingBox box;
172  bool ret = box.Intersection(new_bbox, surf.m_node);
173  if (intersection != NULL) {
174  *intersection = ON_BoundingBox(box.m_min - vtol, box.m_max + vtol);
175  }
176  return ret;
177 }
178 
179 // Local Variables:
180 // tab-width: 8
181 // mode: C++
182 // c-basic-offset: 4
183 // indent-tabs-mode: t
184 // c-file-style: "stroustrup"
185 // End:
186 // ex: shiftwidth=4 tabstop=8
Header file for the BRL-CAD common definitions.
bool ON_NearZero(double val, double epsilon)
Return truthfully whether a value is within a specified epsilon distance from zero.