Mantid
Loading...
Searching...
No Matches
Cone.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7#include <algorithm>
8#include <cmath>
9#include <complex>
10#include <fstream>
11#include <list>
12#include <map>
13#include <sstream>
14#include <stack>
15#include <vector>
16
22#include "MantidKernel/Matrix.h"
25#include "MantidKernel/V3D.h"
26
27#ifdef ENABLE_OPENCASCADE
28// Opencascade defines _USE_MATH_DEFINES without checking whether it is already
29// used.
30// Undefine it here before we include the headers to avoid a warning
31#ifdef _MSC_VER
32#undef _USE_MATH_DEFINES
33#ifdef M_SQRT1_2
34#undef M_SQRT1_2
35#endif
36#endif
37
39GNU_DIAG_OFF("conversion")
40GNU_DIAG_OFF("cast-qual")
41#include <BRepPrimAPI_MakeCone.hxx>
42GNU_DIAG_ON("conversion")
43GNU_DIAG_ON("cast-qual")
44#endif
45
46namespace Mantid::Geometry {
48using Kernel::V3D;
49
51 : Quadratic(), Centre(), Normal(1, 0, 0), alpha(0.0), cangle(1.0)
56{
57 setBaseEqn();
58}
59
65{
66 return new Cone(*this);
67}
68
69std::unique_ptr<Cone> Cone::clone() const { return std::unique_ptr<Cone>(doClone()); }
70
71int Cone::setSurface(const std::string &Pstr)
80{
81 std::string Line = Pstr;
82 std::string item;
83 if (!Mantid::Kernel::Strings::section(Line, item) || tolower(item[0]) != 'k' || item.length() < 2 ||
84 item.length() > 3)
85 return -1;
86
87 // Cones on X/Y/Z axis
88 const std::size_t itemPt((item[1] == '/' && item.length() == 3) ? 2 : 1);
89 const auto ptype = static_cast<std::size_t>(tolower(item[itemPt]) - 'x');
90 if (ptype >= 3)
91 return -2;
92 std::vector<double> norm(3, 0.0);
93 std::vector<double> cent(3, 0.0);
94 norm[ptype] = 1.0;
95
96 if (itemPt == 1) // kx type cone
97 {
98 if (!Mantid::Kernel::Strings::section(Line, cent[ptype]))
99 return -3;
100 } else {
101 std::size_t index;
102 for (index = 0; index < 3 && Mantid::Kernel::Strings::section(Line, cent[index]); index++)
103 ;
104 if (index != 3)
105 return -4;
106 }
107 // The user must enter t^2 which is tan^2(angle) for MCNPX
108 double tanAng;
110 return -5;
111
112 Centre = Kernel::V3D(cent[0], cent[1], cent[2]);
113 Normal = Kernel::V3D(norm[0], norm[1], norm[2]);
114 setTanAngle(sqrt(tanAng));
115 setBaseEqn();
116 return 0;
117}
118
119int Cone::operator==(const Cone &A) const
126{
127 if (this == &A)
128 return 1;
129 if (fabs(cangle - A.cangle) > Tolerance)
130 return 0;
131 if (Centre.distance(A.Centre) > Tolerance)
132 return 0;
133 if (Normal.distance(A.Normal) > Tolerance)
134 return 0;
135
136 return 1;
137}
138
144{
145 const double c2(cangle * cangle);
146 const double CdotN(Centre.scalar_prod(Normal));
147 BaseEqn[0] = c2 - Normal[0] * Normal[0]; // A x^2
148 BaseEqn[1] = c2 - Normal[1] * Normal[1]; // B y^2
149 BaseEqn[2] = c2 - Normal[2] * Normal[2]; // C z^2
150 BaseEqn[3] = -2 * Normal[0] * Normal[1]; // D xy
151 BaseEqn[4] = -2 * Normal[0] * Normal[2]; // E xz
152 BaseEqn[5] = -2 * Normal[1] * Normal[2]; // F yz
153 BaseEqn[6] = 2.0 * (Normal[0] * CdotN - Centre[0] * c2); // G x
154 BaseEqn[7] = 2.0 * (Normal[1] * CdotN - Centre[1] * c2); // H y
155 BaseEqn[8] = 2.0 * (Normal[2] * CdotN - Centre[2] * c2); // J z
156 BaseEqn[9] = c2 * Centre.scalar_prod(Centre) - CdotN * CdotN; // K const
157}
158
164{
165 Centre.rotate(R);
166 Normal.rotate(R);
167 setBaseEqn();
168}
169
176{
177 Centre += A;
178 setBaseEqn();
179}
180
186{
187 Centre = A;
188 setBaseEqn();
189}
190
196{
197 const double norm = A.norm();
198 if (norm > Tolerance) {
199 Normal = A / norm;
200 setBaseEqn();
201 }
202}
203
204void Cone::setAngle(const double A)
210{
211 alpha = A;
212 cangle = cos(M_PI * alpha / 180.0);
213 setBaseEqn();
214}
215
216void Cone::setTanAngle(const double A)
222{
223 cangle = 1.0 / sqrt(A * A + 1.0); // convert tan(theta) to cos(theta)
224 alpha = acos(cangle) * 180.0 / M_PI;
225 setBaseEqn();
226}
227
228double Cone::distance(const Kernel::V3D &Pt) const
239{
240 const Kernel::V3D Px = Pt - Centre;
241 // test is the centre to point distance is zero
242 if (Px.norm() < Tolerance)
243 return Px.norm();
244 double Pangle = Px.scalar_prod(Normal) / Px.norm();
245 if (Pangle < 0.0)
246 Pangle = acos(-Pangle);
247 else
248 Pangle = acos(Pangle);
249
250 Pangle -= M_PI * alpha / 180.0;
251 return Px.norm() * sin(Pangle);
252}
253
264int Cone::side(const Kernel::V3D &R) const {
265
266 const Kernel::V3D cR = R - Centre;
267 double rptAngle = cR.scalar_prod(Normal);
268 rptAngle *= rptAngle / cR.scalar_prod(cR);
269 const double eqn(sqrt(rptAngle));
270 if (fabs(eqn - cangle) < Tolerance)
271 return 0;
272 return (eqn > cangle) ? 1 : -1;
273}
274
282bool Cone::onSurface(const Kernel::V3D &R) const {
283
284 const Kernel::V3D cR = R - Centre;
285 double rptAngle = cR.scalar_prod(Normal);
286 rptAngle *= rptAngle / cR.scalar_prod(cR);
287 const double eqn(sqrt(rptAngle));
288
289 return (std::abs(eqn - cangle) <= Tolerance);
290}
291
292void Cone::write(std::ostream &OX) const
298{
299 // -3 -2 -1 0 1 2 3
300 const char Tailends[] = "zyx xyz";
301 const int Ndir = Normal.masterDir(Tolerance);
302 if (Ndir == 0) {
304 return;
305 }
306 std::ostringstream cx;
308
309 const int Cdir = Centre.masterDir(Tolerance);
310 cx.precision(Surface::Nprecision);
311 // Name and transform
312
313 if (Cdir || Centre.nullVector(Tolerance)) {
314 cx << " k";
315 cx << Tailends[Ndir + 3] << " "; // set x,y,z based on Ndir
316 cx << ((Cdir > 0) ? Centre[static_cast<std::size_t>(Cdir - 1)] : Centre[static_cast<std::size_t>(-Cdir - 1)]);
317 cx << " ";
318 } else {
319 cx << " k/";
320 cx << Tailends[Ndir + 3] << " "; // set x,y,z based on Ndir
321 for (std::size_t i = 0; i < 3; i++)
322 cx << Centre[i] << " ";
323 }
324 const double TA = tan((M_PI * alpha) / 180.0); // tan^2(angle)
325 cx << TA * TA;
327}
328
329void Cone::getBoundingBox(double &xmax, double &ymax, double &zmax, double &xmin, double &ymin, double &zmin) {
344
345 if (Normal.X() != 0 && Normal.Y() == 0 && Normal.Z() == 0) {
346 if (Normal.X() < 0) {
347 xmin = std::max(Centre.X(), ymin);
348 } else {
349 xmax = std::min(Centre.X(), ymax);
350 }
351 double radius = fabs(xmax - xmin) * sin((M_PI * alpha) / 180.0);
352 ymin = Centre.Y() - radius;
353 ymax = Centre.Y() + radius;
354 zmin = Centre.Z() - radius;
355 zmax = Centre.Z() + radius;
356 } else if (Normal.X() == 0 && Normal.Y() != 0 && Normal.Z() == 0) {
357 if (Normal.Y() < 0) {
358 ymin = std::max(Centre.Y(), ymin);
359 } else {
360 ymax = std::min(Centre.Y(), ymax);
361 }
362 double radius = fabs(ymax - ymin) * sin((M_PI * alpha) / 180.0);
363 xmin = Centre.X() - radius;
364 xmax = Centre.X() + radius;
365 zmin = Centre.Z() - radius;
366 zmax = Centre.Z() + radius;
367 } else if (Normal.X() == 0 && Normal.Y() == 0 && Normal.Z() != 0) {
368 if (Normal.Z() < 0) {
369 zmin = std::max(Centre.Z(), ymin);
370 } else {
371 zmax = std::min(Centre.Z(), ymax);
372 }
373 double radius = fabs(zmax - zmin) * sin((M_PI * alpha) / 180.0);
374 xmin = Centre.X() - radius;
375 xmax = Centre.X() + radius;
376 ymin = Centre.Y() - radius;
377 ymax = Centre.Y() + radius;
378 }
379}
380
381#ifdef ENABLE_OPENCASCADE
382TopoDS_Shape Cone::createShape() {
383 gp_Ax2 gpA(gp_Pnt(Centre[0], Centre[1], Centre[2]), gp_Dir(Normal[0], Normal[1], Normal[2]));
384 return BRepPrimAPI_MakeCone(gpA, 0.0, 1000.0 / tan(acos(cangle * M_PI / 180.0)), 1000.0, 2.0 * M_PI).Shape();
385}
386#endif
387} // namespace Mantid::Geometry
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define fabs(x)
Definition: Matrix.cpp:22
double radius
Definition: Rasterize.cpp:31
#define GNU_DIAG_ON(x)
#define GNU_DIAG_OFF(x)
This is a collection of macros for turning compiler warnings off in a controlled manner.
Holds a cone in vector form.
Definition: Cone.h:29
int setSurface(const std::string &) override
This method sets the cone surface using the input string in MCNPx format.
Definition: Cone.cpp:71
Kernel::V3D Normal
Normal.
Definition: Cone.h:32
int side(const Kernel::V3D &R) const override
Calculate if the point R is within the cone (return -1) or outside (return 1)
Definition: Cone.cpp:264
Kernel::V3D Centre
Kernel::V3D for centre.
Definition: Cone.h:31
bool onSurface(const Kernel::V3D &R) const override
Calculate if the point R is on the cone.
Definition: Cone.cpp:282
std::unique_ptr< Cone > clone() const
Definition: Cone.cpp:69
void write(std::ostream &) const override
This method will write the cone equation in MCNP geometry format.
Definition: Cone.cpp:292
void setNorm(const Kernel::V3D &)
This method sets the cone normal.
Definition: Cone.cpp:191
void setAngle(double const)
This method sets the angle of the cone.
Definition: Cone.cpp:204
double alpha
Angle (degrees)
Definition: Cone.h:33
void getBoundingBox(double &xmax, double &ymax, double &zmax, double &xmin, double &ymin, double &zmin) override
This will get the bounding box for the cone.
Definition: Cone.cpp:329
void setTanAngle(double const)
This method sets the tan angle which will be converted to cos used for MCNPX format.
Definition: Cone.cpp:216
void setBaseEqn() override
This method generates the quadratic equation for cone.
Definition: Cone.cpp:139
double cangle
Cos(angle)
Definition: Cone.h:34
int operator==(const Cone &) const
Equality operator.
Definition: Cone.cpp:119
Cone()
Constructor with centre line along X axis and centre on origin.
Definition: Cone.cpp:50
void rotate(const Kernel::Matrix< double > &) override
Rotate both the centre and the normal direction.
Definition: Cone.cpp:159
void setCentre(const Kernel::V3D &)
This method sets the centre of the cone.
Definition: Cone.cpp:181
void displace(const Kernel::V3D &) override
Displace the centre Only need to update the centre position.
Definition: Cone.cpp:170
double distance(const Kernel::V3D &) const override
This method returns the distance of the point from the cone.
Definition: Cone.cpp:228
Cone * doClone() const override
Makes a clone (implicit virtual copy constructor)
Definition: Cone.cpp:60
Impliments a line.
Definition: Line.h:43
Holds a basic quadratic surface.
Definition: Quadratic.h:29
std::vector< double > BaseEqn
Base equation (as a 10 point vector)
Definition: Quadratic.h:35
void write(std::ostream &) const override
Writes out an MCNPX surface description Note : Swap since base equation is swapped in gq output (mcnp...
Definition: Quadratic.cpp:310
void writeHeader(std::ostream &) const
Writes out the start of an MCNPX surface description .
Definition: Surface.cpp:71
static const int Nprecision
Precision of the output.
Definition: Surface.h:41
Numerical Matrix class.
Definition: Matrix.h:42
Class for 3D vectors.
Definition: V3D.h:34
constexpr double scalar_prod(const V3D &v) const noexcept
Calculates the cross product.
Definition: V3D.h:274
constexpr double X() const noexcept
Get x.
Definition: V3D.h:232
constexpr double Y() const noexcept
Get y.
Definition: V3D.h:233
void rotate(const Matrix< double > &) noexcept
Rotate a point by a matrix.
Definition: V3D.cpp:217
double norm() const noexcept
Definition: V3D.h:263
constexpr double Z() const noexcept
Get z.
Definition: V3D.h:234
int section(std::string &A, T &out)
Convert and cut a string.
Definition: Strings.cpp:573
MANTID_KERNEL_DLL void writeMCNPX(const std::string &Line, std::ostream &OX)
Write file in standard MCNPX input form.
Definition: Strings.cpp:421
constexpr double Tolerance
Standard tolerance value.
Definition: Tolerance.h:12