HSelectionSetOOC.h
1 // Copyright (c) Tech Soft 3D, Inc.
2 //
3 // The information contained herein is confidential and proprietary to Tech Soft 3D, Inc.,
4 // and considered a trade secret as defined under civil and criminal statutes.
5 // Tech Soft 3D, Inc. shall pursue its civil and criminal remedies in the event of
6 // unauthorized use or misappropriation of its trade secrets. Use of this information
7 // by anyone other than authorized employees of Tech Soft 3D, Inc. is granted only under
8 // a written non-disclosure agreement, expressly prescribing the scope and manner of such use.
9 
10 #pragma once
11 
12 
13 #ifdef HMFC_STATIC_LIB
14 # error "Code cannot be statically linked."
15 #endif
16 
17 
18 #ifdef H_PACK_8
19 # pragma pack(push)
20 # pragma pack(8)
21 #endif
22 
23 
25 
26 
27 #include "HMutexOOC.h"
28 #include "HSelectionSet.h"
29 #include "HTManager.h"
30 #include "HWindowFilterOOC.h"
31 #include "PointCloudAPI.h"
32 #include <map>
33 #include <vector>
34 
35 
37 
38 
39 #ifdef _WIN32
40 # pragma warning(disable: 4127)
41 #endif
42 
43 
44 #ifndef ASSERT
45 # ifdef NDEBUG
46 # define ASSERT(x) do {} while (false)
47 # else
48 #if _WIN32
49 # define ASSERT(x) ((!(x)) ? __debugbreak() : 1)
50 #else
51 # include <assert.h>
52 # define ASSERT assert
53 #endif
54 # endif
55 #endif
56 
57 
59 
60 
62 protected:
63  static HSelectionSet *& Instance ()
64  {
65  static HSelectionSet * instance = nullptr;
66  return instance;
67  }
68 };
69 
70 
76 template <typename SelectionSet>
77 class HSelectionSetOOC : public SelectionSet, private HSelectionSetHelperBaseOOC, private HTClient {
79  typedef void (HC_CDECL * CallbackFunc)(...);
80 
81 private:
82  enum CallbackType {
83  CallbackType_Invalid,
84 // CallbackType_Populate,
85  CallbackType_Deleted,
86  };
87 
88  struct CallbackKeyInfo {
89  public:
90  CallbackKeyInfo ()
91  : type(CallbackType_Invalid)
92  {}
93 
94  CallbackKeyInfo (HC_KEY key, CallbackType type)
95  : key(key)
96  , type(type)
97  {
98  ASSERT(type != CallbackType_Invalid);
99  }
100 
101  public:
102  HC_KEY key;
103  CallbackType type;
104  };
105 
106 private:
107  HSelectionSetOOC (HBaseView & view, bool deep_select)
108  : SelectionSet(&view)
109  , HTClient(0.01f, HTCS_PeriodicSkip)
110  , filter(deep_select)
111  , callback_key_infos(new VArray<CallbackKeyInfo>())
112  {
113  static bool callback_names_defined = false;
114 
115  static_cast<HSelectionSet *>(static_cast<SelectionSet *>(this)); // Ensure SelectionSet is a valid base class (i.e. it derives from HSelectionSet).
116 
117  {
118  LockGuard lock(selection_mutex);
119 
120  if (!callback_names_defined) {
121 // HC_Define_Callback_Name("ooc_selection_on_populate_key", reinterpret_cast<CallbackFunc>(StaticOnPopulateKey));
122  HC_Define_Callback_Name("ooc_selection_on_deleted_key", reinterpret_cast<CallbackFunc>(StaticOnDeletedKey));
123  callback_names_defined = true;
124  }
125 // HC_Define_System_Options(H_FORMAT_TEXT("populate key callback = ooc_selection_on_populate_key"));
126  HC_Define_System_Options(H_FORMAT_TEXT("deleted key callback = ooc_selection_on_deleted_key"));
127  }
128 
130  }
131 
132  ~HSelectionSetOOC ()
133  {
134  LockGuard lock(selection_mutex);
135 
137 
138  HC_Define_System_Options("no populate key callback");
139  HC_Define_System_Options("no deleted key callback");
140 
141  Reset();
142  delete callback_key_infos;
143 
144  Instance() = nullptr;
145  }
146 
147 public:
154  static HSelectionSetOOC * CreateInstance (HBaseView & view, bool deep_select)
155  {
156  HSelectionSet *& instance = Instance();
157 
158  if (instance == nullptr) {
159  instance = new HSelectionSetOOC(view, deep_select);
160  return static_cast<HSelectionSetOOC *>(instance);
161  }
162  else {
163  ASSERT(false);
164  return nullptr;
165  }
166  }
167 
170  static bool CanCreateInstance ()
171  {
172  return Instance() == nullptr;
173  }
174 
177  virtual void Reset ()
178  {
179  LockGuard lock(selection_mutex);
180 
181  delete callback_key_infos;
182  callback_key_infos = new VArray<CallbackKeyInfo>();
183 
184  filter.ClearWindows();
185  SelectionSet::Reset();
186  }
187 
197  virtual bool DeleteSelection (bool emit_message = false)
198  {
199  using namespace ooc;
200  using namespace ooc::delta;
201  using namespace ooc::query;
202 
203  HBaseView & view = *GetView();
204 
205  bool has_root;
206  HC_Open_Segment_By_Key(view.GetModelKey());{
207  has_root = HC_QShow_Existence("root", "self") > 0;
208  }HC_Close_Segment();
209 
210  if (!has_root) {
211  return SelectionSet::DeleteSelection();
212  }
213 
214  std::map<ooc::NodeHandle, std::vector<int>> handle_to_indices;
215  {
216  QueryIterator it = SelectedPoints();
217  while (true) {
218  QueryIterator::Status status = it.GetStatus();
219  if (status != QueryIterator::Status_Alive) {
220  if (status != QueryIterator::Status_Dead) {
221  ASSERT(false); // replace with appropriate handling code
222  return false;
223  }
224  break;
225  }
226  QueryResult const & res = *it;
227  NodeHandle const & handle = res.GetNodeHandle();
228  int point_index = static_cast<int>(res.GetNodePointIndex());
229  handle_to_indices[handle].push_back(point_index);
230  it.Advance();
231  }
232  }
233 
234  HC_KEY const ooc_root = HC_Create_Segment_Key_By_Key(view.GetModelKey(), "root");
235  Env env;
236  if (!GetEnv(ooc_root, env)) {
237  ASSERT(false); // replace with appropriate handling code
238  return false;
239  }
240  SyncResult sync_res = ooc::delta::SynchronizeWith(env, [&](SyncToken const & sync_token) {
241  using namespace ooc;
242  using namespace ooc::delta;
243 
244  auto const end = handle_to_indices.end();
245  auto it = handle_to_indices.begin();
246  for (; it != end; ++it) {
247  auto & pair = *it;
248  NodeHandle const & handle = pair.first;
249  std::vector<int> & indices = pair.second;
250  ModifyResult result = DeleteSpecificPoints(sync_token, handle, indices.data(), indices.size());
251  if (result != ModifyResult_Success) {
252  ASSERT(false); // replace with appropriate handling code
253  return;
254  }
255  }
256  });
257  if (sync_res != SyncResult_Success) {
258  ASSERT(false); // replace with appropriate handling code
259  return false;
260  }
261 
262  Reset();
263 
264  if (emit_message) {
265  m_pView->EmitDeleteSelectionListMessage();
266  }
267 
268  return true;
269  }
270 
274  void SetDeepSelection (bool deep_select)
275  {
276  LockGuard lock(selection_mutex);
277  Reset();
278  filter = HWindowFilterOOC(deep_select);
279  }
280 
283  ooc::query::QueryIterator SelectedPoints ()
284  {
285  HBaseView & view = *GetView();
286  HC_KEY const ooc_root = HC_Create_Segment_Key_By_Key(view.GetModelKey(), "root");
287  ooc::Env env;
288  if (!ooc::GetEnv(ooc_root, env)) {
289  ASSERT(false); // replace with appropriate handling code
290  return ooc::query::QueryIterator();
291  }
292  return ooc::query::QueryPoints(env, filter);
293  }
294 
305  {
306  bool update_needed = false;
307 
308  std::vector<HC_KEY> seg_keys;
309  seg_keys.resize(1024);
310 
311  while (1) {
312 
313  int n = HC_Inspect_Proxies(seg_keys.data(), (int)seg_keys.size());
314 
315  if (n >= 0)
316  {
317  seg_keys.resize(n);
318  break;
319  }
320  else
321  seg_keys.resize(-n);
322  }
323 
324  if (callback_key_infos->Count() == 0 && seg_keys.empty())
325  return false;
326 
327  LockGuard lock(selection_mutex);
328 
329  HBaseView & view = *GetView();
330 
331  HC_KEY key_path[] = {
332  view.GetViewKey(),
333  view.GetIncludeLinkKey(),
334  };
335 
336  auto process_populate = [&](HC_KEY const segment_key)
337  {
338  ooc::Point min_bounding;
339  ooc::Point max_bounding;
340  HC_Open_Segment_By_Key(segment_key); {
341  HC_Show_Bounding_Cuboid(&min_bounding, &max_bounding);
342  if (!filter.RejectBounding(min_bounding, max_bounding)) {
343  HC_Begin_Contents_Search(".", "shell"); {
344  HC_KEY shell_key;
345  while (HC_Find_Contents(nullptr, &shell_key)) {
346  int point_count;
347  HC_Show_Shell_Size(shell_key, &point_count, nullptr);
348  ooc::Point const * points;
349  HC_Show_Geometry_Pointer(shell_key, "points", &points);
350  std::vector<int> points_to_highlight;
351  for (int i = 0; i < point_count; ++i) {
352  ooc::Point const & point = points[i];
353  if (filter.AcceptPoint(point, static_cast<size_t>(i))) {
354  points_to_highlight.push_back(i);
355  }
356  }
357  if (!points_to_highlight.empty()) {
358  update_needed |= SelectSubentityOOC(
359  shell_key, sizeof(key_path) / sizeof(HC_KEY), key_path,
360  static_cast<int>(points_to_highlight.size()),
361  nullptr, points_to_highlight.data(), nullptr, true);
362  }
363  }
364  }HC_End_Contents_Search();
365  }
366  }HC_Close_Segment();
367  };
368 
369  if (!seg_keys.empty() && filter.HasWindows())
370  {
371  for (auto seg_key : seg_keys)
372  process_populate(seg_key);
373  }
374 
375  // Move data because the following code can modify original collection.
376  VArray<CallbackKeyInfo> * infos = callback_key_infos;
377  callback_key_infos = new VArray<CallbackKeyInfo>();
378 
379  size_t const count = infos->Count();
380  for (size_t i = 0; i < count; ++i) {
381  CallbackKeyInfo const & info = infos->GetData(i);
382  switch (info.type) {
383 // case CallbackType_Populate: {
384 // process_populate(info.key);
385 // } break;
386 
387  case CallbackType_Deleted: {
388  HC_KEY const shell_key = info.key;
389  update_needed |= DeSelectOOC(shell_key, sizeof(key_path) / sizeof(HC_KEY), key_path);
390  } break;
391 
392  default: {
393  ASSERT(false);
394  }
395  }
396  }
397 
398  delete infos;
399 
400  return update_needed;
401  }
402 
408  void AddRectangleWindow (ooc::Point const & min, ooc::Point const & max)
409  {
410  LockGuard lock(selection_mutex);
411  filter.AddRectangleWindow(*GetView(), min, max);
412  }
413 
420  void AddTriangleWindow (ooc::Point const & p1, ooc::Point const & p2, ooc::Point const & p3)
421  {
422  LockGuard lock(selection_mutex);
423  filter.AddTriangleWindow(*GetView(), p1, p2, p3);
424  }
425 
426  bool HasWindows()
427  {
428  return filter.HasWindows();
429  }
430 
435  template <typename Func>
436  auto SynchronizeWith (Func const & task) -> decltype(task())
437  {
438  LockGuard lock(selection_mutex);
439  return task();
440  }
441 
442 private:
443  virtual bool Tick (float request_time, float actual_time)
444  {
445  UNREFERENCED(request_time);
446  UNREFERENCED(actual_time);
447 
448  while (UpdateSelection()) {
449  GetView()->Update();
450  }
451 
452  return true;
453  }
454 
455 // void OnPopulateKey (HC_KEY segment_key)
456 // {
457 // if (filter.HasWindows()) {
458 // LockGuard lock(selection_mutex);
459 // if (filter.HasWindows()) {
460 // CallbackKeyInfo info(segment_key, CallbackType_Populate);
461 // callback_key_infos->Append(info);
462 // }
463 // }
464 // }
465 
466 // static void HC_CDECL StaticOnPopulateKey (HC_KEY segment_key)
467 // {
468 // static_cast<HSelectionSetOOC *>(Instance())->OnPopulateKey(segment_key);
469 // }
470 
471  void OnDeletedKey (HC_KEY key, int type)
472  {
473  if (type == HIC_Geometry_Type_SHELL) {
474  if (filter.HasWindows()) {
475  LockGuard lock(selection_mutex);
476  if (filter.HasWindows()) {
477  CallbackKeyInfo info(key, CallbackType_Deleted);
478  callback_key_infos->Append(info);
479  }
480  }
481  }
482  }
483 
484  static void HC_CDECL StaticOnDeletedKey (HC_KEY key, int type)
485  {
486  static_cast<HSelectionSetOOC *>(Instance())->OnDeletedKey(key, type);
487  }
488 
489 private:
490  HWindowFilterOOC filter;
491  HMutexOOC selection_mutex;
492  VArray<CallbackKeyInfo> * callback_key_infos; // Using a pointer for fast "move" semantics
493 };
494 
495 
496 
497 
498 
Definition: HSelectionSetOOC.h:77
HTClient(float interval=0.1f, HTCStyle style=HTCS_Invalid, HTClientTickFunction tick_function=0, void *user_data=0)
Definition: HTManager.h:168
HC_KEY GetViewKey()
Definition: HBaseView.h:922
Definition: HMutexOOC.h:24
HC_KEY GetModelKey()
The HSelectionSet class manages a list of selected items.
Definition: HSelectionSet.h:66
Definition: HTManager.h:157
HC_KEY GetIncludeLinkKey()
Definition: HBaseView.h:927
Definition: HWindowFilterOOC.h:44
void AddTriangleWindow(ooc::Point const &p1, ooc::Point const &p2, ooc::Point const &p3)
Definition: HSelectionSetOOC.h:420
void AddRectangleWindow(ooc::Point const &min, ooc::Point const &max)
Definition: HSelectionSetOOC.h:408
static HTManager * GetHTManager()
Definition: HMutexOOC.h:28
Similar to HTCS_Periodic but this option has no make-up events.
Definition: HTManager.h:106
auto SynchronizeWith(Func const &task) -> decltype(task())
Definition: HSelectionSetOOC.h:436
void SetDeepSelection(bool deep_select)
Definition: HSelectionSetOOC.h:274
The HBaseView class defines and manages a view of model information.
Definition: HBaseView.h:332
ooc::query::QueryIterator SelectedPoints()
Definition: HSelectionSetOOC.h:283
bool UpdateSelection()
Definition: HSelectionSetOOC.h:304
virtual bool DeleteSelection(bool emit_message=false)
Definition: HSelectionSetOOC.h:197
static bool CanCreateInstance()
Definition: HSelectionSetOOC.h:170
void UnRegisterClient(HTClient *c)
virtual void Reset()
Definition: HSelectionSetOOC.h:177
void RegisterClient(HTClient *c)
static HSelectionSetOOC * CreateInstance(HBaseView &view, bool deep_select)
Definition: HSelectionSetOOC.h:154
Definition: HSelectionSetOOC.h:61