24#include "G4QuadrangularFacet.hh"
25#include "G4TessellatedSolid.hh"
26#include "G4TriangularFacet.hh"
30const int Geant4GM::Arb8::fgkNofVertices = 8;
31const double Geant4GM::Arb8::fgkTolerance = 1E-3;
41 double dx1, dy1, dx2, dy2;
42 int nv = fgkNofVertices / 2;
43 for (
int i = 0; i < 4; i++) {
45 dx1 = vertices[(i + 1) % nv].first - vertices[i].first;
46 dy1 = vertices[(i + 1) % nv].second - vertices[i].second;
47 if (dx1 == 0 && dy1 == 0)
continue;
49 dx2 = vertices[nv + (i + 1) % nv].first - vertices[nv + i].first;
50 dy2 = vertices[nv + (i + 1) % nv].second - vertices[nv + i].second;
51 if (dx2 == 0 && dy2 == 0)
continue;
53 if (fabs(dy1 * dx2 - dx1 * dy2) < fgkTolerance)
continue;
62 const std::string& name,
double hz, std::vector<VGM::TwoVector> vertices)
92 std::cerr <<
"+++ Error +++" << std::endl;
93 std::cerr <<
" Twisted Arb8 is not supported " << std::endl;
98 G4int nv = fgkNofVertices / 2;
99 std::vector<G4ThreeVector> downVertices;
100 for (G4int i = 0; i < nv; i++)
101 downVertices.push_back(
106 std::vector<G4ThreeVector> upVertices;
107 for (G4int i = nv; i < 2 * nv; i++)
108 upVertices.push_back(
114 G4ThreeVector cross = (downVertices[1] - downVertices[0])
115 .cross(downVertices[2] - downVertices[1]);
116 if (cross.z() > 0.0) {
117 ReorderVertices(downVertices);
118 ReorderVertices(upVertices);
121 fTessellatedSolid =
new G4TessellatedSolid(name);
124 facet = MakeDownFacet(downVertices, 0, 1, 2);
125 if (facet) fTessellatedSolid->AddFacet(facet);
127 facet = MakeDownFacet(downVertices, 0, 2, 3);
128 if (facet) fTessellatedSolid->AddFacet(facet);
130 facet = MakeUpFacet(upVertices, 0, 2, 1);
131 if (facet) fTessellatedSolid->AddFacet(facet);
133 facet = MakeUpFacet(upVertices, 0, 3, 2);
134 if (facet) fTessellatedSolid->AddFacet(facet);
137 for (G4int i = 0; i < nv; ++i) {
138 G4int j = (i + 1) % nv;
139 facet = MakeSideFacet(
140 downVertices[j], downVertices[i], upVertices[i], upVertices[j]);
142 if (facet) fTessellatedSolid->AddFacet(facet);
145 fTessellatedSolid->SetSolidClosed(
true);
184void Geant4GM::Arb8::ReorderVertices(std::vector<G4ThreeVector>& vertices)
188 std::vector<G4ThreeVector> oldVertices(vertices);
190 for (
unsigned int i = 0; i < oldVertices.size(); ++i) {
191 vertices[i] = oldVertices[oldVertices.size() - 1 - i];
196G4VFacet* Geant4GM::Arb8::MakeDownFacet(
197 std::vector<G4ThreeVector> fromVertices,
int ind1,
int ind2,
int ind3)
const
203 if (fromVertices[ind1] == fromVertices[ind2] ||
204 fromVertices[ind2] == fromVertices[ind3] ||
205 fromVertices[ind1] == fromVertices[ind3])
208 std::vector<G4ThreeVector> vertices;
209 vertices.push_back(fromVertices[ind1]);
210 vertices.push_back(fromVertices[ind2]);
211 vertices.push_back(fromVertices[ind3]);
215 G4ThreeVector cross =
216 (vertices[1] - vertices[0]).cross(vertices[2] - vertices[1]);
218 if (cross.z() > 0.0) {
221 std::cerr <<
" Geant4GM::Arb8::MakeDownFacet:" << std::endl;
222 std::cerr <<
" Vertices in wrong order." << std::endl;
223 std::cerr <<
"*** Error: Aborting execution ***" << std::endl;
227 return new G4TriangularFacet(vertices[0], vertices[1], vertices[2], ABSOLUTE);
231G4VFacet* Geant4GM::Arb8::MakeUpFacet(
232 std::vector<G4ThreeVector> fromVertices,
int ind1,
int ind2,
int ind3)
const
238 if (fromVertices[ind1] == fromVertices[ind2] ||
239 fromVertices[ind2] == fromVertices[ind3] ||
240 fromVertices[ind1] == fromVertices[ind3])
243 std::vector<G4ThreeVector> vertices;
244 vertices.push_back(fromVertices[ind1]);
245 vertices.push_back(fromVertices[ind2]);
246 vertices.push_back(fromVertices[ind3]);
250 G4ThreeVector cross =
251 (vertices[1] - vertices[0]).cross(vertices[2] - vertices[1]);
253 if (cross.z() < 0.0) {
256 std::cerr <<
" Geant4GM::Arb8::MakeUpFacet:" << std::endl;
257 std::cerr <<
" Vertices in wrong order." << std::endl;
258 std::cerr <<
"*** Error: Aborting execution ***" << std::endl;
262 return new G4TriangularFacet(vertices[0], vertices[1], vertices[2], ABSOLUTE);
266G4VFacet* Geant4GM::Arb8::MakeSideFacet(G4ThreeVector downVertex0,
267 G4ThreeVector downVertex1, G4ThreeVector upVertex1,
268 G4ThreeVector upVertex0)
const
273 if (downVertex0 == downVertex1 && upVertex0 == upVertex1)
return 0;
275 if (downVertex0 == downVertex1)
276 return new G4TriangularFacet(downVertex0, upVertex1, upVertex0, ABSOLUTE);
278 if (upVertex0 == upVertex1)
279 return new G4TriangularFacet(downVertex0, downVertex1, upVertex0, ABSOLUTE);
281 return new G4QuadrangularFacet(
282 downVertex0, downVertex1, upVertex1, upVertex0, ABSOLUTE);
288 return fTessellatedSolid->GetName();
297 if (index < 0 || index >= NofVertices()) {
298 std::cerr <<
"+++ Error +++" << std::endl;
299 std::cerr <<
" Wrong vertex index: " << index << std::endl;
303 return fVertices[index];
311 if (index < 0 || index >= 4) {
312 std::cerr <<
"+++ Error +++" << std::endl;
313 std::cerr <<
" Wrong twist angle index: " << index << std::endl;
static double Length()
Return CLHEP default length unit in VGM units.
VGM implementation for Geant4 Arb8 solid, the shape is implemented using G4TessellatedSolid.
static bool IsTwisted(std::vector< VGM::TwoVector > vertices)
virtual int NofVertices() const
Return the number of vertices.
virtual double ZHalfLength() const
Return the half-length along the z axis in mm.
virtual VGM::TwoVector Vertex(int index) const
Return the index-th vertex.
virtual double TwistAngle(int index) const
Return the index-th twist angle.
virtual std::string Name() const
Return the name of this solid.
static SolidMap * Instance()
void AddSolid(VGM::ISolid *, G4VSolid *)
std::pair< double, double > TwoVector