Curve extrusion along curve differences between gui and api

Dear all,

I have developed a c++ Rhino plug-in and now I need to write a command to enlarge planar curves of a specific offset value, on a 2D plane.
The expected result is a 2D surface.

I’m able to reach exactly the target using the Rhino user interface, in particular the command “_ExtrudeCrvAlongCrv”.
I simply create a circle with radius equal to the required offset at an end of the curve to be offset, then I use the circle as shape and the curve as drive curve.
The result i simply perfect, as show in figure “Input.png”

and “UI_brep.png”

The problems occur when I try to reach the same result using Rhino SDK API:
In particular I use “Rhino1RailSweep” function, expecting the same results, but instead the output is the one shown in figure “API_brep.png”.

Top-left and top-right example are completely wrong but there are moreover less evident errors:
A) Some corners are not rounded:

B) In one case, the surface does not end with the circle center at the end of the line, but just before

C) In general the algorithm seems to be less precise

The code I wrote is the following:

const double in_offset;
const ON_Curve& in_drive_curve;
const ON_Circle shape(ON_xy_plane, in_drive_curve.PointAtStart(), in_offset);
ON_NurbsCurve shape_nurb;
const int is_nurb_correct =
shape.GetNurbForm(shape_nurb);
if (!is_nurb_correct)
{
	return;
}

ON_SimpleArray<const ON_Curve*> shapes;
shapes.Append(&shape_nurb);

ON_SimpleArray<ON_Brep*> breps;
Rhino1RailSweep(
	breps,
	&in_drive_curve,
	shapes);

Can you please supply to me help for my purpose?
@Dale usually is great with this problems.

Thank you,

Ciao Alberto,

scusa la schiettezza ma non mi pare una grande idea estrudere una curva piana e creare una superficie del genere… vien fuori una roba che si autointerseca…

Non è meglio utilizzare un pipe lungo il percorso e poi intersecarlo con un piano per ottenere la curva piana sulla quale fare la superficie?

Il comando Offset con opzione Both Side e Cap=Round non riesci a richiamarlo da SDK ?
Ti verrebbe una cosa come da immagine sotto

Ci sono veramente tanti modi per creare quello che ti serve, ma fare un extrudecrv lungo lo stesso piano dove giace la curva piana mi sembra l’inizio di un incubo…

Edit
Vedendo le tue immagini presumo che le curve siano dei percorsi utensile… fresatura magari?
Quindi stai facendo una simulazione del percorso utensile?
O stai facendo un aggiornamento pezzo lavorato per vedere dove ci sono sovrametalli da togliere?
Se si tratta solo di una simulazione, allora potresti dividere il percorso (tipo estrapolare un punto ogni 0.01mm) e su quel punto copiare la forma utensile.
Alla fine sommando tutte le circonferenze (con un curve boolean) ottieni l’area lavorata.
Questo approccio può essere più efficace se siamo in presenza di percorsi sovrapposti o autointersecanti dove comandi tipo offset, extrude e compagnia bella tendono a crashare (perchè cercano di risolvere situazioni anomale).

5 Mi Piace

Ciao Lucio,

grazie per il tuo intervento.

Purtroppo con le pipe eventuali spigoli non vengono arrotondati quindi per me non è una soluzione (a meno che non hai delle funzioni da SKD che mi permettano di generare gli spigoli arrotondati).

Il comando Offset con opzione Both Side e Cap=Round funziona perfettamente da SDK, ma come immaginerai non è una soluzione quando stiamo parlando di curve con eventuali auto-intersezioni come mostrato nei miei esempi.

L’idea di generare un cerchio ogni 0.01 mm e poi unire tutto risulta troppo oneroso computazionalmente. Stiamo parlando di curve abbastanza grandi, mi serve un approccio un po’ più ottimizzato.

