KiCad PCB EDA Suite
citemlayercsg2d.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
30 #include "citemlayercsg2d.h"
31 #include "3d_fastmath.h"
32 #include <wx/debug.h>
33 
35  std::vector<const COBJECT2D *> *aObjectB,
36  const COBJECT2D *aObjectC,
37  const BOARD_ITEM &aBoardItem ):
38  COBJECT2D( OBJ2D_CSG, aBoardItem ),
39  m_objectA(aObjectA),
40  m_objectB(aObjectB),
41  m_objectC(aObjectC)
42 {
43  wxASSERT( aObjectA );
44 
45  m_bbox.Reset();
46  m_bbox.Set( aObjectA->GetBBox() );
49 
50  wxASSERT( m_bbox.IsInitialized() );
51 }
52 
53 
55 {
56  if( ((void*)m_objectB != CSGITEM_EMPTY) &&
57  ((void*)m_objectB != CSGITEM_FULL) )
58  {
59  delete m_objectB;
60  m_objectB = NULL;
61  }
62 }
63 
64 
65 bool CITEMLAYERCSG2D::Intersects( const CBBOX2D &aBBox ) const
66 {
67  return m_bbox.Intersects( aBBox );
68  // !TODO: improove this implementation
69  //return false;
70 }
71 
72 
73 bool CITEMLAYERCSG2D::Overlaps( const CBBOX2D &aBBox ) const
74 {
75  // NOT IMPLEMENTED
76  return false;
77 }
78 
79 // Based on ideas and implementation by Nick Chapman
80 // http://homepages.paradise.net.nz/nickamy/raytracer/raytracer.htm
81 bool CITEMLAYERCSG2D::Intersect( const RAYSEG2D &aSegRay,
82  float *aOutT,
83  SFVEC2F *aNormalOut ) const
84 {
85  wxASSERT( aOutT );
86  wxASSERT( aNormalOut );
87 
89  return false;
90 
91  float currentRayDist;
92  SFVEC2F currentRayPos;
93  SFVEC2F currentNormal;
94 
95  if( m_objectA->IsPointInside( aSegRay.m_Start ) )
96  {
97  // start ray point off where it is now (at the origin)
98  currentRayDist = 0.0f;
99  currentRayPos = aSegRay.m_Start;
100  }
101  else
102  {
103  //move ray point to start of main object
104  if( !m_objectA->Intersect( aSegRay, &currentRayDist, &currentNormal ) )
105  return false;
106 
107  currentRayPos = aSegRay.atNormalized( NextFloatDown( currentRayDist ) );
108  }
109 
110  //wxASSERT( (currentRayDist >= 0.0f) && (currentRayDist <= 1.0f) );
111 
112 
113  // move through the union of subtracted regions
114  bool hitSubRegion = false;
115 
116  if( m_objectB )
117  {
118  while(1)
119  {
120  bool wasInsideSubVol = false;
121 
122  //check against all subbed objects
123  for( unsigned int i = 0; i < m_objectB->size(); ++i )
124  {
125  if( ((const COBJECT2D *)(*m_objectB)[i])->IsPointInside( currentRayPos ) )
126  {
127  hitSubRegion = true;
128 
129  // ray point is inside a subtracted region, so move it to the end of the
130  // subtracted region
131  float hitDist;
132  if( !((const COBJECT2D *)(*m_objectB)[i])->Intersect( aSegRay,
133  &hitDist,
134  &currentNormal ) )
135  return false; // ray hit main object but did not leave subtracted volume
136 
137  wxASSERT( hitDist <= 1.0f );
138 
139  if( hitDist > currentRayDist )
140  currentRayDist = hitDist;
141 
142  currentRayDist += 0.0001f;
143 
144  // ray has left this specific subtracted object volume
145  currentRayPos = aSegRay.atNormalized( currentRayDist );
146 
147  if( m_objectA->IsPointInside( currentRayPos ) )
148  {
149  wasInsideSubVol = true;
150 
151  break;
152  }
153  }
154  }
155 
156  if( !wasInsideSubVol )
157  break; // ray has succesfully passed through all subtracted regions
158 
159  if( currentRayDist >= 1.0f )
160  break;
161  }
162  }
163 
164  //ray is not inside any of the specific subtracted regions
165 
166  if( hitSubRegion )
167  {
168  //if( !m_objectA->IsPointInside( currentRayPos ) )
169  // return false; // ray got right through the hole in the object!
170 
171  currentNormal *= -1.0f;
172  }
173  else
174  {
175  //ray just hit the main object without hitting any holes
176  }
177 
178  *aNormalOut = currentNormal;
179  *aOutT = currentRayDist;
180 
181  return true;
182 }
183 
184 
186 {
187 
188  // !TODO:
189 
190  return INTR_MISSES;
191 }
192 
193 
194 bool CITEMLAYERCSG2D::IsPointInside( const SFVEC2F &aPoint ) const
195 {
196  // Perform the operation (A - B) /\ C
197 
198  if( m_objectA->IsPointInside( aPoint ) )
199  {
200 
201  if( m_objectB != CSGITEM_EMPTY)
202  for( unsigned int i = 0; i< m_objectB->size(); i++ )
203  {
204  if( (*m_objectB)[i]->IsPointInside( aPoint ) )
205  return false;
206  }
207 
208  // !TODO: not yet implemented
209  //if( m_objectC && m_objectC != CSGITEM_FULL )
210  // return m_objectC->IsPointInside( aPoint );
211 
212  return true;
213  }
214 
215  return false;
216 }
INTERSECTION_RESULT
Definition: cobject2d.h:38
bool IsInitialized() const
Function IsInitialized check if this bounding box is already initialized.
Definition: cbbox2d.cpp:79
Defines math related functions.
std::vector< const COBJECT2D * > * m_objectB
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
const COBJECT2D * m_objectA
Class CBBOX manages a bounding box defined by two SFVEC2F min max points.
Definition: cbbox2d.h:40
virtual bool Intersect(const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut) const =0
Function Intersect.
bool Intersects(const CBBOX2D &aBBox) const override
Function Intersects.
#define CSGITEM_EMPTY
This class is used to make constructive solig geometry for items objects on layers.
bool Intersects(const CBBOX2D &aBBox) const
Function Intersects test if a bounding box intersects this box.
Definition: cbbox2d.cpp:213
void Reset()
Function Reset reset the bounding box to zero and de-initialized it.
Definition: cbbox2d.cpp:88
glm::vec2 SFVEC2F
Definition: xv3d_types.h:45
float NextFloatDown(float v)
Definition: 3d_fastmath.h:157
CITEMLAYERCSG2D(const COBJECT2D *aObjectA, std::vector< const COBJECT2D * > *aObjectB, const COBJECT2D *aObjectC, const BOARD_ITEM &aBoardItem)
void Set(const SFVEC2F &aPbMin, const SFVEC2F &aPbMax)
Function Set Set bounding box with new parameters.
Definition: cbbox2d.cpp:61
OBJECT2D_TYPE GetObjectType() const
Definition: cobject2d.h:125
#define CSGITEM_FULL
bool Intersect(const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut) const override
Function Intersect.
SFVEC2F atNormalized(float t) const
Function atNormalized - returns the position at t t - value 0.0 ...
Definition: ray.h:115
void ScaleNextUp()
Function ScaleNextUp scales a bounding box to the next float representation making it larger...
Definition: cbbox2d.cpp:164
CBBOX2D m_bbox
Definition: cobject2d.h:65
bool IsPointInside(const SFVEC2F &aPoint) const override
SFVEC2F GetCenter() const
Function GetCenter return the center point of the bounding box.
Definition: cbbox2d.cpp:121
SFVEC2F m_Start
Definition: ray.h:88
SFVEC2F m_centroid
Definition: cobject2d.h:66
bool Overlaps(const CBBOX2D &aBBox) const override
Function Overlaps.
const CBBOX2D & GetBBox() const
Definition: cobject2d.h:121
virtual bool IsPointInside(const SFVEC2F &aPoint) const =0
INTERSECTION_RESULT IsBBoxInside(const CBBOX2D &aBBox) const override
Function IsBBoxInside.
Definition: ray.h:86