Skip to content

Instantly share code, notes, and snippets.

@jpfaraco
Last active February 20, 2026 17:40
Show Gist options
  • Select an option

  • Save jpfaraco/84f37530916c33466cb4597ae995459b to your computer and use it in GitHub Desktop.

Select an option

Save jpfaraco/84f37530916c33466cb4597ae995459b to your computer and use it in GitHub Desktop.
Onshape feature - Sine wave
FeatureScript 2780;
import(path : "onshape/std/common.fs", version : "2780.0");
annotation { "Feature Type Name" : "Sine wave" }
export const sineWave = defineFeature(function(context is Context, id is Id, definition is map)
precondition
{
annotation { "Name" : "Edge", "Filter" : EntityType.EDGE, "MaxNumberOfPicks" : 1 }
definition.edge is Query;
annotation { "Name" : "Reference face", "Filter" : EntityType.FACE && GeometryType.PLANE, "MaxNumberOfPicks" : 1 }
definition.referenceFace is Query;
annotation { "Name" : "Amplitude" }
isLength(definition.amplitude, { (millimeter) : [0.1, 5, 100] } as LengthBoundSpec);
annotation { "Name" : "Number of cycles" }
isReal(definition.cycles, { (unitless) : [0.1, 5, 100] } as RealBoundSpec);
annotation { "Name" : "Phase offset" }
isAngle(definition.phase, { (degree) : [0, 0, 360] } as AngleBoundSpec);
annotation { "Name" : "Points per cycle" }
isInteger(definition.pointsPerCycle, { (unitless) : [8, 32, 100] } as IntegerBoundSpec);
annotation { "Name" : "Flip direction" }
definition.flip is boolean;
}
{
var amplitude = definition.amplitude;
if (definition.flip)
amplitude = -amplitude;
var cycles = definition.cycles;
var phase = definition.phase;
var pointsPerCycle = definition.pointsPerCycle;
var totalPoints = cycles * pointsPerCycle + 1;
// The reference face normal defines which direction the wave oscillates in.
// At each point along the edge, we project this normal onto the plane
// perpendicular to the tangent, so the wave always goes "sideways" relative
// to the edge direction.
var refPlane = evPlane(context, { "face" : definition.referenceFace });
var waveDir = refPlane.normal;
var points = [];
for (var i = 0; i < totalPoints; i += 1)
{
var t = i / (totalPoints - 1);
var tangentLine = evEdgeTangentLine(context, {
"edge" : definition.edge,
"parameter" : t
});
var pos = tangentLine.origin;
var tan = tangentLine.direction;
// Project wave direction onto the plane perpendicular to the tangent
var perp = waveDir - dot(waveDir, tan) * tan;
var len = norm(perp);
if (len < 1e-10)
throw regenError("The reference face normal is parallel to the edge. Pick a different face.", ["referenceFace"]);
perp = perp / len;
// Compute sine offset at this parameter
var angle = t * cycles * 2 * PI * radian + phase;
var offset = sin(angle) * amplitude;
points = append(points, pos + perp * offset);
}
opFitSpline(context, id + "sineWave", {
"points" : points
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment