Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
REveShape.cxx
Go to the documentation of this file.
1 // @(#)root/eve7:$Id$
2 // Author: Matevz Tadel, 2010
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include <ROOT/REveShape.hxx>
13 #include "Riostream.h"
14 
15 #include "json.hpp"
16 
17 
18 using namespace ROOT::Experimental;
19 namespace REX = ROOT::Experimental;
20 
21 /** \class REveShape
22 \ingroup REve
23 Abstract base-class for 2D/3D shapes.
24 
25 It provides:
26  - fill color / transparency, accessible via Get/SetMainColor/Transparency;
27  - frame line color / width;
28  - flag if frame should be drawn;
29  - flag specifying whether frame or whole shape should be emphasised for
30  highlight.
31 */
32 
33 ////////////////////////////////////////////////////////////////////////////////
34 /// Constructor.
35 
36 REveShape::REveShape(const std::string &n, const std::string &t) :
37  REveElement(n, t),
38  fFillColor(5),
39  fLineColor(5),
40  fLineWidth(1),
41  fDrawFrame(kTRUE),
42  fHighlightFrame(kFALSE),
43  fMiniFrame(kTRUE)
44 {
45  fCanEditMainColor = kTRUE;
46  fCanEditMainTransparency = kTRUE;
47  SetMainColorPtr(&fFillColor);
48 }
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 /// Destructor.
52 
53 REveShape::~REveShape()
54 {
55 }
56 
57 ////////////////////////////////////////////////////////////////////////////////
58 /// Fill core part of JSON representation.
59 
60 Int_t REveShape::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset)
61 {
62  Int_t ret = REveElement::WriteCoreJson(j, rnr_offset);
63 
64  j["fFillColor"] = fFillColor;
65  j["fLineColor"] = fLineColor;
66  j["fLineWidth"] = fLineWidth;
67  j["fDrawFrame"] = fDrawFrame;
68 
69  return ret;
70 }
71 
72 ////////////////////////////////////////////////////////////////////////////////
73 /// Set main color.
74 /// Override so that line-color can also be changed if it is equal
75 /// to fill color (which is treated as main color).
76 
77 void REveShape::SetMainColor(Color_t color)
78 {
79  if (fFillColor == fLineColor) {
80  fLineColor = color;
81  StampObjProps();
82  }
83  REveElement::SetMainColor(color);
84 }
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 /// Copy visualization parameters from element el.
88 
89 void REveShape::CopyVizParams(const REveElement* el)
90 {
91  const REveShape* m = dynamic_cast<const REveShape*>(el);
92  if (m)
93  {
94  fFillColor = m->fFillColor;
95  fLineColor = m->fLineColor;
96  fLineWidth = m->fLineWidth;
97  fDrawFrame = m->fDrawFrame;
98  fHighlightFrame = m->fHighlightFrame;
99  fMiniFrame = m->fMiniFrame;
100  }
101 
102  REveElement::CopyVizParams(el);
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 /// Write visualization parameters.
107 
108 void REveShape::WriteVizParams(std::ostream& out, const TString& var)
109 {
110  REveElement::WriteVizParams(out, var);
111 
112  TString t = " " + var + "->";
113  out << t << "SetFillColor(" << fFillColor << ");\n";
114  out << t << "SetLineColor(" << fLineColor << ");\n";
115  out << t << "SetLineWidth(" << fLineWidth << ");\n";
116  out << t << "SetDrawFrame(" << ToString(fDrawFrame) << ");\n";
117  out << t << "SetHighlightFrame(" << ToString(fHighlightFrame) << ");\n";
118 }
119 
120 ////////////////////////////////////////////////////////////////////////////////
121 /// Determines the convex-hull of points in pin.
122 ///
123 /// Adds the hull points to pout and returns the number of added points.
124 /// If size of pout is less then 3 then either the number of input points
125 /// was too low or they were degenerate so that the hull is actually a line
126 /// segment or even a point.
127 
128 Int_t REveShape::FindConvexHull(const vVector2_t& pin, vVector2_t& pout, REveElement* caller)
129 {
130  Int_t N = pin.size();
131 
132  // Find the minimum (bottom-left) point.
133  Int_t min_point = 0;
134  for (Int_t i = 1; i < N; ++i)
135  {
136  if (pin[i].fY < pin[min_point].fY || (pin[i].fY == pin[min_point].fY && pin[i].fX < pin[min_point].fX))
137  min_point = i;
138  }
139 
140  // Calculate angles and sort.
141  std::vector<Float_t> angles(N);
142  for (Int_t i = 0; i < N; ++i)
143  {
144  angles[i] = (pin[i] - pin[min_point]).Phi();
145  }
146  std::vector<Int_t> idcs(N);
147  TMath::Sort(N, &angles[0], &idcs[0], kFALSE);
148 
149  // Weed out points with the same angle -- keep the furthest only.
150  // The first point must stay.
151  if (N > 2)
152  {
153  std::vector<Int_t> new_idcs;
154  new_idcs.push_back(idcs[0]);
155  auto a = idcs.begin(); ++a;
156  auto b = a; ++b;
157  while (b != idcs.end())
158  {
159  if (TMath::Abs(angles[*a] - angles[*b]) < 1e-5f)
160  {
161  if (pin[idcs[0]].SquareDistance(pin[*a]) < pin[idcs[0]].SquareDistance(pin[*b]))
162  a = b;
163  }
164  else
165  {
166  new_idcs.push_back(*a);
167  a = b;
168  }
169  ++b;
170  }
171  new_idcs.push_back(*a);
172  idcs.swap(new_idcs);
173  }
174 
175  N = idcs.size();
176 
177  // Find hull.
178  std::vector<Int_t> hull;
179  if (N > 2)
180  {
181  hull.push_back(idcs[0]);
182  hull.push_back(idcs[1]);
183  hull.push_back(idcs[2]);
184  {
185  Int_t i = 3;
186  while (i < N)
187  {
188  Int_t n = hull.size() - 1;
189  if ((pin[hull[n]] - pin[hull[n-1]]).Cross(pin[idcs[i]] - pin[hull[n]]) > 0)
190  {
191  hull.push_back(idcs[i]);
192  ++i;
193  }
194  else
195  {
196  hull.pop_back();
197  }
198  }
199  }
200  }
201  else
202  {
203  ::Warning("REveShape::FindConvexHull()", "Polygon reduced to %d points. for '%s'.",
204  N, caller ? caller->GetCName() : "unknown");
205  hull.swap(idcs);
206  }
207 
208  // Add hull points into the output vector.
209  N = hull.size();
210  Int_t Nold = pout.size();
211  pout.resize(Nold + N);
212  for (Int_t i = 0; i < N; ++i)
213  {
214  pout[Nold + i] = pin[hull[i]];
215  }
216 
217  // Print the hull.
218  // for (Int_t i = 0; i < N; ++i)
219  // {
220  // const REveVector2 &p = pin[hull[i]];
221  // printf("%d [%d] (%5.1f, %5.1f) %f\n", i, hull[i], p.fX, p.fY, angles[hull[i]]);
222  // }
223 
224  return N;
225 }
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 /// Checks if the first face normal is pointing into the other
229 /// direction as the vector pointing towards the opposite face.
230 /// This assumes standard box vertex arrangement.
231 
232 Bool_t REveShape::IsBoxOrientationConsistentEv(const REveVector box[8])
233 {
234  REveVector f1 = box[1] - box[0];
235  REveVector f2 = box[3] - box[0];
236  REveVector up = box[4] - box[0];
237 
238  return up.Dot(f1.Cross(f2)) < 0;
239 }
240 
241 ////////////////////////////////////////////////////////////////////////////////
242 /// Checks if the first face normal is pointing into the other
243 /// direction as the vector pointing towards the opposite face.
244 /// This assumes standard box vertex arrangement.
245 
246 Bool_t REveShape::IsBoxOrientationConsistentFv(const Float_t box[8][3])
247 {
248  REveVector b0(box[0]);
249  REveVector f1(box[1]); f1 -= b0;
250  REveVector f2(box[3]); f2 -= b0;
251  REveVector up(box[4]); up -= b0;
252 
253  return up.Dot(f1.Cross(f2)) < 0;
254 }
255 
256 ////////////////////////////////////////////////////////////////////////////////
257 /// Make sure box orientation is consistent with standard arrangement.
258 
259 void REveShape::CheckAndFixBoxOrientationEv(REveVector box[8])
260 {
261  if ( ! IsBoxOrientationConsistentEv(box))
262  {
263  std::swap(box[1], box[3]);
264  std::swap(box[5], box[7]);
265  }
266 }
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 /// Make sure box orientation is consistent with standard arrangement.
270 
271 void REveShape::CheckAndFixBoxOrientationFv(Float_t box[8][3])
272 {
273  if ( ! IsBoxOrientationConsistentFv(box))
274  {
275  std::swap(box[1][0], box[3][0]);
276  std::swap(box[1][1], box[3][1]);
277  std::swap(box[1][2], box[3][2]);
278  std::swap(box[5][0], box[7][0]);
279  std::swap(box[5][1], box[7][1]);
280  std::swap(box[5][2], box[7][2]);
281  }
282 }