Select face/edge

I want to use Hoops for picking. When the mouse selects a line/face, they should be highlighted. When clicked again, the highlight should be canceled. I tried using the following code:

class SandboxHighlightOperator : public HPS::SelectOperator {
public:
    SandboxHighlightOperator(HPSWidget* widget);
    virtual ~SandboxHighlightOperator();

    virtual HPS::UTF8 GetName() const { return "Qt_SandboxHighlightOperator"; }

    bool OnMouseDown(HPS::MouseState const& in_state) override;
    bool OnMouseUp(HPS::MouseState const& in_state) override;

    bool OnMouseMove(const HPS::MouseState& in_state) override;

    static ::HPS::Selection::Level SelectionLevel;

    void Unhighlight();

private:
    void HighlightCommon();

private:
    HPSWidget* mainWidget;

    bool m_isMove = false;
    HPS::MouseState m_mouseUpState;

    std::vector<HPS::SelectionItem> m_selectItems; // edge face
};

#include "SandboxHighlightOp.h"
#include "HPSWidget.h"
#include <hps.h>

#include <QDebug>

SandboxHighlightOperator::SandboxHighlightOperator(HPSWidget* widget)
    : HPS::SelectOperator(HPS::MouseButtons::ButtonLeft(), HPS::ModifierKeys())
    , mainWidget(widget)
{
}

SandboxHighlightOperator::~SandboxHighlightOperator() { }

bool SandboxHighlightOperator::OnMouseDown(HPS::MouseState const& in_state)
{
    m_isMove = false;
    m_mouseUpState = in_state;
    return false;
}

bool SandboxHighlightOperator::OnMouseMove(const HPS::MouseState& in_state)
{
    m_isMove = true;
    //    setHoverHighLight(in_state);
    return Operator::OnMouseMove(in_state);
}

bool SandboxHighlightOperator::OnMouseUp(const HPS::MouseState& in_state)
{
    if (!m_isMove) {
        if (IsMouseTriggered(m_mouseUpState) && HPS::SelectOperator::OnMouseDown(m_mouseUpState)) {
            HighlightCommon();
            m_mouseUpState = HPS::MouseState();
            m_isMove = false;
            return true;
        }
    }
    m_mouseUpState = HPS::MouseState();
    m_isMove = false;

    return Operator::OnMouseUp(in_state);
}

void SandboxHighlightOperator::HighlightCommon()
{
    HPS::SelectionResults selection_results = GetActiveSelection();
    size_t selected_count = selection_results.GetCount();
    if (selected_count > 0) {
        HPS::CADModel cad_model = mainWidget->getCADModel();

        HPS::HighlightOptionsKit highlight_options(HPS::HighlightOptionsKit::GetDefault());
        highlight_options.SetStyleName("highlight_style");
        highlight_options.SetSubentityHighlighting(false);
        highlight_options.SetOverlay(HPS::Drawing::Overlay::InPlace);

        if (!cad_model.Empty()) {
            HPS::SelectionResultsIterator it = selection_results.GetIterator();
            HPS::SelectionItem item = it.GetItem();

            HPS::Canvas canvas = *mainWidget->getCanvas();
            HPS::ComponentPath component_path = cad_model.GetComponentPath(item);

            int index = -1;
            for (int i = 0; i < m_selectItems.size(); ++i) {
                HPS::SelectionItem newItem = m_selectItems[i];

                if (newItem.GetClassID() == item.GetClassID()) {
                    index = i;
                }
                qDebug() << i << index << newItem.GetInstanceID() << newItem.GetClassID() << item.GetClassID();
            }

            //            auto iter = std::find_if(m_selectItems.begin(), m_selectItems.end(),
            //                [&item](const HPS::SelectionItem& si) { return si.GetClassID() == item.GetClassID(); });

            if (index != -1) {
                auto iter1 = m_selectItems.begin() + index;
                component_path.Unhighlight(canvas, highlight_options);
                qDebug() << "remove" << iter1->GetInstanceID() << iter1->GetClassID();
                m_selectItems.erase(iter1);
            } else {
                component_path.Highlight(canvas, highlight_options);
                const HPS::SelectionItem& newItem = item;
                m_selectItems.push_back(newItem);
                qDebug() << "add2" << item.GetInstanceID() << item.GetClassID();
            }
            qDebug() << "===============================================2";
        }
    }

    mainWidget->getCanvas()->Update();
}

void SandboxHighlightOperator::Unhighlight()
{
    HPS::HighlightOptionsKit highlightOptions;
    highlightOptions.SetStyleName("highlight_style").SetNotification(true);
    mainWidget->getCanvas()->GetWindowKey().GetHighlightControl().Unhighlight(highlightOptions);

    HPS::EventDispatcher dispatcher = HPS::Database::GetEventDispatcher();
    dispatcher.InjectEvent(HPS::HighlightEvent(HPS::HighlightEvent::Action::Unhighlight, HPS::SelectionResults(), highlightOptions));
    dispatcher.InjectEvent(HPS::ComponentHighlightEvent(HPS::ComponentHighlightEvent::Action::Unhighlight, *mainWidget->getCanvas(), 0, HPS::ComponentPath(), highlightOptions));
}

When testing, I encountered the following issues:

  1. Highlighting and unhighlighting sometimes work and sometimes don’t. I don’t understand why.

  2. I use the following code for highlighting and unhighlighting operations:

            int index = -1;
            for (int i = 0; i < m_selectItems.size(); ++i) {
                HPS::SelectionItem newItem = m_selectItems[i];

                if (newItem.GetClassID() == item.GetClassID()) {
                    index = i;
                }
                qDebug() << i << index << newItem.GetInstanceID() << newItem.GetClassID() << item.GetClassID();
            }

            if (index != -1) {
                auto iter1 = m_selectItems.begin() + index;
                component_path.Unhighlight(canvas, highlight_options);
                qDebug() << "remove" << iter1->GetInstanceID() << iter1->GetClassID();
                m_selectItems.erase(iter1);
            } else {
                component_path.Highlight(canvas, highlight_options);
                const HPS::SelectionItem& newItem = item;
                m_selectItems.push_back(newItem);
                qDebug() << "add2" << item.GetInstanceID() << item.GetClassID();
            }

I can only determine if this SelectionItem is already saved in std::vectorHPS::SelectionItem based on GetClassID, while GetInstanceID changes every time, and I don’t know why.

In the for loop, I can find the corresponding index, but in the subsequent if (index != -1), the GetClassID of iter1 is different from the GetClassID in the for loop, which I also fail to understand.

I’m not sure if my approach is correct, or if there are other ways to implement this.

Hello,

I am not familiar with GetClassID. Our default HPS select operator uses is SelectionResults::SymmetricDifference to find compare the difference.


bool HPS::SelectOperator::SelectCommon(HPS::Point const& in_loc, HPS::WindowKey& in_window, HPS::ModifierKeys in_modifiers)
{
    try {
        HPS::SelectionResults new_selection;
        size_t selected = in_window.GetSelectionControl().SelectByPoint(in_loc, selection_options, new_selection);

        if (active_selection.GetCount() > 0 && in_modifiers.Control() && selected > 0) {
            if (!active_selection.SymmetricDifference(new_selection))
                active_selection = new_selection;
        }
        else
            active_selection = new_selection;
    }
    catch (HPS::InvalidObjectException const&) {
        // do nothing
    }

    return true;
}

Can you try using that?

Our source code for all our default operators is included in our packages.

HPS_INSTALL_DIR\samples\operators

Best Regards,
Simon

1 Like