# HG changeset patch # User Sebastien Jodogne # Date 1621499725 -7200 # Node ID 013dec434a845552ca6db56f82073d0a096d42f5 # Parent 20a0aba0ede5ab2d1e462db9598935198533a44a creation of segment or circle measures diff -r 20a0aba0ede5 -r 013dec434a84 Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp --- a/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp Wed May 19 18:59:45 2021 +0200 +++ b/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp Thu May 20 10:35:25 2021 +0200 @@ -171,16 +171,14 @@ Measure(AnnotationsOverlay& that) : that_(that) { + that.AddMeasure(this); } virtual ~Measure() { for (Primitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it) { - assert(*it != NULL); - assert(that_.primitives_.find(*it) != that_.primitives_.end()); - that_.primitives_.erase(*it); - delete *it; + that_.DeletePrimitive(*it); } } @@ -612,16 +610,27 @@ class Text : public Primitive { private: + AnnotationsOverlay& that_; bool first_; - size_t sublayer_; + size_t subLayer_; std::unique_ptr content_; public: - Text(Measure& parentMeasure) : + Text(AnnotationsOverlay& that, + Measure& parentMeasure) : Primitive(parentMeasure, 2), + that_(that), first_(true) { } + + virtual ~Text() + { + if (content_.get() != NULL) + { + that_.TagSubLayerToRemove(subLayer_); + } + } void SetContent(const TextSceneLayer& content) { @@ -651,12 +660,12 @@ if (first_) { - sublayer_ = macro.AddLayer(layer.release()); + subLayer_ = macro.AddLayer(layer.release()); first_ = false; } else { - macro.UpdateLayer(sublayer_, layer.release()); + macro.UpdateLayer(subLayer_, layer.release()); } } } @@ -766,12 +775,17 @@ handle1_(AddTypedPrimitive(new Handle(*this, p1))), handle2_(AddTypedPrimitive(new Handle(*this, p2))), segment_(AddTypedPrimitive(new Segment(*this, p1, p2))), - label_(AddTypedPrimitive(new Text(*this))) + label_(AddTypedPrimitive(new Text(that, *this))) { label_.SetColor(Color(255, 0, 0)); UpdateLabel(); } + Handle& GetHandle2() const + { + return handle2_; + } + virtual void SignalMove(Primitive& primitive) ORTHANC_OVERRIDE { if (&primitive == &handle1_ || @@ -843,7 +857,7 @@ segment1_(AddTypedPrimitive(new Segment(*this, start, middle))), segment2_(AddTypedPrimitive(new Segment(*this, middle, end))), arc_(AddTypedPrimitive(new Arc(*this, start, middle, end))), - label_(AddTypedPrimitive(new Text(*this))) + label_(AddTypedPrimitive(new Text(that, *this))) { label_.SetColor(Color(255, 0, 0)); UpdateLabel(); @@ -945,12 +959,17 @@ handle2_(AddTypedPrimitive(new Handle(*this, p2))), segment_(AddTypedPrimitive(new Segment(*this, p1, p2))), circle_(AddTypedPrimitive(new Circle(*this, p1, p2))), - label_(AddTypedPrimitive(new Text(*this))) + label_(AddTypedPrimitive(new Text(that, *this))) { label_.SetColor(Color(255, 0, 0)); UpdateLabel(); } + Handle& GetHandle2() const + { + return handle2_; + } + virtual void SignalMove(Primitive& primitive) ORTHANC_OVERRIDE { if (&primitive == &handle1_ || @@ -971,18 +990,121 @@ }; + class CreateSegmentOrCircleTracker : public IFlexiblePointerTracker + { + private: + AnnotationsOverlay& that_; + Measure* measure_; + AffineTransform2D canvasToScene_; + Handle* handle2_; + + public: + CreateSegmentOrCircleTracker(AnnotationsOverlay& that, + bool isCircle, + const ScenePoint2D& sceneClick, + const AffineTransform2D& canvasToScene) : + that_(that), + measure_(NULL), + canvasToScene_(canvasToScene), + handle2_(NULL) + { + if (isCircle) + { + measure_ = new CircleMeasure(that, sceneClick, sceneClick); + handle2_ = &dynamic_cast(measure_)->GetHandle2(); + } + else + { + measure_ = new SegmentMeasure(that, sceneClick, sceneClick); + handle2_ = &dynamic_cast(measure_)->GetHandle2(); + } + + assert(measure_ != NULL && + handle2_ != NULL); + } + + virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE + { + if (measure_ != NULL) + { + assert(handle2_ != NULL); + handle2_->SetCenter(event.GetMainPosition().Apply(canvasToScene_)); + measure_->SignalMove(*handle2_); + } + } + + virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE + { + measure_ = NULL; // IsAlive() becomes false + } + + virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE + { + } + + virtual bool IsAlive() const ORTHANC_OVERRIDE + { + return (measure_ != NULL); + } + + virtual void Cancel() ORTHANC_OVERRIDE + { + if (measure_ != NULL) + { + that_.DeleteMeasure(measure_); + measure_ = NULL; + } + } + }; + + typedef std::set Primitives; typedef std::set Measures; + typedef std::set SubLayers; size_t macroLayerIndex_; - size_t polylineSublayer_; + size_t polylineSubLayer_; Primitives primitives_; Measures measures_; + SubLayers subLayersToRemove_; + + void AddMeasure(Measure* measure) + { + assert(measure != NULL); + assert(measures_.find(measure) == measures_.end()); + measures_.insert(measure); + } + + void DeleteMeasure(Measure* measure) + { + if (measure != NULL) + { + assert(measures_.find(measure) != measures_.end()); + measures_.erase(measure); + delete measure; + } + } + + void DeletePrimitive(Primitive* primitive) + { + if (primitive != NULL) + { + assert(primitives_.find(primitive) != primitives_.end()); + primitives_.erase(primitive); + delete primitive; + } + } + + void TagSubLayerToRemove(size_t subLayerIndex) + { + assert(subLayersToRemove_.find(subLayerIndex) == subLayersToRemove_.end()); + subLayersToRemove_.insert(subLayerIndex); + } public: AnnotationsOverlay(size_t macroLayerIndex) : macroLayerIndex_(macroLayerIndex), - polylineSublayer_(0) // dummy initialization + polylineSubLayer_(0) // dummy initialization { measures_.insert(new SegmentMeasure(*this, ScenePoint2D(0, 0), ScenePoint2D(100, 100))); measures_.insert(new AngleMeasure(*this, ScenePoint2D(100, 50), ScenePoint2D(150, 40), ScenePoint2D(200, 50))); @@ -1011,9 +1133,17 @@ else { macro = &dynamic_cast(scene.SetLayer(macroLayerIndex_, new MacroSceneLayer)); - polylineSublayer_ = macro->AddLayer(new PolylineSceneLayer); + polylineSubLayer_ = macro->AddLayer(new PolylineSceneLayer); } + for (SubLayers::const_iterator it = subLayersToRemove_.begin(); it != subLayersToRemove_.end(); ++it) + { + assert(macro->HasLayer(*it)); + macro->DeleteLayer(*it); + } + + subLayersToRemove_.clear(); + std::unique_ptr polyline(new PolylineSceneLayer); for (Primitives::iterator it = primitives_.begin(); it != primitives_.end(); ++it) @@ -1030,7 +1160,7 @@ } } - macro->UpdateLayer(polylineSublayer_, polyline.release()); + macro->UpdateLayer(polylineSubLayer_, polyline.release()); } bool ClearHover() @@ -1095,6 +1225,11 @@ } } + if (tracker.get() == NULL) + { + tracker.reset(new CreateSegmentOrCircleTracker(*this, true /* circle */, s, scene.GetCanvasToSceneTransform())); + } + return tracker.release(); } }; diff -r 20a0aba0ede5 -r 013dec434a84 OrthancStone/Sources/Scene2D/Internals/MacroLayerRenderer.cpp --- a/OrthancStone/Sources/Scene2D/Internals/MacroLayerRenderer.cpp Wed May 19 18:59:45 2021 +0200 +++ b/OrthancStone/Sources/Scene2D/Internals/MacroLayerRenderer.cpp Thu May 20 10:35:25 2021 +0200 @@ -61,7 +61,10 @@ for (size_t i = 0; i < macro.GetSize(); i++) { - renderers_.push_back(factory_.Create(macro.GetLayer(i))); + if (macro.HasLayer(i)) + { + renderers_.push_back(factory_.Create(macro.GetLayer(i))); + } } } } diff -r 20a0aba0ede5 -r 013dec434a84 OrthancStone/Sources/Scene2D/MacroSceneLayer.cpp --- a/OrthancStone/Sources/Scene2D/MacroSceneLayer.cpp Wed May 19 18:59:45 2021 +0200 +++ b/OrthancStone/Sources/Scene2D/MacroSceneLayer.cpp Thu May 20 10:35:25 2021 +0200 @@ -24,16 +24,16 @@ #include -#include - namespace OrthancStone { void MacroSceneLayer::Clear() { for (size_t i = 0; i < layers_.size(); i++) { - assert(layers_[i] != NULL); - delete layers_[i]; + if (layers_[i] != NULL) + { + delete layers_[i]; + } } layers_.clear(); @@ -49,6 +49,8 @@ } else { + // TODO - Use recycling list from DeleteLayer() + size_t index = layers_.size(); layers_.push_back(layer); BumpRevision(); @@ -70,8 +72,10 @@ } else { - assert(layers_[index] != NULL); - delete layers_[index]; + if (layers_[index] != NULL) + { + delete layers_[index]; + } layers_[index] = layer; BumpRevision(); @@ -79,16 +83,52 @@ } - const ISceneLayer& MacroSceneLayer::GetLayer(size_t i) const + bool MacroSceneLayer::HasLayer(size_t index) const { - if (i >= layers_.size()) + if (index >= layers_.size()) { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } else { - assert(layers_[i] != NULL); - return *layers_[i]; + return (layers_[index] != NULL); + } + } + + + void MacroSceneLayer::DeleteLayer(size_t index) + { + if (index >= layers_.size()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + else if (layers_[index] == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem); + } + else + { + // TODO - Add to a recycling list + + delete layers_[index]; + layers_[index] = NULL; + } + } + + + const ISceneLayer& MacroSceneLayer::GetLayer(size_t index) const + { + if (index >= layers_.size()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + else if (layers_[index] == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem); + } + else + { + return *layers_[index]; } } @@ -99,10 +139,18 @@ for (size_t i = 0; i < layers_.size(); i++) { - assert(layers_[i] != NULL); - copy->layers_.push_back(layers_[i]->Clone()); + if (layers_[i] == NULL) + { + copy->layers_.push_back(NULL); + } + else + { + copy->layers_.push_back(layers_[i]->Clone()); + } } + // TODO - Copy recycling list + return copy.release(); } @@ -113,11 +161,12 @@ for (size_t i = 0; i < layers_.size(); i++) { - assert(layers_[i] != NULL); - - Extent2D subextent; - layers_[i]->GetBoundingBox(subextent); - target.Union(subextent); + if (layers_[i] != NULL) + { + Extent2D subextent; + layers_[i]->GetBoundingBox(subextent); + target.Union(subextent); + } } } } diff -r 20a0aba0ede5 -r 013dec434a84 OrthancStone/Sources/Scene2D/MacroSceneLayer.h --- a/OrthancStone/Sources/Scene2D/MacroSceneLayer.h Wed May 19 18:59:45 2021 +0200 +++ b/OrthancStone/Sources/Scene2D/MacroSceneLayer.h Thu May 20 10:35:25 2021 +0200 @@ -72,6 +72,10 @@ void UpdateLayer(size_t index, ISceneLayer* layer); // takes ownership + bool HasLayer(size_t index) const; + + void DeleteLayer(size_t index); + const ISceneLayer& GetLayer(size_t i) const; virtual ISceneLayer* Clone() const ORTHANC_OVERRIDE;