Edge Constraints
Edge constraints in OCCT (Open CASCADE Technology) provide powerful geometric constraint solving capabilities for creating tangent lines and circles based on existing geometric entities. These operations are essential for parametric modeling, geometric construction, and constraint-based design workflows.
Overview
Edge constraints help you create geometry that follows specific rules or relationships with existing shapes. Think of them as intelligent drawing tools that automatically calculate where new lines or circles should be placed to maintain tangent relationships with your existing geometry.
The system offers five main constraint operations that solve common geometric problems. You can create tangent lines between points and circles, tangent lines between two circles, and even tangent circles that touch existing circles or points. Each operation automatically calculates the mathematically correct positions and orientations.
Understanding the Examples
Each constraint operation is demonstrated using three different programming approaches. The Rete interface lets you build constraint solutions visually by connecting nodes. Blockly provides a block-based approach that's great for learning the logical flow. TypeScript gives you direct code control for advanced customization and integration into larger projects.
All examples use similar patterns - they create the base geometry (circles and points), set up the constraint parameters, execute the constraint operation, and then display the results. The constraint functions handle all the complex mathematical calculations automatically.
Working with Tolerance and Precision
Most constraint operations include a tolerance setting that controls how precisely the calculations are performed. The default value works well for most situations, but you might need to adjust it when working with very large or very small geometry. Think of tolerance as how "strict" the geometric relationships need to be.
Constraint Tangent Lines from Two Points to Circle
This operation solves a classic geometric problem: given two points and a circle, find the lines that connect both points and are tangent to the circle. The function automatically calculates all possible solutions and returns the tangent lines.
This is particularly useful in mechanical design when you need to connect two specific locations with smooth curves that don't intersect existing circular features.
- Rete
- Blockly
- TypeScript
{
"id": "rete-v2-json",
"nodes": {
"0be30c1a2380af3a": {
"id": "0be30c1a2380af3a",
"name": "bitbybit.occt.shapes.edge.constraintTanLinesFromTwoPtsToCircle",
"customName": "constraint tan lines from two pts to circle",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"tolerance": 1e-7,
"positionResult": "all",
"circleRemainder": "none"
},
"inputs": {
"point2": {
"connections": [
{
"node": "9beccb7e88a01228",
"output": "result",
"data": {}
}
]
},
"point1": {
"connections": [
{
"node": "249f184a4a2d34a2",
"output": "result",
"data": {}
}
]
},
"circle": {
"connections": [
{
"node": "be968690cada3446",
"output": "result",
"data": {}
}
]
}
},
"position": [
1964.2421845834122,
707.6536356095846
]
},
"be968690cada3446": {
"id": "be968690cada3446",
"name": "bitbybit.occt.shapes.edge.createCircleEdge",
"customName": "circle edge",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 4,
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {},
"position": [
1274.4210202419606,
397.62302689075284
]
},
"9beccb7e88a01228": {
"id": "9beccb7e88a01228",
"name": "bitbybit.point.pointXYZ",
"customName": "point xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 9,
"y": 0,
"z": 9
},
"inputs": {},
"position": [
1270.789651089078,
1103.1208819773626
]
},
"249f184a4a2d34a2": {
"id": "249f184a4a2d34a2",
"name": "bitbybit.point.pointXYZ",
"customName": "point xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 0,
"z": 7
},
"inputs": {},
"position": [
1271.2543385554595,
752.6047103743216
]
}
}
}
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable id="circle">circle</variable><variable id="point1">point1</variable><variable id="point2">point2</variable><variable id="tangentLines">tangentLines</variable></variables><block type="variables_set" id="create_circle" x="-604" y="-349"><field name="VAR" id="circle">circle</field><value name="VALUE"><block type="base_time_await_return" id="await_circle"><value name="Promise"><block type="bitbybit.occt.shapes.edge.createCircleEdge" id="circle_edge"><value name="Radius"><block type="math_number" id="radius_val"><field name="NUM">4</field></block></value><value name="Center"><block type="bitbybit.point.pointXYZ" id="circle_center"><value name="X"><block type="math_number" id="center_x"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="center_y"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="center_z"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="circle_direction"><value name="X"><block type="math_number" id="dir_x"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="dir_y"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="dir_z"><field name="NUM">0</field></block></value></block></value></block></value></block></value><next><block type="variables_set" id="set_point1"><field name="VAR" id="point1">point1</field><value name="VALUE"><block type="bitbybit.point.pointXYZ" id="point1_xyz"><value name="X"><block type="math_number" id="point1_x"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="point1_y"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="point1_z"><field name="NUM">7</field></block></value></block></value><next><block type="variables_set" id="set_point2"><field name="VAR" id="point2">point2</field><value name="VALUE"><block type="bitbybit.point.pointXYZ" id="point2_xyz"><value name="X"><block type="math_number" id="point2_x"><field name="NUM">9</field></block></value><value name="Y"><block type="math_number" id="point2_y"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="point2_z"><field name="NUM">9</field></block></value></block></value><next><block type="variables_set" id="create_tangent_lines"><field name="VAR" id="tangentLines">tangentLines</field><value name="VALUE"><block type="base_time_await_return" id="await_tangent_lines"><value name="Promise"><block type="bitbybit.occt.shapes.edge.constraintTanLinesFromTwoPtsToCircle" id="Z8Pm$?Q6=3yn{YZ$SETY"><value name="Circle"><block type="variables_get" id="get_circle"><field name="VAR" id="circle">circle</field></block></value><value name="Point1"><block type="variables_get" id="get_point1"><field name="VAR" id="point1">point1</field></block></value><value name="Point2"><block type="variables_get" id="get_point2"><field name="VAR" id="point2">point2</field></block></value><value name="Tolerance"><block type="math_number" id="!,@^_v48JhDk|wh9h18L"><field name="NUM">1e-7</field></block></value><value name="PositionResult"><block type="bitbybit.occt.enums.positionResultEnum" id="5$75]G^!!fu`v-Ns0C`E"><field name="bitbybit.occt.enums.positionResultEnum">'all'</field></block></value><value name="CircleRemainder"><block type="bitbybit.occt.enums.circleInclusionEnum" id="HkhOy9w:3W{PU%(C)J4x"><field name="bitbybit.occt.enums.circleInclusionEnum">'none'</field></block></value></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_tangent_lines"><value name="Entity"><block type="variables_get" id="get_tangent_lines"><field name="VAR" id="tangentLines">tangentLines</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_circle"><value name="Entity"><block type="variables_get" id="get_circle_draw"><field name="VAR" id="circle">circle</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_points"><value name="Entity"><block type="variables_get" id="get_point1_draw"><field name="VAR" id="point1">point1</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="|Ln;9N)$?s!.o8qDb71~"><value name="Entity"><block type="variables_get" id="+zS+*Z2NHEUiIN}dLy,_"><field name="VAR" id="point2">point2</field></block></value></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></xml>
const { CircleDto, ConstraintTanLinesFromTwoPtsToCircleDto, positionResultEnum, circleInclusionEnum } = Bit.Inputs.OCCT;
// Import required types
type Point3 = Bit.Inputs.Base.Point3;
type Vector3 = Bit.Inputs.Base.Vector3;
type TopoDSEdgePointer = Bit.Inputs.OCCT.TopoDSEdgePointer;
// Define the main function
const start = async () => {
// Create a circle edge
const circleOptions = new CircleDto();
circleOptions.radius = 4;
circleOptions.center = [0, 0, 0] as Point3;
circleOptions.direction = [0, 1, 0] as Vector3;
const circle = await bitbybit.occt.shapes.edge.createCircleEdge(circleOptions);
// Define two points
const point1: Point3 = [0, 0, 7];
const point2: Point3 = [9, 0, 9];
// Create constraint options for tangent lines from two points to circle
const constraintOptions = new ConstraintTanLinesFromTwoPtsToCircleDto<TopoDSEdgePointer>();
constraintOptions.circle = circle;
constraintOptions.point1 = point1;
constraintOptions.point2 = point2;
constraintOptions.tolerance = 1e-7;
constraintOptions.positionResult = positionResultEnum.all;
constraintOptions.circleRemainder = circleInclusionEnum.none;
// Create the constraint tangent lines
const tangentLines = await bitbybit.occt.shapes.edge.constraintTanLinesFromTwoPtsToCircle(constraintOptions);
// Draw the tangent lines
bitbybit.draw.drawAnyAsync({ entity: tangentLines });
// Draw the circle
bitbybit.draw.drawAnyAsync({ entity: circle });
// Draw the two points
bitbybit.draw.drawAnyAsync({ entity: [point1] });
bitbybit.draw.drawAnyAsync({ entity: [point2] });
}
// Execute the function
start();
Constraint Tangent Lines from Point to Circle
When you need to draw lines from a single point that just touch a circle without crossing it, this constraint operation provides the solution. It's simpler than the two-point version and automatically finds both possible tangent lines from your point to the circle.
This operation is commonly used in architectural drawings when you need to create sight lines or in mechanical design for clearance calculations.
- Rete
- Blockly
- TypeScript
{
"id": "rete-v2-json",
"nodes": {
"be968690cada3446": {
"id": "be968690cada3446",
"name": "bitbybit.occt.shapes.edge.createCircleEdge",
"customName": "circle edge",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 4,
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {},
"position": [
1274.4210202419606,
397.62302689075284
]
},
"249f184a4a2d34a2": {
"id": "249f184a4a2d34a2",
"name": "bitbybit.point.pointXYZ",
"customName": "point xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 8,
"y": 0,
"z": 7
},
"inputs": {},
"position": [
1271.2543385554595,
752.6047103743216
]
},
"592dbbb1c41d8690": {
"id": "592dbbb1c41d8690",
"name": "bitbybit.occt.shapes.edge.constraintTanLinesFromPtToCircle",
"customName": "constraint tan lines from pt to circle",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"tolerance": 1e-7,
"positionResult": "all",
"circleRemainder": "none"
},
"inputs": {
"circle": {
"connections": [
{
"node": "be968690cada3446",
"output": "result",
"data": {}
}
]
},
"point": {
"connections": [
{
"node": "249f184a4a2d34a2",
"output": "result",
"data": {}
}
]
}
},
"position": [
1824.4560970772618,
562.1674808007256
]
}
}
}
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable id="circle">circle</variable><variable id="point">point</variable><variable id="tangentLines">tangentLines</variable></variables><block type="variables_set" id="create_circle" x="-604" y="-349"><field name="VAR" id="circle">circle</field><value name="VALUE"><block type="base_time_await_return" id="await_circle"><value name="Promise"><block type="bitbybit.occt.shapes.edge.createCircleEdge" id="circle_edge"><value name="Radius"><block type="math_number" id="radius_val"><field name="NUM">4</field></block></value><value name="Center"><block type="bitbybit.point.pointXYZ" id="circle_center"><value name="X"><block type="math_number" id="center_x"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="center_y"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="center_z"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="circle_direction"><value name="X"><block type="math_number" id="dir_x"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="dir_y"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="dir_z"><field name="NUM">0</field></block></value></block></value></block></value></block></value><next><block type="variables_set" id="set_point"><field name="VAR" id="point">point</field><value name="VALUE"><block type="bitbybit.point.pointXYZ" id="point_xyz"><value name="X"><block type="math_number" id="point_x"><field name="NUM">8</field></block></value><value name="Y"><block type="math_number" id="point_y"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="point_z"><field name="NUM">7</field></block></value></block></value><next><block type="variables_set" id="create_tangent_lines"><field name="VAR" id="tangentLines">tangentLines</field><value name="VALUE"><block type="base_time_await_return" id="await_tangent_lines"><value name="Promise"><block type="bitbybit.occt.shapes.edge.constraintTanLinesFromPtToCircle" id="constraint_tangent_lines"><value name="Circle"><block type="variables_get" id="get_circle"><field name="VAR" id="circle">circle</field></block></value><value name="Point"><block type="variables_get" id="get_point"><field name="VAR" id="point">point</field></block></value><value name="Tolerance"><block type="math_number" id="tolerance_val"><field name="NUM">1e-7</field></block></value><value name="PositionResult"><block type="bitbybit.occt.enums.positionResultEnum" id="position_result_val"><field name="bitbybit.occt.enums.positionResultEnum">'all'</field></block></value><value name="CircleRemainder"><block type="bitbybit.occt.enums.circleInclusionEnum" id="circle_remainder_val"><field name="bitbybit.occt.enums.circleInclusionEnum">'none'</field></block></value></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_tangent_lines"><value name="Entity"><block type="variables_get" id="get_tangent_lines"><field name="VAR" id="tangentLines">tangentLines</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_circle"><value name="Entity"><block type="variables_get" id="get_circle_draw"><field name="VAR" id="circle">circle</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_point"><value name="Entity"><block type="variables_get" id="get_point_draw"><field name="VAR" id="point">point</field></block></value></block></next></block></next></block></next></block></next></block></next></block></xml>
const { CircleDto, ConstraintTanLinesFromPtToCircleDto, positionResultEnum, circleInclusionEnum } = Bit.Inputs.OCCT;
// Import required types
type Point3 = Bit.Inputs.Base.Point3;
type Vector3 = Bit.Inputs.Base.Vector3;
type TopoDSEdgePointer = Bit.Inputs.OCCT.TopoDSEdgePointer;
// Define the main function
const start = async () => {
// Create a circle edge
const circleOptions = new CircleDto();
circleOptions.radius = 4;
circleOptions.center = [0, 0, 0] as Point3;
circleOptions.direction = [0, 1, 0] as Vector3;
const circle = await bitbybit.occt.shapes.edge.createCircleEdge(circleOptions);
// Define a point
const point: Point3 = [8, 0, 7];
// Create constraint options for tangent lines from point to circle
const constraintOptions = new ConstraintTanLinesFromPtToCircleDto<TopoDSEdgePointer>();
constraintOptions.circle = circle;
constraintOptions.point = point;
constraintOptions.tolerance = 1e-7;
constraintOptions.positionResult = positionResultEnum.all;
constraintOptions.circleRemainder = circleInclusionEnum.none;
// Create the constraint tangent lines
const tangentLines = await bitbybit.occt.shapes.edge.constraintTanLinesFromPtToCircle(constraintOptions);
// Draw the tangent lines
bitbybit.draw.drawAnyAsync({ entity: tangentLines });
// Draw the circle
bitbybit.draw.drawAnyAsync({ entity: circle });
// Draw the point
bitbybit.draw.drawAnyAsync({ entity: point });
}
// Execute the function
start();
Constraint Tangent Lines on Two Circles
This operation finds all the lines that touch two circles without crossing them. Depending on how the circles are positioned relative to each other, you might get external tangent lines (that don't pass between the circles) or internal tangent lines (that cross between them).
This is especially valuable in gear design, pulley systems, or any mechanical application where you need smooth transitions between circular components.
- Rete
- Blockly
- TypeScript
{
"id": "rete-v2-json",
"nodes": {
"be968690cada3446": {
"id": "be968690cada3446",
"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": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {},
"position": [
683.1370467145987,
165.9470538854013
]
},
"a8c5b2c7d1a9e3f4": {
"id": "a8c5b2c7d1a9e3f4",
"name": "bitbybit.occt.shapes.edge.createCircleEdge",
"customName": "circle edge",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 2,
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {
"center": {
"connections": [
{
"node": "885c6bb2a3ed276b",
"output": "result",
"data": {}
}
]
}
},
"position": [
685.6543210987654,
654.3210987654321
]
},
"f9b3c6d8e4a7f5b2": {
"id": "f9b3c6d8e4a7f5b2",
"name": "bitbybit.occt.shapes.edge.constraintTanLinesOnTwoCircles",
"customName": "constraint tan lines on two circles",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"tolerance": 1e-7,
"positionResult": "all",
"circleRemainders": "none"
},
"inputs": {
"circle1": {
"connections": [
{
"node": "be968690cada3446",
"output": "result",
"data": {}
}
]
},
"circle2": {
"connections": [
{
"node": "a8c5b2c7d1a9e3f4",
"output": "result",
"data": {}
}
]
}
},
"position": [
1249.6118955520265,
407.9391878009695
]
},
"885c6bb2a3ed276b": {
"id": "885c6bb2a3ed276b",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 7,
"y": 0,
"z": 0
},
"inputs": {},
"position": [
306.92934870803884,
696.3229806735962
]
}
}
}
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable id="circle1">circle1</variable><variable id="circle2">circle2</variable><variable id="tangentLines">tangentLines</variable></variables><block type="variables_set" id="create_circle1" x="-604" y="-349"><field name="VAR" id="circle1">circle1</field><value name="VALUE"><block type="base_time_await_return" id="await_circle1"><value name="Promise"><block type="bitbybit.occt.shapes.edge.createCircleEdge" id="circle_edge1"><value name="Radius"><block type="math_number" id="radius_val1"><field name="NUM">3</field></block></value><value name="Center"><block type="bitbybit.point.pointXYZ" id="circle_center1"><value name="X"><block type="math_number" id="center_x1"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="center_y1"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="center_z1"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="circle_direction1"><value name="X"><block type="math_number" id="dir_x1"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="dir_y1"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="dir_z1"><field name="NUM">0</field></block></value></block></value></block></value></block></value><next><block type="variables_set" id="create_circle2"><field name="VAR" id="circle2">circle2</field><value name="VALUE"><block type="base_time_await_return" id="await_circle2"><value name="Promise"><block type="bitbybit.occt.shapes.edge.createCircleEdge" id="circle_edge2"><value name="Radius"><block type="math_number" id="radius_val2"><field name="NUM">2</field></block></value><value name="Center"><block type="bitbybit.point.pointXYZ" id="circle_center2"><value name="X"><block type="math_number" id="center_x2"><field name="NUM">7</field></block></value><value name="Y"><block type="math_number" id="center_y2"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="center_z2"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="circle_direction2"><value name="X"><block type="math_number" id="dir_x2"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="dir_y2"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="dir_z2"><field name="NUM">0</field></block></value></block></value></block></value></block></value><next><block type="variables_set" id="create_tangent_lines"><field name="VAR" id="tangentLines">tangentLines</field><value name="VALUE"><block type="base_time_await_return" id="await_tangent_lines"><value name="Promise"><block type="bitbybit.occt.shapes.edge.constraintTanLinesOnTwoCircles" id="constraint_tangent_lines"><value name="Circle1"><block type="variables_get" id="get_circle1"><field name="VAR" id="circle1">circle1</field></block></value><value name="Circle2"><block type="variables_get" id="get_circle2"><field name="VAR" id="circle2">circle2</field></block></value><value name="Tolerance"><block type="math_number" id="tolerance_val"><field name="NUM">1e-7</field></block></value><value name="PositionResult"><block type="bitbybit.occt.enums.positionResultEnum" id="position_result_val"><field name="bitbybit.occt.enums.positionResultEnum">'all'</field></block></value><value name="CircleRemainders"><block type="bitbybit.occt.enums.twoCircleInclusionEnum" id="circle_remainders_val"><field name="bitbybit.occt.enums.twoCircleInclusionEnum">'none'</field></block></value></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_tangent_lines"><value name="Entity"><block type="variables_get" id="get_tangent_lines"><field name="VAR" id="tangentLines">tangentLines</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_circle1"><value name="Entity"><block type="variables_get" id="get_circle1_draw"><field name="VAR" id="circle1">circle1</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_circle2"><value name="Entity"><block type="variables_get" id="get_circle2_draw"><field name="VAR" id="circle2">circle2</field></block></value></block></next></block></next></block></next></block></next></block></next></block></xml>
const { CircleDto, ConstraintTanLinesOnTwoCirclesDto, positionResultEnum, twoCircleInclusionEnum } = Bit.Inputs.OCCT;
// Import required types
type Point3 = Bit.Inputs.Base.Point3;
type Vector3 = Bit.Inputs.Base.Vector3;
type TopoDSEdgePointer = Bit.Inputs.OCCT.TopoDSEdgePointer;
// Define the main function
const start = async () => {
// Create first circle edge
const circle1Options = new CircleDto();
circle1Options.radius = 3;
circle1Options.center = [0, 0, 0] as Point3;
circle1Options.direction = [0, 1, 0] as Vector3;
const circle1 = await bitbybit.occt.shapes.edge.createCircleEdge(circle1Options);
// Create second circle edge
const circle2Options = new CircleDto();
circle2Options.radius = 2;
circle2Options.center = [7, 0, 0] as Point3;
circle2Options.direction = [0, 1, 0] as Vector3;
const circle2 = await bitbybit.occt.shapes.edge.createCircleEdge(circle2Options);
// Create constraint options for tangent lines between two circles
const constraintOptions = new ConstraintTanLinesOnTwoCirclesDto<TopoDSEdgePointer>();
constraintOptions.circle1 = circle1;
constraintOptions.circle2 = circle2;
constraintOptions.tolerance = 1e-7;
constraintOptions.positionResult = positionResultEnum.all;
constraintOptions.circleRemainders = twoCircleInclusionEnum.none;
// Create the constraint tangent lines
const tangentLines = await bitbybit.occt.shapes.edge.constraintTanLinesOnTwoCircles(constraintOptions);
// Draw the tangent lines
bitbybit.draw.drawAnyAsync({ entity: tangentLines });
// Draw the first circle
bitbybit.draw.drawAnyAsync({ entity: circle1 });
// Draw the second circle
bitbybit.draw.drawAnyAsync({ entity: circle2 });
}
// Execute the function
start();
Constraint Tangent Circles on Two Circles
Sometimes you need to create circles that touch two existing circles. This operation calculates where to place new circles of a specified size so they're tangent to both input circles. You control the radius of the new circles, and the system figures out all the valid positions.
This is particularly useful for creating buffer zones around existing circular features or for designing complex mechanical linkages where multiple circular components need to interact smoothly.
- Rete
- Blockly
- TypeScript
{
"id": "rete-v2-json",
"nodes": {
"a1b2c3d4e5f6g7h8": {
"id": "a1b2c3d4e5f6g7h8",
"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": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {},
"position": [
683.1370467145987,
165.9470538854013
]
},
"b2c3d4e5f6g7h8i9": {
"id": "b2c3d4e5f6g7h8i9",
"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": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {
"center": {
"connections": [
{
"node": "9fb306c7e1feb87a",
"output": "result",
"data": {}
}
]
}
},
"position": [
685.6543210987654,
654.3210987654321
]
},
"c3d4e5f6g7h8i9j0": {
"id": "c3d4e5f6g7h8i9j0",
"name": "bitbybit.occt.shapes.edge.constraintTanCirclesOnTwoCircles",
"customName": "constraint tan circles on two circles",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"tolerance": 1e-7,
"radius": 0.8
},
"inputs": {
"circle1": {
"connections": [
{
"node": "a1b2c3d4e5f6g7h8",
"output": "result",
"data": {}
}
]
},
"circle2": {
"connections": [
{
"node": "b2c3d4e5f6g7h8i9",
"output": "result",
"data": {}
}
]
}
},
"position": [
1224.2595753955707,
414.59942527677146
]
},
"9fb306c7e1feb87a": {
"id": "9fb306c7e1feb87a",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 5,
"y": 0,
"z": 0
},
"inputs": {},
"position": [
297.6273751492513,
695.974022780083
]
}
}
}
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable id="circle1">circle1</variable><variable id="circle2">circle2</variable><variable id="tangentCircles">tangentCircles</variable></variables><block type="variables_set" id="create_circle1" x="-604" y="-349"><field name="VAR" id="circle1">circle1</field><value name="VALUE"><block type="base_time_await_return" id="await_circle1"><value name="Promise"><block type="bitbybit.occt.shapes.edge.createCircleEdge" id="circle_edge1"><value name="Radius"><block type="math_number" id="radius_val1"><field name="NUM">3</field></block></value><value name="Center"><block type="bitbybit.point.pointXYZ" id="circle_center1"><value name="X"><block type="math_number" id="center_x1"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="center_y1"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="center_z1"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="circle_direction1"><value name="X"><block type="math_number" id="dir_x1"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="dir_y1"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="dir_z1"><field name="NUM">0</field></block></value></block></value></block></value></block></value><next><block type="variables_set" id="create_circle2"><field name="VAR" id="circle2">circle2</field><value name="VALUE"><block type="base_time_await_return" id="await_circle2"><value name="Promise"><block type="bitbybit.occt.shapes.edge.createCircleEdge" id="circle_edge2"><value name="Radius"><block type="math_number" id="radius_val2"><field name="NUM">1.5</field></block></value><value name="Center"><block type="bitbybit.point.pointXYZ" id="circle_center2"><value name="X"><block type="math_number" id="center_x2"><field name="NUM">5</field></block></value><value name="Y"><block type="math_number" id="center_y2"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="center_z2"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="circle_direction2"><value name="X"><block type="math_number" id="dir_x2"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="dir_y2"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="dir_z2"><field name="NUM">0</field></block></value></block></value></block></value></block></value><next><block type="variables_set" id="create_tangent_circles"><field name="VAR" id="tangentCircles">tangentCircles</field><value name="VALUE"><block type="base_time_await_return" id="await_tangent_circles"><value name="Promise"><block type="bitbybit.occt.shapes.edge.constraintTanCirclesOnTwoCircles" id="constraint_tangent_circles"><value name="Circle1"><block type="variables_get" id="get_circle1"><field name="VAR" id="circle1">circle1</field></block></value><value name="Circle2"><block type="variables_get" id="get_circle2"><field name="VAR" id="circle2">circle2</field></block></value><value name="Tolerance"><block type="math_number" id="tolerance_val"><field name="NUM">1e-7</field></block></value><value name="Radius"><block type="math_number" id="radius_val"><field name="NUM">0.8</field></block></value></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_tangent_circles"><value name="Entity"><block type="variables_get" id="get_tangent_circles"><field name="VAR" id="tangentCircles">tangentCircles</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_circle1"><value name="Entity"><block type="variables_get" id="get_circle1_draw"><field name="VAR" id="circle1">circle1</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_circle2"><value name="Entity"><block type="variables_get" id="get_circle2_draw"><field name="VAR" id="circle2">circle2</field></block></value></block></next></block></next></block></next></block></next></block></next></block></xml>
const { CircleDto, ConstraintTanCirclesOnTwoCirclesDto } = Bit.Inputs.OCCT;
// Import required types
type Point3 = Bit.Inputs.Base.Point3;
type Vector3 = Bit.Inputs.Base.Vector3;
type TopoDSEdgePointer = Bit.Inputs.OCCT.TopoDSEdgePointer;
// Define the main function
const start = async () => {
// Create first circle edge
const circle1Options = new CircleDto();
circle1Options.radius = 3;
circle1Options.center = [0, 0, 0] as Point3;
circle1Options.direction = [0, 1, 0] as Vector3;
const circle1 = await bitbybit.occt.shapes.edge.createCircleEdge(circle1Options);
// Create second circle edge
const circle2Options = new CircleDto();
circle2Options.radius = 1.5;
circle2Options.center = [5, 0, 0] as Point3;
circle2Options.direction = [0, 1, 0] as Vector3;
const circle2 = await bitbybit.occt.shapes.edge.createCircleEdge(circle2Options);
// Create constraint options for tangent circles between two circles
const constraintOptions = new ConstraintTanCirclesOnTwoCirclesDto<TopoDSEdgePointer>();
constraintOptions.circle1 = circle1;
constraintOptions.circle2 = circle2;
constraintOptions.tolerance = 1e-7;
constraintOptions.radius = 0.8;
// Create the constraint tangent circles
const tangentCircles = await bitbybit.occt.shapes.edge.constraintTanCirclesOnTwoCircles(constraintOptions);
// Draw the tangent circles
bitbybit.draw.drawAnyAsync({ entity: tangentCircles });
// Draw the first circle
bitbybit.draw.drawAnyAsync({ entity: circle1 });
// Draw the second circle
bitbybit.draw.drawAnyAsync({ entity: circle2 });
}
// Execute the function
start();
Constraint Tangent Circles on Circle and Point
This operation creates circles that touch an existing circle and are positioned relative to a specific point. The new circles will be tangent to your input circle and either pass through the point or maintain a specific relationship with it, depending on the radius you specify.
This constraint is perfect for creating rounded transitions in designs where you need a smooth connection between a circular feature and a specific location in your model.
- Rete
- Blockly
- TypeScript
{
"id": "rete-v2-json",
"nodes": {
"d4e5f6g7h8i9j0k1": {
"id": "d4e5f6g7h8i9j0k1",
"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": [
0,
0,
0
],
"direction": [
0,
1,
0
]
},
"inputs": {},
"position": [
683.1370467145987,
165.9470538854013
]
},
"e5f6g7h8i9j0k1l2": {
"id": "e5f6g7h8i9j0k1l2",
"name": "bitbybit.point.pointXYZ",
"customName": "point xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 4,
"y": 0,
"z": 0
},
"inputs": {},
"position": [
683.6543210987654,
654.3210987654321
]
},
"f6g7h8i9j0k1l2m3": {
"id": "f6g7h8i9j0k1l2m3",
"name": "bitbybit.occt.shapes.edge.constraintTanCirclesOnCircleAndPnt",
"customName": "constraint tan circles on circle and pnt",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"tolerance": 1e-7,
"radius": 2
},
"inputs": {
"circle": {
"connections": [
{
"node": "d4e5f6g7h8i9j0k1",
"output": "result",
"data": {}
}
]
},
"point": {
"connections": [
{
"node": "e5f6g7h8i9j0k1l2",
"output": "result",
"data": {}
}
]
}
},
"position": [
1443.2109876543211,
410.9876543210988
]
}
}
}
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable id="circle">circle</variable><variable id="point">point</variable><variable id="tangentCircles">tangentCircles</variable></variables><block type="variables_set" id="create_circle" x="-604" y="-349"><field name="VAR" id="circle">circle</field><value name="VALUE"><block type="base_time_await_return" id="await_circle"><value name="Promise"><block type="bitbybit.occt.shapes.edge.createCircleEdge" id="circle_edge"><value name="Radius"><block type="math_number" id="radius_val"><field name="NUM">3</field></block></value><value name="Center"><block type="bitbybit.point.pointXYZ" id="circle_center"><value name="X"><block type="math_number" id="center_x"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="center_y"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="center_z"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="circle_direction"><value name="X"><block type="math_number" id="dir_x"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="dir_y"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="dir_z"><field name="NUM">0</field></block></value></block></value></block></value></block></value><next><block type="variables_set" id="set_point"><field name="VAR" id="point">point</field><value name="VALUE"><block type="bitbybit.point.pointXYZ" id="point_xyz"><value name="X"><block type="math_number" id="point_x"><field name="NUM">4</field></block></value><value name="Y"><block type="math_number" id="point_y"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="point_z"><field name="NUM">0</field></block></value></block></value><next><block type="variables_set" id="create_tangent_circles"><field name="VAR" id="tangentCircles">tangentCircles</field><value name="VALUE"><block type="base_time_await_return" id="await_tangent_circles"><value name="Promise"><block type="bitbybit.occt.shapes.edge.constraintTanCirclesOnCircleAndPnt" id="constraint_tangent_circles"><value name="Circle"><block type="variables_get" id="get_circle"><field name="VAR" id="circle">circle</field></block></value><value name="Point"><block type="variables_get" id="get_point"><field name="VAR" id="point">point</field></block></value><value name="Tolerance"><block type="math_number" id="tolerance_val"><field name="NUM">1e-7</field></block></value><value name="Radius"><block type="math_number" id="U-2gOwN@2`{{|E*7YzDV"><field name="NUM">2</field></block></value></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_tangent_circles"><value name="Entity"><block type="variables_get" id="get_tangent_circles"><field name="VAR" id="tangentCircles">tangentCircles</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_circle"><value name="Entity"><block type="variables_get" id="get_circle_draw"><field name="VAR" id="circle">circle</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="draw_point"><value name="Entity"><block type="variables_get" id="get_point_draw"><field name="VAR" id="point">point</field></block></value></block></next></block></next></block></next></block></next></block></next></block></xml>
const { CircleDto, ConstraintTanCirclesOnCircleAndPntDto } = Bit.Inputs.OCCT;
// Import required types
type Point3 = Bit.Inputs.Base.Point3;
type Vector3 = Bit.Inputs.Base.Vector3;
type TopoDSEdgePointer = Bit.Inputs.OCCT.TopoDSEdgePointer;
// Define the main function
const start = async () => {
// Create a circle edge
const circleOptions = new CircleDto();
circleOptions.radius = 3;
circleOptions.center = [0, 0, 0] as Point3;
circleOptions.direction = [0, 1, 0] as Vector3;
const circle = await bitbybit.occt.shapes.edge.createCircleEdge(circleOptions);
// Define a point
const point: Point3 = [4, 0, 0];
// Create constraint options for tangent circles between circle and point
const constraintOptions = new ConstraintTanCirclesOnCircleAndPntDto<TopoDSEdgePointer>();
constraintOptions.circle = circle;
constraintOptions.point = point;
constraintOptions.tolerance = 1e-7;
constraintOptions.radius = 2;
// Create the constraint tangent circles
const tangentCircles = await bitbybit.occt.shapes.edge.constraintTanCirclesOnCircleAndPnt(constraintOptions);
// Draw the tangent circles
bitbybit.draw.drawAnyAsync({ entity: tangentCircles });
// Draw the circle
bitbybit.draw.drawAnyAsync({ entity: circle });
// Draw the point
bitbybit.draw.drawAnyAsync({ entity: point });
}
// Execute the function
start();
Getting the Best Results
Working with Precision
The default precision settings work well for most projects. If you're working with very large structures like buildings, you might want to be a bit less strict with the precision. For tiny, detailed mechanical parts, you might need more precision. Think of it like adjusting the zoom level on your calculations.
Choosing Which Solutions to Keep
Many constraint operations find multiple valid solutions. You can ask for all of them to see your options, or specify that you only want the first or second solution if you know which arrangement you prefer. This is especially helpful when you're building parametric models where consistency matters.
Understanding Circle Splitting
Some operations can optionally split your input circles at the points where the tangent lines touch them. This creates separate circle segments that you can use for other operations. Most of the time you won't need this feature, but it's there when you do.
Sizing Tangent Circles
When creating tangent circles, start with smaller sizes to understand how the geometry behaves. You can always increase the radius once you see how the circles position themselves. Very large circles might not have valid tangent solutions depending on your input geometry.
Real-World Applications
These constraint operations solve problems that come up frequently in design work. Architects use them for creating smooth transitions in floor plans. Mechanical engineers use them for designing gear systems and smooth mechanical linkages. Even in artistic applications, they help create flowing, mathematically precise curves and connections.
Performance Tips
Constraint calculations can take some time with complex geometry. It's a good idea to test your setup with simple shapes first, then apply the same approach to your full model. This helps you catch any setup issues early and ensures your final results will be what you expect.
Building Complete Workflows
Think of edge constraints as one tool in a larger toolkit. They excel at solving specific geometric relationship problems, and they integrate seamlessly with other modeling operations to help you build exactly what you envision. The mathematical precision they provide becomes the foundation for reliable, parametric design workflows in BitByBit.