Ciao Alberto,
non hai delle curve di esempio allegare così da fare delle prove?
Qual’è il grado di tolleranza che devi ottenere?
Il tipo di percorso è un qualcosa di “freeform” fatto dall’utente a caso o proviene da una logica “meccanica” (dove quindi si possono prevedere un certo tipo di situazioni)?
Bisogna cercare di restringere il campo per capire quale sia la strada più efficace.

Certo Lucio,
scusa se non li ho allegati prima.

Ecco qui un file con quattro esempi che sintetizzano i casi che vorrei coprire.

EncumbranceConduit_test_light.3dm (193,5 KB)

Ciao Alberto,

senza sminuire quanto sta facendo Lucio per cercare strade alternative,
ma solo per fare un tentativo …

Non so niente di plug-in C++ :blush:
Ma vedo che in RhinoCommon c’e’ questo metodo, che forse potrebbe dare risultati diversi rispetto allo Sweep ..

https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.sumsurface/create#(curve,curve)

Credo che certamente in OpenNurbs ci sia una cosa corrispondente.
Se vuoi vedere se cambia qualcosa … :slight_smile:

Vai Emi, sminuisci pure, non ci sono problemi!!
Tanto oggi ero in ditta a smadonnare per problemi sul taglio laser e quindi non sono riuscito a procedere.
Se ci sono comandi alternativi che fanno il lavoro, ben vengano!
Avevo pensato anche a Ribbon che fa il lavoro di offsettare a destra e sinistra la rail (però non mi risulta ci sia il CAP circolare… cosa che si può aggiungere successivamente al ribbon…)

1 Mi Piace

Non voglio sminuire proprio niente !
:smile:

1 Mi Piace

Ho fatto qualche prova e alla fine mi sono buttato giù uno script che fa circa quello che hai chiesto… poi bisogna vedere come inserire lo stesso procedimento nel plugin…

Option Explicit
'Script written by Lucio Zadra
'Script version giovedì 11 settembre 2025 18:23:17

Call Main()
Sub Main()

	Dim CrvId, Segm, Rad, CrvArr, OffsArr(), i, ResultArray, GrpName
	
	i = 0
	
	'Seleziono la curva da offsettare
	
	CrvId = Rhino.GetObject("Seleziona la curva da elaborare", 4, VbTrue)
	If Not IsNull(CrvId) Then
		Rad = Rhino.GetReal("Inserisci la larghezza dell'offset", 2)
		If IsNull(rad) Then Exit Sub
		CrvArr = Rhino.explodeCurves(CrvId)
		If Not IsNull(CrvArr) Then
			Rhino.EnableRedraw False
			For Each Segm In CrvArr
				ReDim Preserve OffsArr(i)
				Rhino.SelectObject Segm
				Rhino.Command "_Offset " & Cstr(Rad) & " _Bothside _Cap=Round _Enter", False
				Rhino.UnselectAllObjects
				If Rhino.IsCurveClosed(Rhino.FirstObject) Then
					OffsArr(i) = Rhino.FirstObject
					i = i + 1
				Else
					Rhino.DeleteObject Rhino.FirstObject
				End If
			Next
			Rhino.DeleteObjects CrvArr
			ResultArray = Rhino.CurveBooleanUnion(OffsArr, True)
			If IsNull(ResultArray) Then
				'Rhino.DeleteObjects OffsArr
				Rhino.EnableRedraw True
				Exit Sub
			End If
			
			GrpName = "Gruppo" & Cstr(Time)
			Rhino.AddGroup GrpName
			Rhino.AddObjectsToGroup ResultArray, GrpName
			Rhino.EnableRedraw True
		End If
	End If
	
End Sub

E’ in VbScript perchè io sono vecchio e non mi sono adeguato…
Però funziona… su per giù, almeno per i test che ho fatto…

2 Mi Piace

Ma va bene essere sminuiti che dopo uno si esalta troppo e non lo tiri più giù dal piedistallo… :joy:

1 Mi Piace