# Select face/edge

**URL:** <https://forum.techsoft3d.com/t/select-face-edge/3824>\
**Category:** HOOPS Visualize Desktop\
**Tags:** code\
**Created:** [July 2, 2024, 2:42am UTC](https://forum.techsoft3d.com/t/select-face-edge/3824 "2024-07-02T02:42:20Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![1260155516](https://avatars.discourse-cdn.com/v4/letter/1/ecae2f/32.png) [@1260155516](https://forum.techsoft3d.com/u/1260155516)\
**Post date:** [July 2, 2024, 2:42am UTC](https://forum.techsoft3d.com/t/select-face-edge/3824/1 "2024-07-02T02:42:20Z")

</div>

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:

```c++
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
};

```

```c++

#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:

```auto
            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.

---

<div class="post-metadata">

**Author:** ![simon](https://avatars.discourse-cdn.com/v4/letter/s/f07891/32.png) [@simon](https://forum.techsoft3d.com/u/simon)\
**Post date:** [July 26, 2024, 10:18pm UTC](https://forum.techsoft3d.com/t/select-face-edge/3824/2 "2024-07-26T22:18:09Z")

</div>

> [@1260155516](#):
>
> ```auto
> 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
> };
> 
> ```

Hello,

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

```auto

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
