How to highlight a mesh boundary in order?

Hi,
I want to use color transitions to display the odered boundary loop of an open mesh, such as from (255,0,0) to (0,0,255)

Here is my code, but it is not working. I want the boundary curve could displayed with color transitions.


//https://github.com/mcneel/rhino-developer-samples/blob/8/cpp/SampleCommands/cmdSampleDrawPoints.cpp
class CSampleDrawPointsConduit : public CRhinoDisplayConduit
{
public:
	CSampleDrawPointsConduit()
		: CRhinoDisplayConduit(CSupportChannels::SC_CALCBOUNDINGBOX | CSupportChannels::SC_PREDRAWOBJECTS)
	{}

	bool ExecConduit(CRhinoDisplayPipeline& dp, UINT nChannel, bool& bTerminate) override {
		UNREFERENCED_PARAMETER(bTerminate);

		if (nChannel == CSupportChannels::SC_CALCBOUNDINGBOX)
		{
			m_pChannelAttrs->m_BoundingBox.Union(m_points.BoundingBox());
		}
		else if (nChannel == CSupportChannels::SC_PREDRAWOBJECTS)
		{
			int rStart = 0;
			int pCount = m_points.Count();
			for (int i = 0; i < pCount; i++)
			{
				// Yello to Blue (255,255,0)->(0,0,255)
				dp.DrawPoint(m_points[i], 3, RPS_CONTROL_POINT, RGB(1.0 - 1.0*rStart / pCount, 1.0 - 1.0*rStart / pCount, 1.0*rStart));
				rStart++;
			}
		}

		return true;
	}

public:
	ON_3dPointArray m_points;
};

// Given mesh id, show its boundary
void ShowBoundary(const ON_UUID& meshId, CSampleDrawPointsConduit& conduit)
{
	// Find Rhino mesh
	const CRhinoObject* pLookup = CRhinoMeshObject::FromId(RhinoApp().ActiveDoc()->RuntimeSerialNumber(), meshId);
	const CRhinoMeshObject* mesh_object = CRhinoMeshObject::Cast(pLookup);

	if (nullptr == mesh_object) {
		MessageBox(L"Mesh uuid is wrong!");
		return;
	}

	const ON_Mesh* mesh = mesh_object->Mesh();

	// Append boundary points
	const ON_MeshTopology& mesh_top = mesh->Topology();

	for (int i = 0; i < mesh_top.m_topv.Count(); ++i) {
		// for each topology vertex
		const ON_MeshTopologyVertex& mesh_top_vertex = mesh_top.m_topv[i];

		for (int j = 0; i < mesh_top_vertex.m_tope_count; j++) {
			// for each topology edge of current topology vertex
			const ON_MeshTopologyEdge& mesh_top_edge = mesh_top.m_tope[mesh_top_vertex.m_topei[j]];
			if (1 == mesh_top_edge.m_topf_count) {
				conduit.m_points.Append(mesh->Vertex(mesh_top_vertex.m_vi[0]));
				break;
			}
		}

	}
}


int main(){
  ...
  CSampleDrawPointsConduit conduit;
  ShowBoundary(meshId,conduit);
  conduit.Enable();
  ...
}

To display a color transition along the boundary of and open mesh, interpolate colors between red and blue for each boundary point. Use a formula to blend the colors based on the point’s position along the boundary, then draw lines or curves with these colors to visualize the transition. Make sure the boundary points are in order to create a smooth gradient effect.

for (int j = 0; i < mesh_top_vertex.m_tope_count; j++) {

this should be the following (notice j index, not i)

for (int j = 0; j < mesh_top_vertex.m_tope_count; j++) {

Three more things:

  1. this does not draw the points ordered along the border. For that you’d need to duplicate the mesh border, and add the points from the border to the conduit.

  2. RGB color needs values from 0…255, not 0.0-1.0.

  3. If you interpolate from yellow to blue like this, it will interpolate to gray in the middle. You’re probably better off when interpolating in HSV color space if you don’t want gray.

Thanks, @menno, I got many mistakes, It helps a lot.

I want to hightlight the mesh boundary just because I want to pick vertices along it.

so If I use code from SampleDupMeshBorder to duplicate a mesh boundary, I think I could try to make each ON_Lines a color interpolate, but when I was picking vertex, could I get the right vertex indices?

Since my purpose is to pick vertices along mesh boundary with user-friendly highlighting, Is there any better way to achieve it?

Maybe take a step back first. What is the problem you are trying to solve? Why do you need highlighting? What does Rhino not do, that needs improvement?

I am developing a plug-in which need to support picking vertex from a open mesh.
There two mode of vertex picking need to implement:

  1. interior vertex picking.
  2. boundary vertex picking.

Both of them I want to highlights the open mesh boundary in advance so that I could know where is the right area for picking.

here is my code, I want to add ShowBoundary() method into it:

void CMainDlg::VertexPicker(const ON_UUID& meshId, std::vector<int>& outVertexIndices, bool pickBoundary)
{
	const CRhinoObject* pLookup = CRhinoMeshObject::FromId(RhinoApp().ActiveDoc()->RuntimeSerialNumber(), meshId);
	const CRhinoMeshObject* mesh_object = CRhinoMeshObject::Cast(pLookup);

	if (nullptr == mesh_object) {
		MessageBox(L"Mesh uuid is wrong!");
		return;
	}


   // Try to implement ShowBoundary() here
   // ShowBoundary();

	// https://github.com/mcneel/rhino-developer-samples/blob/6/cpp/SampleCommands/cmdSamplePullCurveToMesh.cpp
	// https://github.com/mcneel/rhino-developer-samples/blob/6/cpp/SampleCommands/cmdSampleMeshFacePicker.cpp

	//CRhinoGetObject gv;
	CRhGetMeshComponentRef gv(mesh_object->RuntimeSerialNumber());
	gv.SetCommandPrompt(L"Select mesh vertex");
	gv.SetGeometryFilter(CRhinoGetObject::meshvertex_filter);
	gv.GetObjects(1, 0);
	if (gv.CommandResult() != CRhinoCommand::success)
		return;

	for (int i = 0; i < gv.ObjectCount(); i++) {
		const ON_MeshComponentRef* mesh_vertex_ref = gv.Object(i).MeshComponentRef();
		if (nullptr == mesh_vertex_ref) {
			RhinoApp().Print(L"Selected vertex INVALID!");
			return;
		}

		if (!pickBoundary) {
			if (SURF_PARA::IsRhinoBoundary(mesh_vertex_ref)) {
				RhinoApp().Print(L"Can only select non-boundary vertex!");
				return;
			}
		}

		ON_3dPoint position;
		const ON_MeshTopologyVertex* tempTopVertex;
		unsigned int tIndex = mesh_vertex_ref->GetMeshTopologyVertexAndPoint(tempTopVertex, position);	

		int index = tempTopVertex->m_vi[0];
		outVertexIndices.push_back(index);


		ON_wString wstr;
		wstr.Format(L"%d", i);
		ON_TextDot dot(position, wstr, 0);
		CRhinoTextDot* obj = new CRhinoTextDot();
		obj->SetDot(dot);

		RhinoApp().ActiveDoc()->AddObject(obj);


		RhinoApp().ActiveDoc()->Redraw();
	}
}