KiCad PCB EDA Suite
cylinder_3d.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 <[email protected]>
5  * Copyright (C) 1992-2020 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 "3d_fastmath.h"
31 #include "cylinder_3d.h"
32 
33 
34 CYLINDER::CYLINDER( SFVEC2F aCenterPoint, float aZmin, float aZmax, float aRadius )
36 {
37  m_center = aCenterPoint;
38  m_radius_squared = aRadius * aRadius;
39  m_inv_radius = 1.0f / aRadius;
40 
41  m_bbox.Set( SFVEC3F( aCenterPoint.x - aRadius, aCenterPoint.y - aRadius, aZmin ),
42  SFVEC3F( aCenterPoint.x + aRadius, aCenterPoint.y + aRadius, aZmax ) );
45 }
46 
47 
48 bool CYLINDER::Intersect( const RAY& aRay, HITINFO& aHitInfo ) const
49 {
50  // Based on: http://www.cs.utah.edu/~lha/Code%206620%20/Ray4/Cylinder.cpp
51  // Ray-sphere intersection: geometric
52  const double OCx_Start = aRay.m_Origin.x - m_center.x;
53  const double OCy_Start = aRay.m_Origin.y - m_center.y;
54 
55  const double p_dot_p = OCx_Start * OCx_Start + OCy_Start * OCy_Start;
56 
57  const double a = (double)aRay.m_Dir.x * (double)aRay.m_Dir.x +
58  (double)aRay.m_Dir.y * (double)aRay.m_Dir.y;
59  const double b = (double)aRay.m_Dir.x * (double)OCx_Start +
60  (double)aRay.m_Dir.y * (double)OCy_Start;
61  const double c = p_dot_p - m_radius_squared;
62 
63  const float delta = (float) ( b * b - a * c );
64 
65  bool hitResult = false;
66 
67  if( delta > FLT_EPSILON )
68  {
69  const float inv_a = 1.0 / a;
70 
71  const float sdelta = sqrtf( delta );
72  const float t = (-b - sdelta) * inv_a;
73  const float z = aRay.m_Origin.z + t * aRay.m_Dir.z;
74 
75  if( ( z >= m_bbox.Min().z ) && ( z <= m_bbox.Max().z ) )
76  {
77  if( t < aHitInfo.m_tHit )
78  {
79  hitResult = true;
80  aHitInfo.m_tHit = t;
81  }
82  }
83 
84  if( !hitResult )
85  {
86  const float t1 = (-b + sdelta) * inv_a;
87  const float z1 = aRay.m_Origin.z + t1 * aRay.m_Dir.z;
88 
89  if( ( z1 > m_bbox.Min().z ) && ( z1 < m_bbox.Max().z ) )
90  {
91  if( t1 < aHitInfo.m_tHit )
92  {
93  hitResult = true;
94  aHitInfo.m_tHit = t1;
95  }
96  }
97  }
98  }
99 
100  if( hitResult )
101  {
102  aHitInfo.m_HitPoint = aRay.at( aHitInfo.m_tHit );
103 
104  const SFVEC2F hitPoint2D = SFVEC2F( aHitInfo.m_HitPoint.x, aHitInfo.m_HitPoint.y );
105 
106  aHitInfo.m_HitNormal = SFVEC3F( -( hitPoint2D.x - m_center.x ) * m_inv_radius,
107  -( hitPoint2D.y - m_center.y ) * m_inv_radius, 0.0f );
108 
109  m_material->Generate( aHitInfo.m_HitNormal, aRay, aHitInfo );
110 
111  aHitInfo.pHitObject = this;
112  }
113 
114  return hitResult;
115 }
116 
117 
118 bool CYLINDER::IntersectP(const RAY& aRay , float aMaxDistance ) const
119 {
120  // Based on: http://www.cs.utah.edu/~lha/Code%206620%20/Ray4/Cylinder.cpp
121  // Ray-sphere intersection: geometric
122  const double OCx_Start = aRay.m_Origin.x - m_center.x;
123  const double OCy_Start = aRay.m_Origin.y - m_center.y;
124 
125  const double p_dot_p = OCx_Start * OCx_Start + OCy_Start * OCy_Start;
126 
127  const double a = (double)aRay.m_Dir.x * (double)aRay.m_Dir.x +
128  (double)aRay.m_Dir.y * (double)aRay.m_Dir.y;
129  const double b = (double)aRay.m_Dir.x * (double)OCx_Start +
130  (double)aRay.m_Dir.y * (double)OCy_Start;
131  const double c = p_dot_p - m_radius_squared;
132 
133  const float delta = (float) ( b * b - a * c );
134 
135  if( delta > FLT_EPSILON )
136  {
137  const float inv_a = 1.0 / a;
138 
139  const float sdelta = sqrtf( delta );
140  const float t = ( -b - sdelta ) * inv_a;
141  const float z = aRay.m_Origin.z + t * aRay.m_Dir.z;
142 
143  if( ( z >= m_bbox.Min().z ) && ( z <= m_bbox.Max().z ) )
144  {
145  if( t < aMaxDistance )
146  return true;
147  }
148 
149  const float t1 = ( -b + sdelta ) * inv_a;
150  const float z1 = aRay.m_Origin.z + t1 * aRay.m_Dir.z;
151 
152  if( ( z1 > m_bbox.Min().z ) && ( z1 < m_bbox.Max().z ) )
153  {
154  if( t1 < aMaxDistance )
155  return true;
156  }
157  }
158 
159  return false;
160 }
161 
162 
163 bool CYLINDER::Intersects( const BBOX_3D& aBBox ) const
164 {
165  // !TODO: improve
166  return m_bbox.Intersects( aBBox );
167 }
168 
169 
170 SFVEC3F CYLINDER::GetDiffuseColor( const HITINFO& /* aHitInfo */ ) const
171 {
172  return m_diffusecolor;
173 }
bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const override
Definition: cylinder_3d.cpp:48
Defines math related functions.
float m_radius_squared
Definition: cylinder_3d.h:57
const SFVEC3F & Max() const
Return the maximum vertex pointer.
Definition: bbox_3d.h:198
CYLINDER(SFVEC2F aCenterPoint, float aZmin, float aZmax, float aRadius)
Definition: cylinder_3d.cpp:34
Manage a bounding box defined by two SFVEC3F min max points.
Definition: bbox_3d.h:41
void Generate(SFVEC3F &aNormal, const RAY &aRay, const HITINFO &aHitInfo) const
Definition: material.cpp:89
bool IntersectP(const RAY &aRay, float aMaxDistance) const override
Definition: ray.h:62
float m_inv_radius
Definition: cylinder_3d.h:58
float m_tHit
( 4) distance
Definition: hitinfo.h:38
SFVEC3F at(float t) const
Definition: ray.h:84
const SFVEC3F & Min() const
Return the minimum vertex pointer.
Definition: bbox_3d.h:191
bool Intersects(const BBOX_3D &aBBox) const override
A vertical cylinder.
Definition: cylinder_3d.h:37
SFVEC3F m_HitPoint
(12) hit position
Definition: hitinfo.h:44
SFVEC3F GetCenter() const
Return the center point of the bounding box.
Definition: bbox_3d.cpp:132
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
BBOX_3D m_bbox
Definition: object_3d.h:97
const MATERIAL * m_material
Definition: object_3d.h:100
const OBJECT_3D * pHitObject
( 4) Object that was hitted
Definition: hitinfo.h:40
SFVEC3F m_Dir
Definition: ray.h:67
void Set(const SFVEC3F &aPbMin, const SFVEC3F &aPbMax)
Set bounding box with new parameters.
Definition: bbox_3d.cpp:68
SFVEC3F m_Origin
Definition: ray.h:64
void ScaleNextUp()
Scale a bounding box to the next float representation making it larger.
Definition: bbox_3d.cpp:194
SFVEC3F m_centroid
Definition: object_3d.h:98
Stores the hit information of a ray with a point on the surface of a object.
Definition: hitinfo.h:35
SFVEC2F m_center
Definition: cylinder_3d.h:56
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
SFVEC3F m_HitNormal
(12) normal at the hit point
Definition: hitinfo.h:37
constexpr int delta
OBJECT_3D_TYPE
Definition: object_3d.h:38
SFVEC3F GetDiffuseColor(const HITINFO &aHitInfo) const override
SFVEC3F m_diffusecolor
Definition: cylinder_3d.h:59
bool Intersects(const BBOX_3D &aBBox) const
Test if a bounding box intersects this box.
Definition: bbox_3d.cpp:218