Skip to main content

Tangent lines and circles

Many outlines are built from pieces that touch: a belt around two pulleys, a slot rounded into a plate, an arc that joins two lines smoothly. OpenCascade can work out where such pieces go. You give it the curves to touch and the plane to work in, and it gives back every line or circle that fits.

The constructions​

FunctionGives every
linesTangentToTwostraight line that touches two curved edges, or touches one and passes through a point
linesTangentAtAnglestraight line that touches a curved edge at an angle to a straight reference edge
circlesTangentToTwoWithRadiuscircle of a given radius that touches two edges, or passes through the points among them
circlesTangentToTwoCenteredOncircle centred on one edge that touches two others
circlesTangentToThreecircle that touches three edges, or passes through the points among them

All five live under bitbybit.occt.shapes.edge, and work the same way:

  • The shapes are edges, or vertices for points (bitbybit.occt.shapes.vertex.vertexFromPoint makes one from [x, y, z]).
  • The frame gives the plane they lie in: its origin is a point on the plane and its normal is square to it. bitbybit.frame.zx is the ground; bitbybit.frame.xy stands upright.
  • Every solution comes back, as a list of edges. Two circles have up to four lines touching both, and you choose the ones you need from the list.
  • Arcs count as whole circles, and straight edges as endless lines, unless onArgumentsOnly keeps only the solutions that touch within the edges' ends.

A belt between two wheels​

Two circles lie on the ground, and every straight line touching both is drawn: the two outer lines a belt would follow, and the two that cross between the wheels:

Bitbybit Platform

Lines tangent to two circles in Rete

rete logoRete
Script Source (rete)
{
"id": "rete-v2-json",
"nodes": {
"big": {
"id": "big",
"name": "bitbybit.occt.shapes.edge.createCircleEdge",
"customName": "circle edge",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 3,
"center": [
-4,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {},
"position": [
40,
40
]
},
"small": {
"id": "small",
"name": "bitbybit.occt.shapes.edge.createCircleEdge",
"customName": "circle edge",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 1.5,
"center": [
4,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {},
"position": [
40,
420
]
},
"wheels": {
"id": "wheels",
"name": "bitbybit.lists.createList",
"customName": "create list",
"async": false,
"drawable": false,
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "big",
"output": "result",
"data": {}
},
{
"node": "small",
"output": "result",
"data": {}
}
]
}
},
"position": [
460,
240
]
},
"ground": {
"id": "ground",
"name": "bitbybit.frame.zx",
"customName": "zx",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"origin": [
0,
0,
0
]
},
"inputs": {},
"position": [
460,
520
]
},
"belt": {
"id": "belt",
"name": "bitbybit.occt.shapes.edge.linesTangentToTwo",
"customName": "lines tangent to two",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"angularTolerance": 0.000001,
"onArgumentsOnly": false
},
"inputs": {
"shapes": {
"connections": [
{
"node": "wheels",
"output": "list",
"data": {}
}
]
},
"frame": {
"connections": [
{
"node": "ground",
"output": "result",
"data": {}
}
]
}
},
"position": [
880,
240
]
}
},
"modules": {}
}

To build the belt itself, take the two outer lines from the list, trim the circles to the arcs between the touch points, and join the four edges into a wire with bitbybit.occt.shapes.wire.combineEdgesAndWiresIntoAWire.

The older constraint functions​

The constraintTan... functions of earlier versions, such as constraintTanLinesOnTwoCircles, still work, but are deprecated and will be removed in a future major version. Each has a counterpart above, which takes a frame instead of assuming the ground and gives every solution.