diff --git a/e2e/image-plan-gate.spec.ts b/e2e/image-plan-gate.spec.ts new file mode 100644 index 0000000..42a49ba --- /dev/null +++ b/e2e/image-plan-gate.spec.ts @@ -0,0 +1,37 @@ +import { expect, test } from "@playwright/test"; + +test("image design rejects CAD and incomplete plans before rendering a mapped spec sheet", async ({ page }) => { + test.setTimeout(600_000); + await page.goto("/"); + await page.getByTestId("sidebar").getByRole("button", { name: "New chat", exact: true }).first().click(); + const composer = page.getByTestId("composer-input"); + await expect(composer).toBeEnabled(); + await composer.fill("image-plan-gate: build the dimensioned spacer in this drawing"); + await page.getByTestId("composer-file-input").setInputFiles({ + name: "spacer.png", + mimeType: "image/png", + buffer: Buffer.from( + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=", + "base64", + ), + }); + await page.getByTestId("composer-send").click(); + + const rejectedRun = page.getByTestId("tool-call-card").filter({ hasText: "run_build123d" }).filter({ hasText: "Failed" }); + await expect(rejectedRun).toContainText("update_plan", { timeout: 600_000 }); + await expect(rejectedRun).toContainText("spec sheet"); + + const rejectedPlan = page.getByTestId("tool-call-card").filter({ hasText: "update_plan" }).filter({ hasText: "Failed" }); + await expect(rejectedPlan).toContainText("spec_sheet is required", { timeout: 600_000 }); + + const planCard = page.getByTestId("plan-card"); + await expect(planCard).toBeVisible({ timeout: 600_000 }); + await expect(page.getByTestId("plan-progress")).toHaveText("1/1 components", { timeout: 600_000 }); + await page.getByTestId("plan-card-toggle").click(); + await expect(page.getByTestId("plan-spec-row")).toHaveCount(2); + await expect(page.getByTestId("plan-spec-check-link")).toContainText("spacer check 1"); + await expect(page.getByTestId("plan-spec-unverifiable")).toContainText("cannot measure surface finish"); + + const completedRun = page.getByTestId("tool-call-card").filter({ hasText: "run_build123d" }).filter({ hasText: "Complete" }); + await expect(completedRun.getByTestId("tool-gate")).toHaveAttribute("data-status", "passed", { timeout: 600_000 }); +}); diff --git a/package-lock.json b/package-lock.json index c271a92..90af88c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8546,6 +8546,12 @@ "node": "*" } }, + "node_modules/minisearch": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -12205,6 +12211,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "lucide-react": "^0.460.0", + "minisearch": "^7.2.0", "react": "^19.0.0", "react-dom": "^19.0.0", "streamdown": "^2.5.0", diff --git a/packages/client/doc-index/build123d-docs.json b/packages/client/doc-index/build123d-docs.json new file mode 100644 index 0000000..d124394 --- /dev/null +++ b/packages/client/doc-index/build123d-docs.json @@ -0,0 +1,50 @@ +{ + "docs_ref": "v0.11.1", + "source_files": [ + "docs/OpenSCAD.rst", + "docs/advanced.rst", + "docs/advantages.rst", + "docs/algebra_definition.rst", + "docs/algebra_performance.rst", + "docs/assemblies.rst", + "docs/build_line.rst", + "docs/build_part.rst", + "docs/build_sketch.rst", + "docs/builder_api_reference.rst", + "docs/builders.rst", + "docs/center.rst", + "docs/cheat_sheet.rst", + "docs/debugging_logging.rst", + "docs/direct_api_reference.rst", + "docs/examples_1.rst", + "docs/external.rst", + "docs/import_export.rst", + "docs/index.rst", + "docs/installation.rst", + "docs/introduction.rst", + "docs/introductory_examples.rst", + "docs/joints.rst", + "docs/key_concepts.rst", + "docs/key_concepts_algebra.rst", + "docs/key_concepts_builder.rst", + "docs/location_arithmetic.rst", + "docs/moving_objects.rst", + "docs/objects.rst", + "docs/operations.rst", + "docs/selectors.rst", + "docs/tech_drawing_tutorial.rst", + "docs/tips.rst", + "docs/topology_selection.rst", + "docs/tttt.rst", + "docs/tutorial_constraints.rst", + "docs/tutorial_design.rst", + "docs/tutorial_joints.rst", + "docs/tutorial_lego.rst", + "docs/tutorial_selectors.rst", + "docs/tutorial_spitfire_wing_gordon.rst", + "docs/tutorial_stl_reconstruction.rst", + "docs/tutorial_surface_heart_token.rst", + "docs/tutorial_surface_modeling.rst", + "docs/tutorials.rst" + ] +} diff --git a/packages/client/doc-index/doc-synonyms.json b/packages/client/doc-index/doc-synonyms.json new file mode 100644 index 0000000..b878c89 --- /dev/null +++ b/packages/client/doc-index/doc-synonyms.json @@ -0,0 +1,50 @@ +[ + { + "terms": ["offset"], + "synonyms": ["shell", "hollow", "wall thickness"] + }, + { + "terms": ["Locations", "GridLocations", "PolarLocations"], + "synonyms": ["pattern", "array", "repeat"] + }, + { + "terms": ["sweep", "Mode.SUBTRACT"], + "synonyms": ["groove", "channel", "path cut"] + }, + { + "terms": ["loft"], + "synonyms": ["transition", "blend profiles", "cross sections"] + }, + { + "terms": ["revolve"], + "synonyms": ["lathe", "turned", "axisymmetric"] + }, + { + "terms": ["fillet", "chamfer"], + "synonyms": ["round edge", "bevel edge"] + }, + { + "terms": ["Hole", "CounterBoreHole", "CounterSinkHole"], + "synonyms": ["drill", "bore", "recessed fastener"] + }, + { + "terms": ["split"], + "synonyms": ["trim", "slice", "cut in half"] + }, + { + "terms": ["Spline", "BSpline"], + "synonyms": ["smooth curve", "control points", "interpolation"] + }, + { + "terms": ["Helix"], + "synonyms": ["spiral", "coil", "thread path"] + }, + { + "terms": ["mirror"], + "synonyms": ["symmetry", "reflect"] + }, + { + "terms": ["clearance", "offset"], + "synonyms": ["gap", "fit", "tolerance"] + } +] diff --git a/packages/client/doc-index/docIndex.mjs b/packages/client/doc-index/docIndex.mjs new file mode 100644 index 0000000..110c773 --- /dev/null +++ b/packages/client/doc-index/docIndex.mjs @@ -0,0 +1,203 @@ +import { readFile, writeFile } from "node:fs/promises"; +import { basename, dirname, posix, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import MiniSearch from "minisearch"; +import { BUILD123D_VERSION } from "../src/cad/versions.ts"; +import { DOC_INDEX_OPTIONS } from "../src/agent/docSearchConfig.ts"; + +export const INDEX_OPTIONS = DOC_INDEX_OPTIONS; + +const HEADING_ADORNMENT = /^([=\-`:.'"~^_*+#<>])\1{2,}$/; +const PYTHON_NON_APIS = new Set([ + "and", "as", "assert", "bool", "dict", "enumerate", "float", "for", "if", "in", "int", "len", + "list", "max", "min", "not", "or", "print", "range", "set", "str", "sum", "tuple", "zip", +]); + +function slugify(value) { + return value + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-|-$/g, "") || "section"; +} + +function extractApiNames(text) { + const names = new Set(); + const addQualified = (value) => { + const name = value.replace(/^~/, "").split(".").at(-1); + if (name && /^[A-Za-z_]\w*$/.test(name) && !PYTHON_NON_APIS.has(name)) names.add(name); + }; + + for (const match of text.matchAll(/:(?:attr|class|data|func|meth):`(?:[^<`]+<)?(~?[\w.]+)>?`/g)) { + addQualified(match[1]); + } + for (const match of text.matchAll(/^\s*\.\. auto(?:class|function|method)::\s+([\w.]+)/gm)) { + addQualified(match[1]); + } + for (const match of text.matchAll(/``([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)/g)) { + addQualified(match[1]); + } + for (const match of text.matchAll(/\b([A-Za-z_]\w*)\s*\(/g)) { + addQualified(match[1]); + } + return [...names].sort((a, b) => a.localeCompare(b)); +} + +function headingAt(lines, index) { + if (lines[index] !== lines[index]?.trim() || lines[index + 1] !== lines[index + 1]?.trim()) return undefined; + const title = lines[index]?.trim(); + const underline = lines[index + 1]?.trim(); + if (!title || !underline || !HEADING_ADORNMENT.test(underline) || underline.length < title.length) return undefined; + if (/^[.][.]\s/.test(title) || /^[+|]/.test(title)) return undefined; + const overline = lines[index - 1]?.trim(); + const hasOverline = overline === underline && HEADING_ADORNMENT.test(overline); + return { title, start: hasOverline ? index - 1 : index, bodyStart: index + 2 }; +} + +export function chunkRstDocument(sourcePath, source, synonymTable = []) { + const lines = source.replace(/\r\n?/g, "\n").replaceAll("\u2014", "-").split("\n"); + const headings = []; + for (let index = 0; index < lines.length - 1; index += 1) { + const heading = headingAt(lines, index); + if (heading) headings.push(heading); + } + + const sourceSlug = slugify(basename(sourcePath, posix.extname(sourcePath))); + const seenIds = new Map(); + return headings.map((heading, index) => { + const nextStart = headings[index + 1]?.start ?? lines.length; + const body = lines.slice(heading.bodyStart, nextStart).join("\n").trim(); + const baseId = `${sourceSlug}#${slugify(heading.title)}`; + const occurrence = (seenIds.get(baseId) ?? 0) + 1; + seenIds.set(baseId, occurrence); + const section_id = occurrence === 1 ? baseId : `${baseId}-${occurrence}`; + const api_names = extractApiNames(`${heading.title}\n${body}`); + const searchable = `${heading.title}\n${body}\n${api_names.join(" ")}`.toLowerCase(); + const synonyms = synonymTable + .filter((entry) => entry.terms.some((term) => searchable.includes(term.toLowerCase()))) + .flatMap((entry) => entry.synonyms) + .filter((value, synonymIndex, values) => values.indexOf(value) === synonymIndex) + .sort((a, b) => a.localeCompare(b)); + return { section_id, title: heading.title, body, api_names, synonyms }; + }); +} + +function selectIncludedLines(source, options) { + let lines = source.replace(/\r\n?/g, "\n").split("\n"); + const markerIndex = (marker) => lines.findIndex((line) => line.includes(marker)); + if (options["start-after"]) { + const index = markerIndex(options["start-after"]); + if (index < 0) throw new Error(`literalinclude start marker not found: ${options["start-after"]}`); + lines = lines.slice(index + 1); + } else if (options["start-at"]) { + const index = markerIndex(options["start-at"]); + if (index < 0) throw new Error(`literalinclude start marker not found: ${options["start-at"]}`); + lines = lines.slice(index); + } + if (options["end-before"]) { + const index = markerIndex(options["end-before"]); + if (index < 0) throw new Error(`literalinclude end marker not found: ${options["end-before"]}`); + lines = lines.slice(0, index); + } else if (options["end-at"]) { + const index = markerIndex(options["end-at"]); + if (index < 0) throw new Error(`literalinclude end marker not found: ${options["end-at"]}`); + lines = lines.slice(0, index + 1); + } + if (options.lines) { + const selected = []; + for (const part of options.lines.split(",")) { + const [startText, endText] = part.trim().split("-"); + const start = Number(startText); + const end = endText ? Number(endText) : start; + if (!Number.isInteger(start) || !Number.isInteger(end) || start < 1 || end < start) { + throw new Error(`invalid literalinclude lines option: ${options.lines}`); + } + selected.push(...lines.slice(start - 1, end)); + } + lines = selected; + } + return lines; +} + +export async function expandLiteralIncludes(sourcePath, source, readSource) { + const lines = source.replace(/\r\n?/g, "\n").split("\n"); + const output = []; + for (let index = 0; index < lines.length; index += 1) { + const match = lines[index].match(/^(\s*)\.\. literalinclude::\s+(.+?)\s*$/); + if (!match) { + output.push(lines[index]); + continue; + } + const [, indent, target] = match; + const options = {}; + while (index + 1 < lines.length) { + const option = lines[index + 1].match(/^\s+:([\w-]+):\s*(.*?)\s*$/); + if (!option) break; + options[option[1]] = option[2]; + index += 1; + } + const includePath = posix.normalize(posix.join(posix.dirname(sourcePath), target)); + const included = selectIncludedLines(await readSource(includePath), options); + const language = options.language || (posix.extname(includePath) === ".py" ? "python" : "text"); + output.push(`${indent}.. code-block:: ${language}`, ""); + output.push(...included.map((line) => `${indent} ${line}`)); + } + return output.join("\n"); +} + +export async function buildIndexAsset({ sourceFiles, synonymTable, readSource, version = BUILD123D_VERSION }) { + const chunks = []; + for (const sourcePath of [...sourceFiles].sort()) { + const expanded = await expandLiteralIncludes(sourcePath, await readSource(sourcePath), readSource); + chunks.push(...chunkRstDocument(sourcePath, expanded, synonymTable)); + } + chunks.sort((a, b) => a.section_id.localeCompare(b.section_id)); + + const index = new MiniSearch(INDEX_OPTIONS); + index.addAll(chunks.map((chunk) => ({ + ...chunk, + api_names: chunk.api_names.join(" "), + synonyms: chunk.synonyms.join(" "), + }))); + return { + format_version: 1, + attribution: { + project: "build123d", + version, + source: `https://github.com/gumyr/build123d/tree/v${version}/docs`, + license: "Apache-2.0", + }, + index: index.toJSON(), + }; +} + +async function main() { + const scriptDir = dirname(fileURLToPath(import.meta.url)); + const packageDir = resolve(scriptDir, ".."); + const config = JSON.parse(await readFile(resolve(scriptDir, "build123d-docs.json"), "utf8")); + if (config.docs_ref !== `v${BUILD123D_VERSION}`) { + throw new Error(`Docs ref ${config.docs_ref} does not match build123d ${BUILD123D_VERSION}`); + } + const synonymTable = JSON.parse(await readFile(resolve(scriptDir, "doc-synonyms.json"), "utf8")); + const cache = new Map(); + const readSource = async (sourcePath) => { + if (!cache.has(sourcePath)) { + const url = `https://raw.githubusercontent.com/gumyr/build123d/${config.docs_ref}/${sourcePath}`; + const response = await fetch(url); + if (!response.ok) throw new Error(`Failed to fetch ${url}: ${response.status}`); + cache.set(sourcePath, await response.text()); + } + return cache.get(sourcePath); + }; + const asset = await buildIndexAsset({ + sourceFiles: config.source_files, + synonymTable, + readSource, + }); + const outputPath = resolve(packageDir, "public/docs/build123d-index.json"); + await writeFile(outputPath, `${JSON.stringify(asset)}\n`, "utf8"); + process.stdout.write(`Generated ${asset.index.documentCount} sections at ${outputPath}\n`); +} + +if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + await main(); +} diff --git a/packages/client/doc-index/docIndex.test.mjs b/packages/client/doc-index/docIndex.test.mjs new file mode 100644 index 0000000..e185ac8 --- /dev/null +++ b/packages/client/doc-index/docIndex.test.mjs @@ -0,0 +1,111 @@ +import { readFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import MiniSearch from "minisearch"; +import { describe, expect, it } from "vitest"; +import { chunkRstDocument, INDEX_OPTIONS } from "./docIndex.mjs"; +import { DOC_SEARCH_OPTIONS } from "../src/agent/docSearchConfig.ts"; + +describe("build123d documentation chunking", () => { + it("keeps a code example with its heading section", () => { + const source = `Guide +===== + +Overview text. + +Loft between sections +--------------------- + +Use :func:\`~operations_part.loft\` for cross sections. + +.. code-block:: python + + result = loft(sections) + +Next operation +-------------- + +Use extrude here. +`; + + const chunks = chunkRstDocument("guide.rst", source); + const loft = chunks.find((chunk) => chunk.title === "Loft between sections"); + const next = chunks.find((chunk) => chunk.title === "Next operation"); + + expect(loft?.body).toContain("result = loft(sections)"); + expect(loft?.api_names).toContain("loft"); + expect(next?.body).not.toContain("result = loft(sections)"); + }); + + it("gives every chunk stable required fields", () => { + const chunks = chunkRstDocument("objects.rst", "Objects\n=======\n\nHelix\n-----\n\n``Helix(pitch, height, radius)``\n"); + + expect(chunks).toEqual([ + expect.objectContaining({ + section_id: "objects#objects", + title: "Objects", + body: expect.any(String), + api_names: expect.any(Array), + synonyms: expect.any(Array), + }), + expect.objectContaining({ + section_id: "objects#helix", + title: "Helix", + api_names: expect.arrayContaining(["Helix"]), + }), + ]); + }); + + it("does not treat heading-like lines inside code as sections", () => { + const source = `Example +======= + +.. code-block:: python + + Generated profile + ================= + result = Box(1, 2, 3) +`; + + const chunks = chunkRstDocument("example.rst", source); + + expect(chunks).toHaveLength(1); + expect(chunks[0].body).toContain("Generated profile\n ================="); + }); +}); + +describe("generated build123d documentation index", () => { + const asset = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), "../public/docs/build123d-index.json"), "utf8")); + const index = MiniSearch.loadJS(asset.index, INDEX_OPTIONS); + + it("contains the pinned full corpus with attribution and required chunk fields", () => { + expect(asset.attribution).toEqual({ + project: "build123d", + version: "0.11.1", + source: "https://github.com/gumyr/build123d/tree/v0.11.1/docs", + license: "Apache-2.0", + }); + expect(index.documentCount).toBeGreaterThan(400); + const loft = index.getStoredFields("introductory-examples#24-loft"); + expect(loft).toEqual(expect.objectContaining({ + title: "24. Loft", + body: expect.stringContaining(".. code-block:: build123d"), + api_names: expect.stringContaining("loft"), + synonyms: expect.stringContaining("cross sections"), + })); + expect(loft?.body).not.toContain("literalinclude"); + expect(JSON.stringify(asset)).not.toContain("\u2014"); + }); + + it.each([ + ["loft usage", "introductory-examples#24-loft"], + ["sweep usage", "introductory-examples#14-position-on-a-line-with-and-introduce-sweep"], + ["revolve usage", "introductory-examples#23-revolve"], + ["spline usage", "introductory-examples#12-defining-an-edge-with-a-spline"], + ["helix usage", "objects#1d-objects"], + ])("ranks the teaching section first for %s", (query, expectedSection) => { + const results = index.search(query, DOC_SEARCH_OPTIONS); + + expect(results[0]?.id).toBe(expectedSection); + }); +}); diff --git a/packages/client/doc-index/eval/README.md b/packages/client/doc-index/eval/README.md new file mode 100644 index 0000000..ddda2da --- /dev/null +++ b/packages/client/doc-index/eval/README.md @@ -0,0 +1,8 @@ +# Documentation retrieval evaluation + +`cases.json` is a committed set of build123d queries and expected section IDs. +The client Vitest suite requires every expected section to appear in the top three results from the committed index. + +Embeddings stay out of this retrieval path unless this set grows real misses that lexical ranking and synonym tuning cannot fix. +New cases should be seeded from privacy-safe logged `search_docs` queries in persisted conversations and traces, not synthetic benchmark inflation. +Any future embeddings implementation must preserve the `search_docs` tool interface and demonstrate that it fixes those documented lexical misses. diff --git a/packages/client/doc-index/eval/cases.json b/packages/client/doc-index/eval/cases.json new file mode 100644 index 0000000..be548b0 --- /dev/null +++ b/packages/client/doc-index/eval/cases.json @@ -0,0 +1,46 @@ +[ + { + "query": "loft between cross sections", + "expected_section": "introductory-examples#24-loft" + }, + { + "query": "sweep multisection", + "expected_section": "examples-1#handle" + }, + { + "query": "revolve usage", + "expected_section": "introductory-examples#23-revolve" + }, + { + "query": "spline through control points", + "expected_section": "introductory-examples#12-defining-an-edge-with-a-spline" + }, + { + "query": "helix pitch radius height", + "expected_section": "objects#1d-objects" + }, + { + "query": "shell hollow wall offset", + "expected_section": "tutorial-lego#step-5-offset-to-create-walls" + }, + { + "query": "pattern holes grid locations", + "expected_section": "examples-1#fast-grid-holes" + }, + { + "query": "groove sweep subtract", + "expected_section": "introductory-examples#14-position-on-a-line-with-and-introduce-sweep" + }, + { + "query": "ValueError: path must be provided", + "expected_section": "introductory-examples#14-position-on-a-line-with-and-introduce-sweep" + }, + { + "query": "RuntimeError: Failed to create valid loft", + "expected_section": "introductory-examples#24-loft" + }, + { + "query": "ValueError: 3D fillet operation takes only Edges", + "expected_section": "tutorial-design#step-8-apply-chamfers-and-fillets" + } +] diff --git a/packages/client/doc-index/eval/retrievalEval.test.mjs b/packages/client/doc-index/eval/retrievalEval.test.mjs new file mode 100644 index 0000000..25f24bd --- /dev/null +++ b/packages/client/doc-index/eval/retrievalEval.test.mjs @@ -0,0 +1,19 @@ +import { readFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import MiniSearch from "minisearch"; +import { describe, expect, it } from "vitest"; +import { DOC_INDEX_OPTIONS, DOC_SEARCH_OPTIONS } from "../../src/agent/docSearchConfig.ts"; + +const evalDir = dirname(fileURLToPath(import.meta.url)); +const cases = JSON.parse(readFileSync(join(evalDir, "cases.json"), "utf8")); +const asset = JSON.parse(readFileSync(join(evalDir, "../../public/docs/build123d-index.json"), "utf8")); +const index = MiniSearch.loadJS(asset.index, DOC_INDEX_OPTIONS); + +describe("build123d documentation retrieval eval", () => { + it.each(cases)("returns $expected_section in the top 3 for '$query'", ({ query, expected_section }) => { + const topThree = index.search(query, DOC_SEARCH_OPTIONS).slice(0, 3).map((result) => String(result.id)); + + expect(topThree, `ranked sections for ${JSON.stringify(query)}`).toContain(expected_section); + }); +}); diff --git a/packages/client/package.json b/packages/client/package.json index 2cd5feb..3a628bb 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -6,6 +6,7 @@ "scripts": { "dev": "vite", "build": "tsc -b && vite build", + "docs:index": "node doc-index/docIndex.mjs", "test": "vitest --run", "typecheck": "tsc --noEmit" }, @@ -24,6 +25,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "lucide-react": "^0.460.0", + "minisearch": "^7.2.0", "react": "^19.0.0", "react-dom": "^19.0.0", "streamdown": "^2.5.0", diff --git a/packages/client/public/docs/build123d-index.json b/packages/client/public/docs/build123d-index.json new file mode 100644 index 0000000..489d06d --- /dev/null +++ b/packages/client/public/docs/build123d-index.json @@ -0,0 +1 @@ +{"format_version":1,"attribution":{"project":"build123d","version":"0.11.1","source":"https://github.com/gumyr/build123d/tree/v0.11.1/docs","license":"Apache-2.0"},"index":{"documentCount":423,"nextId":423,"documentIds":{"0":"advanced#advanced-topics","1":"advantages#enums","2":"advantages#extensions","3":"advantages#instantiated-objects","4":"advantages#last-operation-objects","5":"advantages#operators","6":"advantages#selectors-replaced-by-lists","7":"advantages#standard-python-context-manager","8":"algebra-definition#algebraic-definition","9":"algebra-definition#locations-planes-and-location-arithmetic","10":"algebra-definition#objects-and-arithmetic","11":"algebra-performance#performance-considerations-in-algebra-mode","12":"assemblies#assemblies","13":"assemblies#assigning-labels","14":"assemblies#create-the-assembly-compound","15":"assemblies#detailed-description","16":"assemblies#example-usage","17":"assemblies#iterating-over-compounds","18":"assemblies#pack","19":"assemblies#shallow-vs-deep-copies-of-shapes","20":"assemblies#shapes-are-anytree-nodes","21":"assemblies#tip","22":"assemblies#usage-note","23":"build-line#basic-functionality","24":"build-line#buildline","25":"build-line#buildline-to-buildpart","26":"build-line#buildline-to-buildsketch","27":"build-line#constraints","28":"build-line#position-at-operator","29":"build-line#reference","30":"build-line#tangent-at-operator","31":"build-line#working-on-other-planes","32":"build-part#basic-functionality","33":"build-part#buildpart","34":"build-part#implicit-parameters","35":"build-part#reference","36":"build-part#units","37":"build-sketch#basic-functionality","38":"build-sketch#buildsketch","39":"build-sketch#local-vs-global-sketches","40":"build-sketch#locating-features","41":"build-sketch#reference","42":"build-sketch#sketching-on-other-planes","43":"builder-api-reference#builder-common-api-reference","44":"builder-api-reference#enums","45":"builder-api-reference#locations","46":"builder-api-reference#selector-methods","47":"builders#builders","48":"center#cad-object-centers","49":"cheat-sheet#cheat-sheet","50":"debugging-logging#debugging-logging","51":"debugging-logging#logging","52":"debugging-logging#printing","53":"debugging-logging#python-debugger","54":"direct-api-reference#direct-api-reference","55":"direct-api-reference#geometric-objects","56":"direct-api-reference#import-export","57":"direct-api-reference#joint-object","58":"direct-api-reference#topological-objects","59":"examples-1#benchy","60":"examples-1#bicycle-tire","61":"examples-1#bracelet","62":"examples-1#canadian-flag-blowing-in-the-wind","63":"examples-1#cast-bearing-unit","64":"examples-1#circuit-board-with-holes","65":"examples-1#clock-face","66":"examples-1#fast-grid-holes","67":"examples-1#former-build123d-logo","68":"examples-1#handle","69":"examples-1#heat-exchanger","70":"examples-1#key-cap","71":"examples-1#maker-coin","72":"examples-1#multi-sketch-loft","73":"examples-1#overview","74":"examples-1#peg-board-hook","75":"examples-1#platonic-solids","76":"examples-1#playing-cards","77":"examples-1#stud-wall","78":"examples-1#tea-cup","79":"examples-1#the-build123d-examples","80":"examples-1#toy-truck","81":"examples-1#vase","82":"external#bd-beams-and-bars","83":"external#bd-vslot","84":"external#bd-warehouse","85":"external#blendquery","86":"external#cq-editor-fork","87":"external#dl4to4ocp","88":"external#editors-viewers","89":"external#external-tools-and-libraries","90":"external#makerrepo-cli","91":"external#makerrepo-library-mr","92":"external#nething","93":"external#ocp-freecad-cam","94":"external#ocp-vscode","95":"external#ocp-wasm","96":"external#part-libraries","97":"external#partcad","98":"external#partcad-vs-code-extension","99":"external#partomatic","100":"external#public-partcad-repository","101":"external#py-gearworks-generator","102":"external#superellipses-superellipsoids","103":"external#tools","104":"external#yet-another-cad-viewer","105":"import-export#2d-importers","106":"import-export#3d-exporters","107":"import-export#3d-importers","108":"import-export#3d-mesh-export","109":"import-export#3d-mesh-import","110":"import-export#3d-to-2d-projection","111":"import-export#3mf","112":"import-export#brep","113":"import-export#dxf","114":"import-export#exportdxf","115":"import-export#exportsvg","116":"import-export#file-formats","117":"import-export#gltf","118":"import-export#import-export","119":"import-export#linetype","120":"import-export#step","121":"import-export#stl","122":"import-export#stl-reconstruction","123":"import-export#svg","124":"index#about","125":"index#indices-and-tables","126":"index#table-of-contents","127":"installation#adding-a-nicer-gui","128":"installation#development-install-of-build123d","129":"installation#install-build123d-from-github","130":"installation#installation","131":"installation#test-your-build123d-installation","132":"introduction#advantages-over-cadquery","133":"introduction#automated-documentation","134":"introduction#automated-testing","135":"introduction#boundary-representation-brep-modelling","136":"introduction#introduction","137":"introduction#key-aspects","138":"introduction#open-source-software","139":"introduction#parameterized-models","140":"introduction#python-programming-language","141":"introduction#source-code-control-systems","142":"introductory-examples#1-simple-rectangular-plate","143":"introductory-examples#10-select-last-and-hole","144":"introductory-examples#11-use-a-face-as-a-plane-for-buildsketch-and-introduce-gridlocations","145":"introductory-examples#12-defining-an-edge-with-a-spline","146":"introductory-examples#13-counterboreholes-countersinkholes-and-polarlocations","147":"introductory-examples#14-position-on-a-line-with-and-introduce-sweep","148":"introductory-examples#15-mirroring-symmetric-geometry","149":"introductory-examples#16-mirroring-3d-objects","150":"introductory-examples#17-mirroring-from-faces","151":"introductory-examples#18-creating-workplanes-on-faces","152":"introductory-examples#19-locating-a-workplane-on-a-vertex","153":"introductory-examples#2-plate-with-hole","154":"introductory-examples#20-offset-sketch-workplane","155":"introductory-examples#21-create-a-workplanes-in-the-center-of-another-shape","156":"introductory-examples#22-rotated-workplanes","157":"introductory-examples#23-revolve","158":"introductory-examples#24-loft","159":"introductory-examples#25-offset-sketch","160":"introductory-examples#26-offset-part-to-create-thin-features","161":"introductory-examples#27-splitting-an-object","162":"introductory-examples#28-locating-features-based-on-faces","163":"introductory-examples#29-the-classic-occ-bottle","164":"introductory-examples#3-an-extruded-prismatic-solid","165":"introductory-examples#30-bezier-curve","166":"introductory-examples#31-nesting-locations","167":"introductory-examples#32-python-for-loop","168":"introductory-examples#33-python-function-and-for-loop","169":"introductory-examples#34-embossed-and-debossed-text","170":"introductory-examples#35-slots","171":"introductory-examples#36-extrude-until","172":"introductory-examples#4-building-profiles-using-lines-and-arcs","173":"introductory-examples#5-moving-the-current-working-point","174":"introductory-examples#6-using-point-lists","175":"introductory-examples#7-polygons","176":"introductory-examples#8-polylines","177":"introductory-examples#9-selectors-fillets-and-chamfers","178":"introductory-examples#introductory-examples","179":"joints#ball-joint","180":"joints#cylindrical-joint","181":"joints#joints","182":"joints#linear-joint","183":"joints#revolute-joint","184":"joints#rigid-joint","185":"key-concepts-algebra#combing-both-concepts","186":"key-concepts-algebra#key-concepts-algebra-mode","187":"key-concepts-algebra#object-arithmetic","188":"key-concepts-algebra#placement-arithmetic","189":"key-concepts-builder#analogy-adding-numbers-on-paper","190":"key-concepts-builder#builder-s-pending-objects","191":"key-concepts-builder#builders","192":"key-concepts-builder#combination-modes","193":"key-concepts-builder#example-workflow","194":"key-concepts-builder#how-the-builder-works","195":"key-concepts-builder#implicit-builder-instance-variables","196":"key-concepts-builder#key-concepts","197":"key-concepts-builder#key-concepts-builder-mode","198":"key-concepts-builder#locations-context","199":"key-concepts-builder#operation-inputs","200":"key-concepts-builder#understanding-the-builder-paradigm","201":"key-concepts-builder#using-locations-rotating-objects","202":"key-concepts-builder#workplanes","203":"key-concepts#key-concepts","204":"key-concepts#location","205":"key-concepts#selectors","206":"key-concepts#topology","207":"location-arithmetic#location-arithmetic-for-algebra-mode","208":"location-arithmetic#position-a-shape-relative-to-the-xy-plane","209":"location-arithmetic#relative-positioning-to-a-plane","210":"moving-objects#algebra-mode","211":"moving-objects#builder-mode","212":"moving-objects#direct-manipulation-methods","213":"moving-objects#movement-methods","214":"moving-objects#moving-objects","215":"moving-objects#orientation","216":"moving-objects#position","217":"moving-objects#transformation-a-k-a-translation-and-rotation","218":"objects#1d-objects","219":"objects#2d-objects","220":"objects#3d-objects","221":"objects#align","222":"objects#custom-objects","223":"objects#mode","224":"objects#objects","225":"objects#reference","226":"objects#reference-2","227":"objects#reference-3","228":"objects#text","229":"openscad#conclusion","230":"openscad#example-comparison","231":"openscad#moving-beyond-constructive-solid-geometry-csg","232":"openscad#refining-the-model","233":"openscad#tips-for-transitioning","234":"openscad#transitioning-from-openscad","235":"openscad#using-a-more-traditional-cad-design-workflow","236":"openscad#why-transition-away-from-csg","237":"openscad#why-transition-to-build123d","238":"operations#operations","239":"operations#reference","240":"selectors#custom-sorting-and-filtering","241":"selectors#quick-reference","242":"selectors#shapelist-class","243":"tech-drawing-tutorial#code","244":"tech-drawing-tutorial#dependencies","245":"tech-drawing-tutorial#how-it-works","246":"tech-drawing-tutorial#overview","247":"tech-drawing-tutorial#result","248":"tech-drawing-tutorial#technical-drawing-tutorial","249":"tech-drawing-tutorial#try-it-yourself","250":"tips#2d-before-3d","251":"tips#build123d-cadquery-integration","252":"tips#can-t-get-there-from-here","253":"tips#delay-chamfers-and-fillets","254":"tips#don-t-builders-inherit-workplane-coordinate-systems-when-nested","255":"tips#isn-t-from-build123d-import-bad-practice","256":"tips#object-selection","257":"tips#packing-objects-on-a-plane","258":"tips#parameterize","259":"tips#self-intersection","260":"tips#tips-best-practices-and-faq","261":"tips#use-shallow-copies","262":"tips#why-doesn-t-buildsketch-plane-xz-work","263":"tips#why-is-buildline-not-working-as-expected-within-the-scope-of-buildsketch","264":"topology-selection#examples","265":"topology-selection#examples-2","266":"topology-selection#examples-3","267":"topology-selection#filter","268":"topology-selection#group","269":"topology-selection#operators","270":"topology-selection#overview","271":"topology-selection#overview-2","272":"topology-selection#select-in-build-context","273":"topology-selection#select-new-edges-in-algebra-mode","274":"topology-selection#selectors","275":"topology-selection#sort","276":"topology-selection#topological-distance","277":"topology-selection#topology-selection-and-exploration","278":"tttt#23-02-02-sm-hanger","279":"tttt#23-t-24-curved-support","280":"tttt#24-spo-06-buffer-stand","281":"tttt#party-pack-01-01-bearing-bracket","282":"tttt#party-pack-01-02-post-cap","283":"tttt#party-pack-01-03-c-clamp-base","284":"tttt#party-pack-01-04-angle-bracket","285":"tttt#party-pack-01-05-paste-sleeve","286":"tttt#party-pack-01-06-bearing-jig","287":"tttt#party-pack-01-07-flanged-hub","288":"tttt#party-pack-01-08-tie-plate","289":"tttt#party-pack-01-09-corner-tie","290":"tttt#party-pack-01-10-light-cap","291":"tttt#too-tall-toby-ttt-tutorials","292":"tutorial-constraints#algebra-mode","293":"tutorial-constraints#allowed-constraint-objects","294":"tutorial-constraints#analytical-constraints","295":"tutorial-constraints#analytical-constraints-2","296":"tutorial-constraints#builder-mode","297":"tutorial-constraints#builder-vs-algebra-mode","298":"tutorial-constraints#coincident","299":"tutorial-constraints#complex-drawing-example","300":"tutorial-constraints#constrainedarcs","301":"tutorial-constraints#constrainedlines","302":"tutorial-constraints#constraint-types","303":"tutorial-constraints#continuity-constraints","304":"tutorial-constraints#continuity-constraints-2","305":"tutorial-constraints#drawing-with-constraints","306":"tutorial-constraints#extent-termination-constraints","307":"tutorial-constraints#extent-termination-constraints-2","308":"tutorial-constraints#geometric-relationship-constraints","309":"tutorial-constraints#geometric-relationship-constraints-2","310":"tutorial-constraints#introduction","311":"tutorial-constraints#multiple-solutions","312":"tutorial-constraints#multiple-solutions-and-qualification","313":"tutorial-constraints#offset-equidistance-constraints","314":"tutorial-constraints#offset-equidistance-constraints-2","315":"tutorial-constraints#overview","316":"tutorial-constraints#overview-2","317":"tutorial-constraints#perpendicular","318":"tutorial-constraints#practical-examples","319":"tutorial-constraints#selecting-results","320":"tutorial-constraints#selection-recipes","321":"tutorial-constraints#signature-a-two-constraints","322":"tutorial-constraints#signature-a-two-constraints-radius","323":"tutorial-constraints#signature-b-one-constraint-through-point","324":"tutorial-constraints#signature-b-two-constraints-center-on","325":"tutorial-constraints#signature-c-one-constraint-fixed-orientation","326":"tutorial-constraints#signature-c-three-constraints","327":"tutorial-constraints#signature-d-one-constraint-fixed-center","328":"tutorial-constraints#signature-e-one-constraint-radius-center-on","329":"tutorial-constraints#tangency-constraints","330":"tutorial-constraints#tangency-constraints-2","331":"tutorial-constraints#tangency-qualifiers","332":"tutorial-constraints#tangent","333":"tutorial-constraints#troubleshooting","334":"tutorial-design#designing-a-part-in-build123d","335":"tutorial-design#step-1-examine-the-part-in-all-three-orientations","336":"tutorial-design#step-10-plan-for-parametric-flexibility","337":"tutorial-design#step-11-test-fit-and-tolerances","338":"tutorial-design#step-2-identify-rotational-symmetries","339":"tutorial-design#step-3-select-a-convenient-origin","340":"tutorial-design#step-4-create-2d-profiles","341":"tutorial-design#step-5-use-extrusion-for-prismatic-features","342":"tutorial-design#step-6-generate-revolved-features","343":"tutorial-design#step-7-combine-sub-parts-intelligently","344":"tutorial-design#step-8-apply-chamfers-and-fillets","345":"tutorial-design#step-9-design-for-assembly","346":"tutorial-design#summary","347":"tutorial-joints#conclusion","348":"tutorial-joints#joint-tutorial","349":"tutorial-joints#step-1-setup","350":"tutorial-joints#step-2-create-hinge","351":"tutorial-joints#step-3-add-joints-to-the-hinge-leaf","352":"tutorial-joints#step-3a-leaf-joint","353":"tutorial-joints#step-3b-hinge-joint","354":"tutorial-joints#step-3c-fastener-joints","355":"tutorial-joints#step-3d-call-super","356":"tutorial-joints#step-3e-instantiate-hinge-leaves","357":"tutorial-joints#step-4-create-the-box","358":"tutorial-joints#step-4a-relocate-box","359":"tutorial-joints#step-5-create-the-lid","360":"tutorial-joints#step-6-import-a-screw-and-bind-a-joint-to-it","361":"tutorial-joints#step-7-connect-the-joints-together","362":"tutorial-joints#step-7a-hinge-to-box","363":"tutorial-joints#step-7b-hinge-to-hinge","364":"tutorial-joints#step-7c-lid-to-hinge","365":"tutorial-joints#step-7d-screw-to-hinge","366":"tutorial-lego#lego-tutorial","367":"tutorial-lego#step-1-setup","368":"tutorial-lego#step-10-adding-a-top","369":"tutorial-lego#step-11-adding-pips","370":"tutorial-lego#step-2-part-builder","371":"tutorial-lego#step-3-sketch-builder","372":"tutorial-lego#step-4-perimeter-rectangle","373":"tutorial-lego#step-5-offset-to-create-walls","374":"tutorial-lego#step-6-create-internal-grid","375":"tutorial-lego#step-7-create-ridges","376":"tutorial-lego#step-8-hollow-circles","377":"tutorial-lego#step-9-extruding-sketch-into-walls","378":"tutorial-selectors#conclusion","379":"tutorial-selectors#selector-tutorial","380":"tutorial-selectors#step-1-setup","381":"tutorial-selectors#step-2-create-base-with-buildpart","382":"tutorial-selectors#step-3-place-sketch-on-top-of-base","383":"tutorial-selectors#step-3a-extract-faces-from-a-part","384":"tutorial-selectors#step-3b-get-top-face","385":"tutorial-selectors#step-4-create-hole-shape","386":"tutorial-selectors#step-4a-draw-a-hexagon","387":"tutorial-selectors#step-4b-create-a-hole-in-the-hexagon","388":"tutorial-selectors#step-5-create-the-hole","389":"tutorial-selectors#step-6-fillet-the-top-perimeter-edge","390":"tutorial-selectors#step-6a-extract-all-the-edges","391":"tutorial-selectors#step-6b-filter-the-edges-for-circles","392":"tutorial-selectors#step-6c-sort-the-circles-by-radius","393":"tutorial-selectors#step-6d-slice-the-list-to-get-the-two-largest","394":"tutorial-selectors#step-6e-select-the-top-edge","395":"tutorial-spitfire-wing-gordon#complete-listing","396":"tutorial-spitfire-wing-gordon#overview","397":"tutorial-spitfire-wing-gordon#step-1-dimensions-and-guide-curves","398":"tutorial-spitfire-wing-gordon#step-2-root-and-tip-airfoil-sizing","399":"tutorial-spitfire-wing-gordon#step-3-build-airfoil-profiles-root-and-tip","400":"tutorial-spitfire-wing-gordon#step-4-gordon-surface-construction","401":"tutorial-spitfire-wing-gordon#step-5-cap-the-root-and-create-the-solid","402":"tutorial-spitfire-wing-gordon#tips-for-robust-gordon-surfaces","403":"tutorial-spitfire-wing-gordon#tutorial-spitfire-wing-with-gordon-surface","404":"tutorial-stl-reconstruction#1-examine-the-primitives-visually","405":"tutorial-stl-reconstruction#2-examine-the-leftovers","406":"tutorial-stl-reconstruction#3-examine-the-generated-code","407":"tutorial-stl-reconstruction#inspecting-the-results","408":"tutorial-stl-reconstruction#overview","409":"tutorial-stl-reconstruction#preparing-the-mesh","410":"tutorial-stl-reconstruction#reconstruction-script","411":"tutorial-stl-reconstruction#signs-of-good-output","412":"tutorial-stl-reconstruction#signs-of-poor-output","413":"tutorial-stl-reconstruction#summary","414":"tutorial-stl-reconstruction#turning-primitive-hints-into-sketches","415":"tutorial-stl-reconstruction#tutorial-reconstructing-a-design-from-an-stl","416":"tutorial-stl-reconstruction#why-cache-a-working-section-as-brep","417":"tutorial-stl-reconstruction#worked-example-filleted-box","418":"tutorial-surface-heart-token#next-steps","419":"tutorial-surface-heart-token#summary","420":"tutorial-surface-heart-token#tutorial-heart-token-basics","421":"tutorial-surface-modeling#surface-modeling","422":"tutorials#tutorials"},"fieldIds":{"title":0,"body":1,"api_names":2,"synonyms":3},"fieldLength":{"0":[2,13,1,1],"1":[1,22,1,1],"2":[1,38,1,1],"3":[2,46,2,1],"4":[3,88,10,7],"5":[1,81,5,5],"6":[4,61,4,1],"7":[4,94,12,3],"8":[2,1,1,1],"9":[5,94,8,3],"10":[3,162,52,16],"11":[5,111,9,7],"12":[1,67,4,1],"13":[2,55,3,1],"14":[4,94,6,1],"15":[2,70,3,1],"16":[2,44,2,4],"17":[3,78,4,1],"18":[1,36,2,1],"19":[6,159,15,3],"20":[4,117,18,1],"21":[1,38,3,1],"22":[2,50,2,1],"23":[2,79,10,1],"24":[1,40,1,1],"25":[3,103,12,9],"26":[3,149,14,2],"27":[1,35,1,1],"28":[4,122,10,1],"29":[1,8,1,1],"30":[4,100,13,1],"31":[4,171,9,7],"32":[2,100,9,8],"33":[1,32,1,1],"34":[2,219,29,25],"35":[1,8,1,1],"36":[1,85,4,1],"37":[2,116,15,8],"38":[1,45,2,3],"39":[4,111,13,1],"40":[2,65,7,3],"41":[1,8,1,1],"42":[4,219,23,17],"43":[4,9,1,1],"44":[1,17,11,1],"45":[1,8,2,3],"46":[2,10,2,1],"47":[1,19,1,1],"48":[3,86,2,1],"49":[2,355,138,43],"50":[2,35,1,1],"51":[1,138,9,14],"52":[1,55,2,7],"53":[2,85,2,1],"54":[3,48,2,1],"55":[2,56,11,1],"56":[2,26,8,1],"57":[2,33,1,1],"58":[2,86,15,1],"59":[1,137,23,8],"60":[2,231,23,16],"61":[1,369,47,29],"62":[6,214,35,18],"63":[3,99,20,10],"64":[4,86,12,11],"65":[2,133,15,14],"66":[3,142,11,7],"67":[3,179,35,5],"68":[1,105,14,12],"69":[2,152,18,12],"70":[2,153,20,10],"71":[2,153,19,25],"72":[3,100,14,12],"73":[1,150,1,9],"74":[3,180,17,8],"75":[2,204,34,1],"76":[2,329,51,23],"77":[2,195,29,3],"78":[2,217,26,25],"79":[3,8,1,1],"80":[2,275,38,23],"81":[1,207,31,18],"82":[4,20,1,1],"83":[2,18,1,1],"84":[2,47,1,4],"85":[1,15,1,1],"86":[3,29,1,1],"87":[1,41,1,1],"88":[2,1,1,1],"89":[4,15,1,1],"90":[2,50,3,1],"91":[4,87,5,1],"92":[1,40,1,1],"93":[3,31,1,1],"94":[2,57,2,1],"95":[2,37,1,1],"96":[2,1,1,1],"97":[1,50,1,1],"98":[4,63,3,1],"99":[1,74,1,1],"100":[3,41,1,1],"101":[3,25,1,1],"102":[2,92,1,1],"103":[1,1,1,1],"104":[4,80,3,1],"105":[2,11,6,1],"106":[2,11,5,1],"107":[2,6,4,1],"108":[3,126,18,1],"109":[3,52,5,1],"110":[4,143,17,1],"111":[1,79,1,1],"112":[1,77,3,1],"113":[1,80,2,1],"114":[1,5,1,1],"115":[1,5,1,1],"116":[2,1,1,1],"117":[1,81,1,1],"118":[2,27,4,1],"119":[1,102,5,1],"120":[1,69,4,1],"121":[1,69,2,1],"122":[2,43,2,1],"123":[1,119,3,1],"124":[1,318,34,25],"125":[3,5,1,1],"126":[3,33,1,1],"127":[4,18,1,1],"128":[5,80,3,1],"129":[5,121,1,1],"130":[1,30,1,1],"131":[5,57,5,1],"132":[3,4,1,1],"133":[2,123,1,1],"134":[2,146,1,1],"135":[4,156,3,7],"136":[1,1,1,1],"137":[2,35,1,1],"138":[3,112,1,1],"139":[2,134,1,1],"140":[3,148,1,1],"141":[4,167,1,1],"142":[4,40,2,1],"143":[5,108,14,7],"144":[11,163,23,14],"145":[7,69,8,5],"146":[5,90,10,7],"147":[9,161,17,7],"148":[4,81,10,2],"149":[4,92,12,19],"150":[4,64,10,2],"151":[5,87,16,7],"152":[6,128,16,14],"153":[4,65,4,8],"154":[4,65,12,7],"155":[10,63,6,1],"156":[3,103,14,11],"157":[2,98,13,11],"158":[2,98,13,12],"159":[3,77,8,7],"160":[7,91,7,7],"161":[4,75,11,15],"162":[6,85,12,7],"163":[5,104,19,12],"164":[5,74,5,4],"165":[3,73,10,1],"166":[3,73,7,3],"167":[4,92,9,3],"168":[6,82,11,3],"169":[5,112,16,4],"170":[2,84,13,4],"171":[3,80,11,6],"172":[7,129,11,1],"173":[6,76,9,7],"174":[4,92,6,7],"175":[2,69,6,7],"176":[2,85,10,2],"177":[5,108,9,3],"178":[2,136,6,1],"179":[2,171,26,21],"180":[2,67,8,4],"181":[1,129,11,1],"182":[2,221,29,28],"183":[2,81,7,1],"184":[2,212,23,7],"185":[3,43,4,3],"186":[5,25,5,1],"187":[2,63,3,1],"188":[2,134,14,1],"189":[5,186,10,3],"190":[4,115,13,8],"191":[1,72,7,1],"192":[2,115,13,8],"193":[2,51,9,4],"194":[4,130,1,1],"195":[4,63,7,1],"196":[2,50,1,1],"197":[5,79,1,1],"198":[2,133,10,3],"199":[2,78,6,3],"200":[4,54,1,1],"201":[4,133,10,3],"202":[1,166,18,1],"203":[2,13,1,1],"204":[1,153,14,3],"205":[1,4,1,1],"206":[1,269,12,1],"207":[5,1,1,1],"208":[8,70,17,1],"209":[5,95,18,1],"210":[2,71,3,1],"211":[2,78,6,3],"212":[3,26,1,1],"213":[2,17,4,1],"214":[2,36,1,1],"215":[1,19,1,1],"216":[1,19,1,1],"217":[6,63,4,1],"218":[2,138,30,15],"219":[2,107,18,1],"220":[2,65,10,4],"221":[1,95,7,1],"222":[2,183,22,2],"223":[1,48,7,1],"224":[1,70,8,7],"225":[1,44,29,12],"226":[1,26,19,1],"227":[1,17,11,4],"228":[1,5,1,1],"229":[1,43,1,9],"230":[2,225,15,3],"231":[7,49,1,1],"232":[3,42,1,3],"233":[3,133,1,3],"234":[3,60,1,1],"235":[7,110,1,9],"236":[6,126,1,9],"237":[5,41,1,1],"238":[1,245,39,31],"239":[1,43,35,28],"240":[4,100,9,4],"241":[2,161,20,12],"242":[2,37,1,1],"243":[1,240,36,7],"244":[1,18,1,1],"245":[3,81,2,1],"246":[1,60,5,1],"247":[1,15,1,1],"248":[3,38,1,1],"249":[3,27,1,1],"250":[3,103,8,6],"251":[3,63,9,1],"252":[6,65,2,9],"253":[4,68,1,3],"254":[9,68,1,1],"255":[9,157,3,1],"256":[2,94,10,10],"257":[5,114,4,1],"258":[1,70,1,4],"259":[2,71,5,9],"260":[5,34,1,1],"261":[3,60,1,1],"262":[8,162,15,3],"263":[13,95,8,1],"264":[1,34,1,1],"265":[1,35,1,4],"266":[1,84,14,1],"267":[1,83,8,1],"268":[1,105,10,1],"269":[1,37,3,1],"270":[1,65,10,1],"271":[1,80,14,1],"272":[4,166,14,3],"273":[6,76,8,3],"274":[1,46,1,1],"275":[1,84,5,1],"276":[2,147,22,1],"277":[4,42,1,1],"278":[4,270,30,23],"279":[5,175,27,7],"280":[5,135,26,20],"281":[5,149,26,27],"282":[6,142,22,24],"283":[7,102,11,18],"284":[6,150,16,17],"285":[6,97,11,16],"286":[6,163,23,12],"287":[6,142,22,25],"288":[6,122,15,9],"289":[6,166,34,20],"290":[6,228,28,15],"291":[5,147,1,1],"292":[2,22,4,1],"293":[3,21,4,1],"294":[2,36,8,1],"295":[2,190,17,1],"296":[2,29,4,1],"297":[4,1,1,1],"298":[1,42,3,1],"299":[3,222,26,8],"300":[1,1,1,1],"301":[1,1,1,1],"302":[2,30,1,1],"303":[2,102,5,1],"304":[2,112,13,5],"305":[3,1,1,1],"306":[3,107,12,1],"307":[3,125,12,1],"308":[3,47,1,2],"309":[3,1,1,1],"310":[1,237,16,14],"311":[2,50,4,1],"312":[4,116,6,1],"313":[3,45,2,7],"314":[3,48,2,10],"315":[1,59,6,1],"316":[1,30,4,1],"317":[1,51,6,1],"318":[2,32,1,1],"319":[2,57,7,1],"320":[2,39,4,1],"321":[4,17,1,1],"322":[6,32,2,1],"323":[7,21,1,1],"324":[7,36,4,1],"325":[7,44,3,1],"326":[4,36,2,1],"327":[7,24,2,1],"328":[8,28,3,1],"329":[2,78,2,1],"330":[2,39,4,1],"331":[2,162,23,1],"332":[1,49,4,1],"333":[1,43,3,1],"334":[5,57,1,1],"335":[9,51,1,1],"336":[6,53,1,7],"337":[6,32,1,3],"338":[5,40,1,1],"339":[6,102,2,1],"340":[5,155,11,12],"341":[7,107,9,12],"342":[5,49,1,3],"343":[6,53,1,1],"344":[6,117,7,3],"345":[5,201,14,11],"346":[1,101,22,23],"347":[1,74,9,1],"348":[2,34,1,1],"349":[3,19,1,1],"350":[4,183,34,14],"351":[8,23,3,1],"352":[4,82,7,1],"353":[4,98,5,1],"354":[4,117,5,7],"355":[4,22,3,1],"356":[5,39,1,1],"357":[5,108,15,18],"358":[4,63,3,1],"359":[5,74,7,7],"360":[10,57,7,1],"361":[6,27,1,1],"362":[5,45,7,1],"363":[4,52,5,1],"364":[5,47,6,1],"365":[5,52,2,4],"366":[2,23,1,1],"367":[3,98,3,1],"368":[5,178,17,14],"369":[4,198,17,14],"370":[4,30,2,1],"371":[4,66,3,1],"372":[4,57,4,1],"373":[6,97,10,11],"374":[5,129,8,14],"375":[4,88,5,14],"376":[4,123,6,14],"377":[6,123,8,14],"378":[1,61,1,1],"379":[2,54,4,1],"380":[3,19,1,1],"381":[6,37,2,1],"382":[8,74,7,1],"383":[7,38,4,1],"384":[5,44,4,1],"385":[5,46,8,8],"386":[5,17,1,1],"387":[8,29,3,8],"388":[5,79,11,8],"389":[7,81,14,7],"390":[6,21,2,1],"391":[7,40,4,4],"392":[7,30,4,1],"393":[9,42,5,1],"394":[6,55,5,1],"395":[2,103,19,1],"396":[1,84,2,1],"397":[6,59,2,1],"398":[7,46,3,1],"399":[9,56,6,1],"400":[5,58,9,1],"401":[8,38,3,1],"402":[5,30,2,1],"403":[6,57,3,1],"404":[5,52,1,3],"405":[4,60,1,1],"406":[5,82,4,7],"407":[3,10,1,1],"408":[1,86,6,5],"409":[3,58,7,5],"410":[2,101,8,1],"411":[4,41,2,1],"412":[4,53,1,1],"413":[1,72,2,5],"414":[5,71,3,10],"415":[7,115,2,1],"416":[8,53,1,1],"417":[4,168,15,10],"418":[2,23,3,1],"419":[1,68,6,7],"420":[5,326,31,17],"421":[2,220,14,1],"422":[1,49,1,1]},"averageFieldLength":[3.326241134751774,83.46335697399536,8.354609929078018,4.576832151300237],"storedFields":{"0":{"title":"Advanced Topics","body":".. toctree::\n :maxdepth: 2\n\n algebra_performance.rst\n location_arithmetic.rst\n algebra_definition.rst\n center.rst\n debugging_logging.rst","api_names":"","synonyms":""},"1":{"title":"Enums","body":"All `Literal` strings have been replaced with `Enum` which allows IDEs to\nprompt users for valid options without having to refer to documentation.","api_names":"","synonyms":""},"2":{"title":"Extensions","body":"Extending build123d is relatively simple in that custom objects or operations\ncan be created as new classes without the need to monkey patch any of the\ncore functionality. These new classes will be seen in IDEs which is not\npossible with monkey patching the core CadQuery classes.","api_names":"","synonyms":""},"3":{"title":"Instantiated Objects","body":"Each object and operation is now a class instantiation that interacts with the\nactive context implicitly for the user. These instantiations can be assigned to\nan instance variable as with standard python programming for direct use.\n\n.. code-block:: build123d\n\n with BuildSketch() as plan:\n r = Rectangle(width, height)\n print(r.area)\n ...","api_names":"BuildSketch Rectangle","synonyms":""},"4":{"title":"Last Operation Objects","body":"All of the `vertices()`, `edges()`, `faces()`, and `solids()` methods of the builders\ncan either return all of the objects requested or just the objects changed during the\nlast operation. This allows the user to easily access features for further refinement,\nas shown in the following code where the final line selects the edges that were added\nby the last operation and fillets them. Such a selection would be quite difficult\notherwise.\n\n.. code-block:: build123d\n\n from build123d import *\n \n with BuildPart() as pipes:\n box = Box(10, 10, 10, rotation=(10, 20, 30))\n with BuildSketch(*box.faces()) as pipe:\n Circle(4)\n extrude(amount=-5, mode=Mode.SUBTRACT)\n with BuildSketch(*box.faces()) as pipe:\n Circle(4.5)\n Circle(4, mode=Mode.SUBTRACT)\n extrude(amount=10)\n fillet(pipes.edges(Select.LAST), 0.2)","api_names":"Box BuildPart BuildSketch Circle edges extrude faces fillet solids vertices","synonyms":"bevel edge channel groove path cut round edge"},"5":{"title":"Operators","body":"New operators have been created to extract information from objects created previously\nin the code. The `@` operator extracts the position along an Edge or Wire while the\n`%` operator extracts the tangent along an Edge or Wire. The position parameter are float\nvalues between 0.0 and 1.0 which represent the beginning and end of the line. In the following\nexample, a spline is created from the end of l5 (`l5 @ 1`) to the beginning of l6 (`l6 @ 0`)\nwith tangents equal to the tangents of l5 and l6 at their end and beginning respectively.\nBeing able to extract information from existing features allows the user to \"snap\" new\nfeatures to these points without knowing their numeric values.\n\n.. code-block:: build123d\n\n with BuildLine() as outline:\n ...\n l5 = Polyline(...)\n l6 = Polyline(...)\n Spline(l5 @ 1, l6 @ 0, tangents=(l5 % 1, l6 % 0))","api_names":"BuildLine l5 l6 Polyline Spline","synonyms":"control points interpolation smooth curve"},"6":{"title":"Selectors replaced by Lists","body":"String based selectors have been replaced with standard python filters and\nsorting which opens up the full functionality of python lists. To aid the\nuser, common operations have been optimized as shown here along with\na fully custom selection:\n\n.. code-block:: build123d\n\n top = rail.faces().filter_by(Axis.Z)[-1]\n ...\n outside_vertices = filter(\n lambda v: (v.Y == 0.0 or v.Y == height) and -width / 2 < v.X < width / 2,\n din.vertices(),\n )","api_names":"faces filter filter_by vertices","synonyms":""},"7":{"title":"Standard Python Context Manager","body":"The creation of standard instance variables, looping and other normal python operations\nis enabled by the replacement of method chaining (fluent programming) with a standard\npython context manager.\n\n.. code-block:: python\n\n # CadQuery Fluent API\n pillow_block = (cq.Workplane(\"XY\")\n .box(height, width, thickness)\n .edges(\"|Z\")\n .fillet(fillet)\n .faces(\">Z\")\n .workplane()\n ...\n )\n\n.. code-block:: build123d\n\n # build123d API\n with BuildPart() as pillow_block:\n with BuildSketch() as plan:\n Rectangle(width, height)\n fillet(plan.vertices(), radius=fillet)\n extrude(thickness)\n ...\n\nThe use of the standard `with` block allows standard python instructions to be\ninserted anyway in the code flow. One can insert a CQ-editor `debug` or standard `print`\nstatement anywhere in the code without impacting functionality. Simple python\n`for` loops can be used to repetitively create objects instead of forcing users\ninto using more complex `lambda` and `iter` operations.","api_names":"box BuildPart BuildSketch chaining edges extrude faces fillet Rectangle vertices workplane Workplane","synonyms":"bevel edge round edge"},"8":{"title":"Algebraic definition","body":"","api_names":"","synonyms":""},"9":{"title":"Locations, planes and location arithmetic","body":"**Set definitions:**\n\n:math:`L := \\lbrace` ``Location((x, y, z), (a, b, c))`` :math:`: x,y,z \\in R \\land a,b,c \\in R \\rbrace\\;`\n\n with :math:`a,b,c` being angles in degrees.\n\n:math:`P := \\lbrace` ``Plane(o, x, z)`` :math:`: o,x,z ∈ R^3 \\land \\|x\\| = \\|z\\| = 1\\rbrace`\n\n with ``o`` being the origin and ``x``, ``z`` the x- and z-direction of the plane.\n\nNeutral element: :math:`\\; l_0 \\in L`: ``Location()``\n\n**Operations:**\n\n:math:`*: L \\times L \\rightarrow L` with :math:`(l_1,l_2) \\mapsto l_1 * l_2`\n\n :math:`\\; l_1 * l_2 :=` ``l1 * l2`` (multiply two locations)\n\n:math:`*: P \\times L \\rightarrow P` with :math:`(p,l) \\mapsto p * l`\n\n :math:`\\; p * l :=` ``Plane(p.location * l)`` (move plane :math:`p \\in P` to location :math:`l \\in L`)\n\nInverse element: :math:`\\; l^{-1} \\in L`: ``l.inverse()``\n\n\n**Placing objects onto planes**\n\n:math:`*: P \\times C^n \\rightarrow C^n \\;` with :math:`(p,c) \\mapsto p * c`, :math:`\\;` for :math:`n=1,2,3`\n\n Locate an object :math:`c \\in C^n` onto plane :math:`p \\in P`, i.e. ``c.moved(p.location)``\n\n**Placing objects at locations**\n\n:math:`*: L \\times C^n \\rightarrow C^n \\;` with :math:`(l,c) \\mapsto l * c`, :math:`\\;` for :math:`n=1,2,3`\n\n Locate an object :math:`c \\in C^n` at location :math:`l \\in L`, i.e. ``c.moved(l)``","api_names":"inverse l1 Location moved o Plane x z","synonyms":"array pattern repeat"},"10":{"title":"Objects and arithmetic","body":"**Set definitions:**\n\n:math:`C^3` is the set of all ``Part`` objects ``p`` with ``p._dim = 3``\n\n:math:`C^2` is the set of all ``Sketch`` objects ``s`` with ``s._dim = 2``\n\n:math:`C^1` is the set of all ``Curve`` objects ``c`` with ``c._dim = 1``\n\n**Neutral elements:**\n\n:math:`c^3_0` is the empty ``Part`` object ``p0 = Part()`` with ``p0._dim = 3`` and ``p0.wrapped = None``\n\n:math:`c^2_0` is the empty ``Sketch`` object ``s0 = Sketch()`` with ``s0._dim = 2`` and ``s0.wrapped = None``\n\n:math:`c^1_0` is the empty ``Curve`` object ``c0 = Curve()`` with ``c0._dim = 1`` and ``c0.wrapped = None``\n\n\n**Sets of predefined basic shapes:**\n\n:math:`B^3 := \\lbrace` ``Part``, ``Box``, ``Cylinder``, ``Cone``, ``Sphere``, ``Torus``, ``Wedge``, ``Hole``, ``CounterBoreHole``, ``CounterSinkHole`` :math:`\\rbrace`\n\n:math:`B^2 := \\lbrace` ``Sketch``, ``Rectangle``, ``Circle``, ``Ellipse``, ``Rectangle``, ``Polygon``, ``RegularPolygon``, ``Text``, ``Trapezoid``, ``SlotArc``, ``SlotCenterPoint``, ``SlotCenterToCenter``, ``SlotOverall`` :math:`\\rbrace`\n\n:math:`B^1 := \\lbrace` ``Curve``, ``Bezier``, ``FilletPolyline``, ``PolarLine``, ``Polyline``, ``Spline``, ``Helix``, ``CenterArc``, ``EllipticalCenterArc``, ``ParabolicCenterArc``, ``HyperbolicCenterArc``, ``RadiusArc``, ``SagittaArc``, ``TangentArc``, ``ThreePointArc``, ``JernArc`` :math:`\\rbrace`\n\nwith :math:`B^3 \\subset C^3, B^2 \\subset C^2` and :math:`B^1 \\subset C^1`\n\n\n**Operations:**\n\n:math:`+: C^n \\times C^n \\rightarrow C^n` with :math:`(a,b) \\mapsto a + b`, :math:`\\;` for :math:`n=1,2,3`\n\n :math:`\\; a + b :=` ``a.fuse(b)`` for each operation\n\n:math:`-: C^n \\rightarrow C^n` with :math:`a \\mapsto -a`, :math:`\\;` for :math:`n=1,2,3`\n\n :math:`\\; b + (-a) :=` ``b.cut(a)`` for each operation (implicit definition)\n\n\n:math:`\\&: C^n \\times C^n \\rightarrow C^n` with :math:`(a,b) \\mapsto a \\; \\& \\; b`, :math:`\\;` for :math:`n=2,3`\n\n :math:`\\; a \\; \\& \\; b :=` ``a.intersect(b)`` for each operation\n\n * :math:`\\&` is not defined for :math:`n=1` in build123d\n * The following relationship holds: :math:`a \\; \\& \\; b = (a + b) + -(a + (-b)) + -(b + (-a))`\n\n\n**Abelian groups**\n\n:math:`( C^n, \\; c^n_0, \\; +, \\; -)` :math:`\\;` are abelian groups for :math:`n=1,2,3`.\n\n* The implementation ``a - b = a.cut(b)`` needs to be read as :math:`a + (-b)` since the group does not have a binary ``-`` operation. As such, :math:`a - (b - c) = a + -(b + -c)) \\ne a - b + c`\n* This definition also includes that neither ``-`` nor ``&`` are commutative.","api_names":"_dim a Bezier Box c c0 CenterArc Circle Cone CounterBoreHole CounterSinkHole Curve cut Cylinder Ellipse EllipticalCenterArc FilletPolyline fuse Helix Hole HyperbolicCenterArc intersect JernArc operation p p0 ParabolicCenterArc Part PolarLine Polygon Polyline RadiusArc Rectangle RegularPolygon s s0 SagittaArc Sketch SlotArc SlotCenterPoint SlotCenterToCenter SlotOverall Sphere Spline TangentArc Text ThreePointArc Torus Trapezoid Wedge wrapped","synonyms":"bevel edge bore coil control points drill interpolation recessed fastener round edge smooth curve spiral thread path"},"11":{"title":"Performance considerations in algebra mode","body":"Creating lots of Shapes in a loop means for every step ``fuse`` and ``clean`` will be called. \nIn an example like the below, both functions get slower and slower the more objects are \nalready fused. Overall it takes on an M1 Mac 4.76 sec.\n\n.. code-block:: build123d\n\n diam = 80\n holes = Sketch()\n r = Rectangle(2, 2)\n for loc in GridLocations(4, 4, 20, 20):\n if loc.position.X**2 + loc.position.Y**2 < (diam / 2 - 1.8) ** 2:\n holes += loc * r\n\n c = Circle(diam / 2) - holes\n\n\nOne way to avoid it is to use lazy evaluation for the algebra operations. Just collect all objects and \nthen call ``fuse`` (``+``) once with all objects and ``clean`` once. Overall it takes 0.19 sec.\n\n.. code-block:: build123d\n\n r = Rectangle(2, 2)\n holes = [\n loc * r\n for loc in GridLocations(4, 4, 20, 20).locations\n if loc.position.X**2 + loc.position.Y**2 < (diam / 2 - 1.8) ** 2\n ]\n\n c = Circle(diam / 2) - holes\n\nAnother way to leverage the vectorized algebra operations is to add a list comprehension of objects to\nan empty ``Part``, ``Sketch`` or ``Curve``:\n\n.. code-block:: build123d\n\n polygons = Sketch() + [\n loc * RegularPolygon(radius=5, side_count=5)\n for loc in GridLocations(40, 30, 2, 2)\n ]\n\nThis again ensures one single ``fuse`` and ``clean`` call.","api_names":"Circle clean Curve fuse GridLocations Part Rectangle RegularPolygon Sketch","synonyms":"array bore drill pattern recessed fastener repeat"},"12":{"title":"Assemblies","body":"Most CAD designs consist of more than one part which are naturally arranged in\nsome type of assembly. Once parts have been assembled in a :class:`~topology.Compound` object\nthey can be treated as a unit - i.e. :meth:`~topology.Shape.moved` or exported.\n\nTo create an assembly in build123d, one needs to\ncreate a tree of parts by simply assigning either a :class:`~topology.Compound` object's ``parent`` or\n``children`` attributes. To illustrate the process, we'll extend the\n:ref:`Joint Tutorial `.","api_names":"children Compound moved parent","synonyms":""},"13":{"title":"Assigning Labels","body":"In order keep track of objects one can assign a ``label`` to all :class:`~topology.Shape` objects.\nHere we'll assign labels to all of the components that will be part of the box\nassembly:\n\n.. code-block:: build123d\n\n box.label = \"box\"\n lid.label = \"lid\"\n hinge_outer.label = \"outer hinge\"\n hinge_inner.label = \"inner hinge\"\n m6_screw.label = \"M6 screw\"\n \n\nThe labels are just strings with no further limitations (they don't have to be unique\nwithin the assembly).","api_names":"label limitations Shape","synonyms":""},"14":{"title":"Create the Assembly Compound","body":"Creation of the assembly is done by simply creating a :class:`~topology.Compound` object and assigning\nappropriate ``parent`` and ``children`` attributes as shown here:\n\n.. code-block:: build123d\n\n box_assembly = Compound(label=\"assembly\", children=[box, lid, hinge_inner, hinge_outer])\n\nTo display the topology of an assembly :class:`~topology.Compound`, the :meth:`~topology.Shape.show_topology`\nmethod can be used as follows:\n\n.. code-block:: build123d\n\n print(box_assembly.show_topology())\n \n\nwhich results in:\n\n.. code::\n\n assembly Compound at 0x7fc8ee235760, Location(p=(0, 0, 0), o=(-0, 0, -0))\n ├── box Compound at 0x7fc8ee2188b0, Location(p=(0, 0, 50), o=(-0, 0, -0))\n ├── lid Compound at 0x7fc8ee228460, Location(p=(-26, 0, 181), o=(-180, 30, -0))\n ├── inner hinge Hinge at 0x7fc9292c3f70, Location(p=(-119, 60, 122), o=(90, 0, -150))\n └── outer hinge Hinge at 0x7fc9292c3f40, Location(p=(-150, 60, 50), o=(90, 0, 90))\n\nTo add to an assembly :class:`~topology.Compound` one can change either ``children`` or ``parent`` attributes.\n\n.. code-block:: build123d\n\n m6_screw.parent = box_assembly\n print(box_assembly.show_topology())\n \n\nand now the screw is part of the assembly.\n\n.. code::\n\n assembly Compound at 0x7fc8ee235760, Location(p=(0, 0, 0), o=(-0, 0, -0))\n ├── box Compound at 0x7fc8ee2188b0, Location(p=(0, 0, 50), o=(-0, 0, -0))\n ├── lid Compound at 0x7fc8ee228460, Location(p=(-26, 0, 181), o=(-180, 30, -0))\n ├── inner hinge Hinge at 0x7fc9292c3f70, Location(p=(-119, 60, 122), o=(90, 0, -150))\n ├── outer hinge Hinge at 0x7fc9292c3f40, Location(p=(-150, 60, 50), o=(90, 0, 90))\n └── M6 screw Compound at 0x7fc8ee235310, Location(p=(-157, -40, 70), o=(-0, -90, -60))\n\n.. _shallow_copy:","api_names":"children Compound Location parent show_topology","synonyms":""},"15":{"title":"Detailed Description","body":"The ``pack`` function uses a bin-packing algorithm to efficiently place objects within a 2D plane, ensuring that there is no overlap and that the space between objects is minimized. This is particularly useful in scenarios where spatial efficiency is crucial, such as layout design and object arrangement in constrained spaces.\n\nThe function begins by calculating the bounding boxes for each object, including the specified padding. It then uses a helper function ``_pack2d`` to determine the optimal positions for each object within the 2D plane. The positions are then translated back to the original objects, ensuring that they are arranged without overlapping.","api_names":"_pack2d pack","synonyms":""},"16":{"title":"Example Usage","body":".. code:: python\n\n # [import]\n from build123d import *\n from ocp_vscode import *\n\n\n # [initial space]\n b1 = Box(100, 100, 100, align=(Align.CENTER, Align.CENTER, Align.MIN))\n b2 = Box(54, 54, 54, align=(Align.CENTER, Align.CENTER, Align.MAX), mode=Mode.SUBTRACT)\n b3 = Box(34, 34, 34, align=(Align.MIN, Align.MIN, Align.CENTER), mode=Mode.SUBTRACT)\n b4 = Box(24, 24, 24, align=(Align.MAX, Align.MAX, Align.CENTER), mode=Mode.SUBTRACT)\n\n\n\n.. image:: assets/pack_demo_initial_state.svg\n :align: center\n\n\n.. code:: python\n\n # [pack 2D]\n\n xy_pack = pack(\n [b1, b2, b3, b4],\n padding=5,\n align_z=False\n )\n\n\n.. image:: assets/pack_demo_packed_xy.svg\n :align: center\n\n\n.. code:: python\n\n # [Pack and align_z]\n\n z_pack = pack(\n [b1, b2, b3, b4],\n padding=5,\n align_z=True\n )\n\n.. image:: assets/pack_demo_packed_z.svg\n :align: center","api_names":"Box pack","synonyms":"channel groove path cut"},"17":{"title":"Iterating Over Compounds","body":"As Compounds are containers for shapes, build123d can iterate over these as required.\nComplex nested assemblies (compounds within compounds) do not need to be looped over with recursive functions.\nIn the example below, the variable total_volume holds the sum of all the volumes in each solid in an assembly.\nCompare this to assembly3_volume which only results in the volume of the top level part.\n\n.. code:: python\n\n # [import]\n from build123d import *\n from ocp_vscode import *\n\n # Each assembly has a box and the previous assembly.\n assembly1 = Compound(label='Assembly1', children=[Box(1, 1, 1),])\n assembly2 = Compound(label='Assembly2', children=[assembly1, Box(1, 1, 1)])\n assembly3 = Compound(label='Assembly3', children=[assembly2, Box(1, 1, 1)])\n total_volume = sum(part.volume for part in assembly3.solids()) # 3\n assembly3_volume = assembly3.volume # 1","api_names":"assemblies Box Compound solids","synonyms":""},"18":{"title":"pack","body":"The :meth:`pack.pack` function arranges objects in a compact, non-overlapping layout within a square(ish) 2D area. It is designed to minimize the space between objects while ensuring that no two objects overlap.\n\n.. py:module:: pack\n\n\n.. autofunction:: pack","api_names":"pack square","synonyms":""},"19":{"title":"Shallow vs. Deep Copies of Shapes","body":"Build123d supports the standard python ``copy`` module which provides two different types of\ncopy operations ``copy.copy()`` and ``copy.deepcopy()``.\n\nBuild123d's implementation of ``deepcopy()`` for the :class:`~topology.Shape` class (e.g. ``Solid``, ``Face``, etc.)\ndoes just that, creates a complete copy of the original all the way down to the CAD object.\n``deepcopy`` is therefore suited to the case where the copy will be subsequently modified to\nbecome its own unique item.\n\nHowever, when building an assembly a common use case is to include many instances of an\nobject, each one identical but in a different location. This is where ``copy.copy()`` is\nvery useful as it copies all of the :class:`~topology.Shape` except for the actual CAD object\nwhich instead is a reference to the original (OpenCascade refers this as a ``TShape``). As\nit's a reference any changes to the original will be seen in all of the shallow copies.\n\nConsider this example where 100 screws are added to an assembly:\n\n.. image:: reference_assembly.svg\n :align: center\n\n.. code::\n\n screw = import_step(\"M6-1x12-countersunk-screw.step\")\n locs = HexLocations(6, 10, 10).local_locations\n\n screw_copies = [copy.deepcopy(screw).locate(loc) for loc in locs]\n copy_assembly = Compound(children=screw_copies)\n export_step(copy_assembly, \"copy_assembly.step\")\n\nwhich takes about 5 seconds to run (on an older computer) and produces\na file of size 51938 KB. However, if a shallow copy is used instead:\n\n.. code::\n\n screw = import_step(\"M6-1x12-countersunk-screw.step\")\n locs = HexLocations(6, 10, 10).local_locations\n\n screw_references = [copy.copy(screw).locate(loc) for loc in locs]\n reference_assembly = Compound(children=screw_references)\n export_step(reference_assembly, \"reference_assembly.step\")\n\nthis takes about ¼ second and produces a file of size 550 KB - just over\n1% of the size of the ``deepcopy()`` version and only 12% larger than the\nscrew's step file.\n\nUsing ``copy.copy()`` to create references to the original CAD object\nfor assemblies can substantially reduce the time and resources used\nto create and store that assembly.","api_names":"class Compound copy deepcopy export_step Face HexLocations import_step locate original run Shape Solid TShape","synonyms":"array pattern repeat"},"20":{"title":"Shapes are Anytree Nodes","body":"The build123d assembly constructs are built using the python\n`anytree `_ package by making the build123d\n:class:`~topology.Shape` class a sub-class of anytree's ``NodeMixin`` class. Doing so\nadds the following attributes to :class:`~topology.Shape`:\n\n* ``parent`` - Parent Node. On set, the node is detached from any previous parent node and attached to the new node.\n* ``children`` - Tuple of all child nodes.\n* ``path`` - Path of this ``Node``.\n* ``iter_path_reverse`` - Iterate up the tree from the current node.\n* ``ancestors`` - All parent nodes and their parent nodes.\n* ``descendants`` - All child nodes and all their child nodes.\n* ``root`` - Tree Root Node.\n* ``siblings`` - Tuple of nodes with the same parent.\n* ``leaves`` - Tuple of all leaf nodes.\n* ``is_leaf`` - ``Node`` has no children (External Node).\n* ``is_root`` - ``Node`` is tree root.\n* ``height`` - Number of edges on the longest path to a leaf ``Node``.\n* ``depth`` - Number of edges to the root ``Node``.\n\n.. note::\n\n Changing the ``children`` attribute\n\n Any iterator can be assigned to the ``children`` attribute but subsequently the children\n are stored as immutable ``tuple`` objects. To add a child to an existing :class:`~topology.Compound`\n object, the ``children`` attribute will have to be reassigned.\n\n .. _pack:","api_names":"ancestors children Compound depth descendants height is_leaf is_root iter_path_reverse leaves Node NodeMixin parent path root Shape siblings","synonyms":""},"21":{"title":"Tip","body":"If you place the arranged objects into a ``Compound``, you can easily determine their bounding box and check whether the objects fit on your print bed.\n\n\n.. code:: python\n\n # [bounding box]\n print(Compound(xy_pack).bounding_box())\n # bbox: 0.0 <= x <= 159.0, 0.0 <= y <= 129.0, -54.0 <= z <= 100.0\n\n print(Compound(z_pack).bounding_box())\n # bbox: 0.0 <= x <= 159.0, 0.0 <= y <= 129.0, 0.0 <= z <= 100.0","api_names":"bounding_box Compound","synonyms":""},"22":{"title":"Usage Note","body":"The ``align_z`` parameter is especially useful when creating print-plates for 3D printing. By aligning the bottoms of the shapes to the same XY plane, you ensure that the objects are perfectly positioned for slicing software, which will no longer need to perform this alignment for you. This can streamline the process and improve the accuracy of the print setup.","api_names":"align_z","synonyms":""},"23":{"title":"Basic Functionality","body":"The following is a simple BuildLine example:\n\n.. code-block:: build123d\n\n with BuildLine() as example_1:\n Line((0, 0), (2, 0))\n ThreePointArc((0, 0), (1, 1), (2, 0))\n\nThe ``with`` statement creates the ``BuildLine`` context manager with the\nidentifier ``example_1``. The objects and operations that are within the\nscope (i.e. indented) of this context will contribute towards the object\nbeing created by the context manager. For ``BuildLine``, this object is\n``line`` and it's referenced as ``example_1.line``.\n\nThe first object in this example is a ``Line`` object which is used to create\na straight line from coordinates (0,0) to (2,0) on the default XY plane.\nThe second object is a ``ThreePointArc`` that starts and ends at the two\nends of the line.\n\n.. image:: assets/buildline_example_1.svg\n :align: center","api_names":"BuildLine coordinates example_1 line Line scope ThreePointArc to with","synonyms":""},"24":{"title":"BuildLine","body":"BuildLine is a python context manager that is used to create one dimensional\nobjects - objects with the property of length but not area - that are typically\nused as part of a BuildSketch sketch or a BuildPart path.\n\nThe complete API for BuildLine is located at the end of this section.","api_names":"","synonyms":""},"25":{"title":"BuildLine to BuildPart","body":"The other primary reasons to use BuildLine is to create paths for BuildPart\n:meth:`~operations_generic.sweep` operations. Here some curved and straight segments\ndefine a path:\n\n.. code-block:: build123d\n\n with BuildPart() as example_7:\n with BuildLine() as example_7_path:\n l1 = RadiusArc((0, 0), (1, 1), 2)\n l2 = Spline(l1 @ 1, (2, 3), (3, 3), tangents=(l1 % 1, (0, -1)))\n l3 = Line(l2 @ 1, (3, 0))\n with BuildSketch(Plane(origin=l1 @ 0, z_dir=l1 % 0)) as example_7_section:\n Circle(0.1)\n sweep()\n\nwhich generates:\n\n.. image:: assets/buildline_example_7.svg\n :align: center\n\nThere are few things to note from this example:\n\n* The @ and % operators are used to create a plane normal to the beginning of the\n path with which to create the circular section used by the sweep operation\n (this plane is not one of the ordinal planes).\n* Both the path generated by BuildLine and the section generated by BuildSketch\n have been transferred to BuildPart when each of them exit.\n* The BuildPart ``Sweep`` operation is using the path and section previously\n transferred to it (as \"pending\" objects) as parameters of the sweep. The\n ``Sweep`` operation \"consumes\" these pending objects as to not interfere with\n subsequence operations.","api_names":"BuildLine BuildPart BuildSketch Circle it Line operation Plane RadiusArc Spline sweep Sweep","synonyms":"channel control points groove interpolation path cut smooth curve"},"26":{"title":"BuildLine to BuildSketch","body":"As mentioned previously, one of the two primary reasons to create BuildLine objects is to\nuse them in BuildSketch. When a BuildLine context manager exits and is within the scope of a\nBuildSketch context manager it will transfer the generated line to BuildSketch. The BuildSketch\n:meth:`~operations_sketch.make_face` or :meth:`~operations_sketch.make_hull` operations are then used\nto transform the line (specifically a list of Edges) into a Face - the native BuildSketch\nobjects.\n\nHere is an example of using BuildLine to create an object that otherwise might be\ndifficult to create:\n\n.. code-block:: build123d\n\n with BuildSketch() as example_6:\n with BuildLine() as club_outline:\n l0 = Line((0, -188), (76, -188))\n b0 = Bezier(l0 @ 1, (61, -185), (33, -173), (17, -81))\n b1 = Bezier(b0 @ 1, (49, -128), (146, -145), (167, -67))\n b2 = Bezier(b1 @ 1, (187, 9), (94, 52), (32, 18))\n b3 = Bezier(b2 @ 1, (92, 57), (113, 188), (0, 188))\n mirror(about=Plane.YZ)\n make_face()\n\nwhich generates:\n\n.. image:: assets/buildline_example_6.svg\n :align: center\n\n.. note:: SVG import to BuildLine\n\n The BuildLine code used in this example was generated by translating a SVG file\n into BuildLine source code with the :func:`~importers.import_svg_as_buildline_code`\n function. For example:\n\n .. code::\n\n svg_code, builder_name = import_svg_as_buildline_code(\"club.svg\")\n\n would translate the \"club.svg\" image file's paths into BuildLine code much like\n that shown above. From there it's easy for a user to add constraints or otherwise\n enhance the original image and use it in their design.","api_names":"Bezier BuildLine BuildSketch import_svg_as_buildline_code line Line make_face make_hull mirror","synonyms":"reflect symmetry"},"27":{"title":"Constraints","body":"Building with constraints enables the designer to capture design intent and\nadd a high degree of robustness to their designs. The following sections\ndescribe creating positional and tangential constraints as well as using\nobject attributes to enable this type of design.","api_names":"","synonyms":""},"28":{"title":"@ ``position_at`` Operator","body":"In the previous example, the ``ThreePointArc`` started and ended at the\ntwo ends of the ``Line`` but this was done by referring to the same\npoint ``(0,0)`` and ``(2,0)``. This can be improved upon by specifying\nconstraints that lock the arc to those two end points, as follows:\n\n.. code-block:: build123d\n\n with BuildLine() as example_2:\n l1 = Line((0, 0), (2, 0))\n l2 = ThreePointArc(l1 @ 0, (1, 1), l1 @ 1)\n\nHere instance variables ``l1`` and ``l2`` are assigned to the two BuildLine\nobjects and the ``ThreePointArc`` references the beginning of the straight\nline with ``l1 @ 0`` and the end with ``l1 @ 1``. The ``@`` operator takes\na float (or integer) parameter between 0 and 1 and determines a position\nat this fractional position along the line's length.\n\nThis example can be improved on further by calculating the mid-point\nof the arc as follows:\n\n.. code-block:: build123d\n\n with BuildLine() as example_3:\n l1 = Line((0, 0), (2, 0))\n l2 = ThreePointArc(l1 @ 0, l1 @ 0.5 + (0, 1), l1 @ 1)\n\nHere ``l1 @ 0.5`` finds the center of ``l1`` while ``l1 @ 0.5 + (0, 1)`` does\na vector addition to generate the point ``(1,1)``.\n\nTo make the design even more parametric, the height of the arc can be calculated\nfrom ``l1`` as follows:\n\n.. code-block:: build123d\n\n with BuildLine() as example_4:\n l1 = Line((0, 0), (2, 0))\n l2 = ThreePointArc(l1 @ 0, l1 @ 0.5 + (0, l1.length / 2), l1 @ 1)\n\nThe arc height is now calculated as ``(0, l1.length / 2)`` by using the ``length``\nproperty of ``Edge`` and ``Wire`` shapes. At this point the ``ThreePointArc`` is\nfully parametric and able to generate the same shape for any horizontal line.","api_names":"BuildLine Edge l1 l2 length Line position_at ThreePointArc Wire","synonyms":""},"29":{"title":"Reference","body":".. py:module:: build_line\n\n.. autoclass:: BuildLine\n :members:","api_names":"BuildLine","synonyms":""},"30":{"title":"% ``tangent_at`` Operator","body":"The other operator that is commonly used within BuildLine is ``%`` the tangent at\noperator. Here is another example:\n\n.. code-block:: build123d\n\n with BuildLine() as example_5:\n l1 = Line((0, 0), (5, 0))\n l2 = Line(l1 @ 1, l1 @ 1 + (0, l1.length - 1))\n l3 = JernArc(start=l2 @ 1, tangent=l2 % 1, radius=0.5, arc_size=90)\n l4 = Line(l3 @ 1, (0, l2.length + l3.radius))\n\nwhich generates (note that the circles show line junctions):\n\n.. image:: assets/buildline_example_5.svg\n :align: center\n\nThe ``JernArc`` has the following parameters:\n\n* ``start=l2 @ 1`` - start the arc at the end of line ``l2``,\n* ``tangent=l2 % 1`` - the tangent of the arc at the start point is equal to the ``l2``\\'s,\n tangent at its end (shown as a dashed line)\n* ``radius=0.5`` - the radius of the arc, and\n* ``arc_size=90`` the angular size of the arc.\n\nThe final line starts at the end of ``l3`` and ends at a point calculated from the length\nof ``l2`` and the radius of arc ``l3``.\n\nBuilding with constraints as shown here will ensure that your designs both fully represent\ndesign intent and are robust to design changes.","api_names":"arc_size BuildLine end generates JernArc l2 l3 Line radius start tangent tangent_at","synonyms":""},"31":{"title":"Working on other Planes","body":"So far all of the examples were created on ``Plane.XY`` - the default plane - which is equivalent\nto global coordinates. Sometimes it's convenient to work on another plane, especially when\ncreating paths for BuildPart ``Sweep`` operations.\n\n.. code-block:: build123d\n\n with BuildLine(Plane.YZ) as example_8:\n l1 = Line((0, 0), (5, 0))\n l2 = Line(l1 @ 1, l1 @ 1 + (0, l1.length - 1))\n l3 = JernArc(start=l2 @ 1, tangent=l2 % 1, radius=0.5, arc_size=90)\n l4 = Line(l3 @ 1, (0, l2.length + l3.radius))\n\nwhich generates:\n\n.. image:: assets/buildline_example_8.svg\n :align: center\n\nHere the BuildLine object is created on ``Plane.YZ`` just by specifying the working plane\nduring BuildLine initialization.\n\nThere are three rules to keep in mind when working with alternate planes in BuildLine:\n\n#. ``BuildLine`` accepts a single ``Plane`` to work with as opposed to other Builders\n that accept more than one workplane.\n#. Values entered as tuples such as ``(1, 2)`` or ``(1, 2, 3)`` will be localized to the\n current workplane. This rule applies to points and to the use of tuples to modify\n locations calculated with the ``@`` and ``%`` operators such as ``l1 @ 1 + (1, 1)``.\n For example, if the workplane is ``Plane.YZ`` the local value of ``(1, 2)`` would\n be converted to ``(0, 1, 2)`` in global coordinates. Three tuples are converted as\n well - ``(1, 2, 3)`` on ``Plane.YZ`` would be ``(3, 1, 2)`` in global coordinates.\n Providing values in local coordinates allows the designer to automate such\n conversions.\n#. Values entered using the ``Vector`` class or those generated by the ``@`` operator\n are considered global values and are not localized. For example:\n ``Line(Vector(1, 2, 3), Vector(4, 5, 6))`` will generate the same line independent\n of the current workplane. It's unlikely that users will need to use ``Vector``\n values but the option is there.\n\nFinally, BuildLine's workplane need not be one of the predefined ordinal planes, it\ncould be one created from a surface of a BuildPart part that is currently under\nconstruction.","api_names":"BuildLine JernArc l1 Line Plane Sweep Vector XY YZ","synonyms":"array channel groove path cut pattern repeat"},"32":{"title":"Basic Functionality","body":"The following is a simple BuildPart example:\n\n.. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n center_hole_dia = 22.0\n \n with BuildPart() as ex2:\n Box(length, width, thickness)\n Cylinder(radius=center_hole_dia / 2, height=thickness, mode=Mode.SUBTRACT)\n\nThe ``with`` statement creates the ``BuildPart`` context manager with the\nidentifier ``ex2`` (this code is the second of the introductory examples).\nThe objects and operations that are within the\nscope (i.e. indented) of this context will contribute towards the object\nbeing created by the context manager. For ``BuildPart``, this object is\n``part`` and it's referenced as ``ex2.part``.\n\nThe first object in this example is a ``Box`` object which is used to create\na polyhedron with rectangular faces centered on the default ``Plane.XY``.\nThe second object is a ``Cylinder`` that is subtracted from the box as directed\nby the ``mode=Mode.SUBTRACT`` parameter thus creating a hole.\n\n.. image:: assets/general_ex2.svg\n :align: center","api_names":"Box BuildPart Cylinder ex2 mode part scope with XY","synonyms":"bore channel drill groove path cut recessed fastener"},"33":{"title":"BuildPart","body":"BuildPart is a python context manager that is used to create three dimensional\nobjects - objects with the property of volume - that are typically\nfinished parts.\n\nThe complete API for BuildPart is located at the end of this section.","api_names":"","synonyms":""},"34":{"title":"Implicit Parameters","body":"The BuildPart context keeps track of pending objects such that they can be used\nimplicitly - there are a couple things to consider when deciding how to proceed:\n\n* For sketches, the planes that they were constructed on is maintained in internal\n data structures such that operations like :func:`~operations_part.extrude` will\n have a good reference for the extrude direction. One can pass a Face to extrude\n but it will then be forced to use the normal direction at the center of the Face\n as the extrude direction which unfortunately can be reversed in some circumstances.\n* Implicit parameters save some typing but hide some functionality - users have\n to decide what works best for them.\n\nThis tea cup example uses implicit parameters - note the :func:`~operations_generic.sweep`\noperation on the last line:\n\n.. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n wall_thickness = 3 * MM\n fillet_radius = wall_thickness * 0.49\n \n with BuildPart() as tea_cup:\n # Create the bowl of the cup as a revolved cross section\n with BuildSketch(Plane.XZ) as bowl_section:\n with BuildLine():\n # Start & end points with control tangents\n s = Spline(\n (30 * MM, 10 * MM),\n (69 * MM, 105 * MM),\n tangents=((1, 0.5), (0.7, 1)),\n tangent_scalars=(1.75, 1),\n )\n # Lines to finish creating ½ the bowl shape\n Polyline(s @ 0, s @ 0 + (10 * MM, -10 * MM), (0, 0), (0, (s @ 1).Y), s @ 1)\n make_face() # Create a filled 2D shape\n revolve(axis=Axis.Z)\n # Hollow out the bowl with openings on the top and bottom\n offset(amount=-wall_thickness, openings=tea_cup.faces().filter_by(GeomType.PLANE))\n # Add a bottom to the bowl\n with Locations((0, 0, (s @ 0).Y)):\n Cylinder(radius=(s @ 0).X, height=wall_thickness)\n # Smooth out all the edges\n fillet(tea_cup.edges(), radius=fillet_radius)\n \n # Determine where the handle contacts the bowl\n handle_intersections = [\n tea_cup.part.find_intersection_points(\n Axis(origin=(0, 0, vertical_offset), direction=(1, 0, 0))\n )[-1][0]\n for vertical_offset in [35 * MM, 80 * MM]\n ]\n # Create a path for handle creation\n with BuildLine(Plane.XZ) as handle_path:\n Spline(\n handle_intersections[0] - (wall_thickness / 2, 0),\n handle_intersections[0] + (35 * MM, 30 * MM),\n handle_intersections[0] + (40 * MM, 60 * MM),\n handle_intersections[1] - (wall_thickness / 2, 0),\n tangents=((1, 1.25), (-0.2, -1)),\n )\n # Align the cross section to the beginning of the path\n with BuildSketch(handle_path.line ^ 0) as handle_cross_section:\n RectangleRounded(wall_thickness, 8 * MM, fillet_radius)\n sweep() # Sweep handle cross section along path\n \n assert abs(tea_cup.part.volume - 130326) < 1\n \n show(tea_cup, names=[\"tea cup\"])\n\n:func:`~operations_generic.sweep` requires a 2D cross section - ``handle_cross_section`` -\nand a path - ``handle_path`` - which are both passed implicitly.\n\n.. image:: tea_cup.png\n :align: center","api_names":"abs Axis BuildLine BuildPart BuildSketch Cylinder edges extrude faces fillet filter_by find_intersection_points handle_cross_section handle_path Locations make_face offset Polyline RectangleRounded revolve show Spline sweep","synonyms":"array axisymmetric bevel edge channel control points fit gap groove hollow interpolation lathe path cut pattern repeat round edge shell smooth curve tolerance turned wall thickness"},"35":{"title":"Reference","body":".. py:module:: build_part\n\n.. autoclass:: BuildPart\n :members:","api_names":"BuildPart","synonyms":""},"36":{"title":"Units","body":"Parts created with build123d have no inherent units associated with them. However, when\nexporting parts to external formats like ``STL`` or ``STEP`` the units are assumed to\nbe millimeters (mm). To be more explicit with units one can use the technique shown\nin the above tea cup example where linear dimensions are followed by ``* MM`` which\nmultiplies the dimension by the ``MM`` scaling factor - in this case ``1``.\n\nThe following dimensional constants are pre-defined:\n\n.. code:: python\n\n MM = 1\n CM = 10 * MM\n M = 1000 * MM\n IN = 25.4 * MM\n FT = 12 * IN\n THOU = IN / 1000\n\nSome export formats like DXF have the ability to explicitly set the units used.","api_names":"millimeters MM STEP STL","synonyms":""},"37":{"title":"Basic Functionality","body":"The following is a simple BuildSketch example:\n\n.. code-block:: build123d\n\n length, radius = 40.0, 60.0\n \n with BuildSketch() as circle_with_hole:\n Circle(radius=radius)\n Rectangle(width=length, height=length, mode=Mode.SUBTRACT)\n\nThe ``with`` statement creates the ``BuildSketch`` context manager with the\nidentifier ``circle_with_hole``. The objects and operations that are within the\nscope (i.e. indented) of this context will contribute towards the object\nbeing created by the context manager. For ``BuildSketch``, this object is\n``sketch`` and it's referenced as ``circle_with_hole.sketch``.\n\nThe first object in this example is a ``Circle`` object which is used to create\na filled circular shape on the default XY plane. The second object is a ``Rectangle``\nthat is subtracted from the circle as directed by the ``mode=Mode.SUBTRACT`` parameter.\nA key aspect of sketch objects is that they are all filled shapes and not just\na shape perimeter which enables combining subsequent shapes with different modes\n(the valid values of Mode are ``ADD``, ``SUBTRACT``, ``INTERSECT``, ``REPLACE``,\nand ``PRIVATE``).\n\n.. image:: assets/circle_with_hole.svg\n :align: center\n\n.. _sketching_on_other_planes:","api_names":"ADD BuildSketch Circle circle_with_hole INTERSECT mode modes PRIVATE Rectangle REPLACE scope sketch SUBTRACT with","synonyms":"bore channel drill groove path cut recessed fastener"},"38":{"title":"BuildSketch","body":"BuildSketch is a python context manager that is used to create planar two dimensional\nobjects - objects with the property of area but not volume - that are typically\nused as profiles for BuildPart operations like :func:`~operations_part.extrude` or\n:func:`~operations_part.revolve`.\n\nThe complete API for BuildSketch is located at the end of this section.","api_names":"extrude revolve","synonyms":"axisymmetric lathe turned"},"39":{"title":"Local vs. Global Sketches","body":"In the above example the target for the sketch was not ``Plane.XY`` but a workplane\npassed by the user. Internally ``BuildSketch`` is always creating the sketch\non ``Plane.XY`` which one can see by looking at the ``sketch_local`` property of your\nsketch. For example, to display the local version of the ``display`` sketch from\nabove, one would use:\n\n.. code-block:: build123d\n\n show_object(display.sketch_local, name=\"sketch on Plane.XY\")\n\nwhile the sketches as applied to their target workplanes is accessible through\nthe ``sketch`` property, as follows:\n\n.. code-block:: build123d\n\n show_object(display.sketch, name=\"sketch on target workplane(s)\")\n\nWhen using the :func:`~operations_generic.add` operation to add an external Face\nto a sketch the face will automatically be reoriented to ``Plane.XY`` before being\ncombined with the sketch. As Faces don't provide an x-direction it's possible\nthat the new Face may not be oriented as expected. To reorient the Face manually\nto ``Plane.XY`` one can use the :meth:`~geometry.to_local_coords` method as\nfollows:\n\n.. code-block:: build123d\n\n reoriented_face = plane.to_local_coords(face)\n\nwhere ``plane`` is the plane that ``face`` was constructed on.","api_names":"add BuildSketch display face plane show_object sketch sketch_local to_local_coords workplane XY","synonyms":""},"40":{"title":"Locating Features","body":"Within a sketch features are positioned with ``Locations`` contexts\n(see :ref:`Location Context `) on the current workplane(s). The following\nlocation contexts are available within a sketch:\n\n* :class:`~build_common.GridLocations` : a X/Y grid of locations\n* :class:`~build_common.HexLocations` : a hex grid of locations ideal for nesting circles\n* :class:`~build_common.Locations` : a sequence of arbitrary locations\n* :class:`~build_common.PolarLocations` : locations defined by radius and angle\n\nGenerally one would specify tuples of (X, Y) values when defining locations but\nthere are many options available to the user.","api_names":"contexts GridLocations HexLocations Locations of PolarLocations workplane","synonyms":"array pattern repeat"},"41":{"title":"Reference","body":".. py:module:: build_sketch\n\n.. autoclass:: BuildSketch\n :members:","api_names":"BuildSketch","synonyms":""},"42":{"title":"Sketching on other Planes","body":"Often when designing parts one needs to build on top of other features. To facilitate\ndoing this ``BuildSketch`` allows one to create sketches on any Plane while allowing\nthe designer to work in a local X, Y coordinate system. It might be helpful to think\nof what is happening with this metaphor:\n\n#. When instantiating ``BuildSketch`` one or more workplanes can be passed as parameters.\n These are the placement targets for the completed sketch.\n#. The designer draws on a flat \"drafting table\" which is ``Plane.XY``.\n#. Once the sketch is complete, it's applied like a sticker to all of the workplanes\n passed in step 1.\n\nAs an example, let's build the following simple control box with a display on an angled plane:\n\n.. image:: assets/controller.svg\n :align: center\n\nHere is the code:\n\n.. code-block:: build123d\n\n with BuildPart() as controller:\n # Create the side view of the controller\n with BuildSketch(Plane.YZ) as profile:\n with BuildLine():\n Polyline((0, 0), (0, 40), (20, 80), (40, 80), (40, 0), (0, 0))\n # Create a filled face from the perimeter drawing\n make_face()\n # Extrude to create the basis controller shape\n extrude(amount=30, both=True)\n # Round off all the edges\n fillet(controller.edges(), radius=3)\n # Hollow out the controller\n offset(amount=-1, mode=Mode.SUBTRACT)\n # Extract the face that will house the display\n display_face = (\n controller.faces()\n .filter_by(GeomType.PLANE)\n .filter_by_position(Axis.Z, 50, 70)[0]\n )\n # Create a workplane from the face\n display_workplane = Plane(\n origin=display_face.center(), x_dir=(1, 0, 0), z_dir=display_face.normal_at()\n )\n # Place the sketch directly on the controller\n with BuildSketch(display_workplane) as display:\n RectangleRounded(40, 30, 2)\n with GridLocations(45, 35, 2, 2):\n Circle(1)\n # Cut the display sketch through the controller\n extrude(amount=-1, mode=Mode.SUBTRACT)\n\nThe highlighted part of the code shows how a face is extracted from the design,\na workplane is constructed from this face and finally this workplane is passed\nto ``BuildSketch`` as the target for the complete sketch. Notice how the\n``display`` sketch uses local coordinates for its features thus avoiding having\nthe user to determine how to move and rotate the sketch to get it where it\nshould go.\n\nNote that ``BuildSketch`` accepts a sequence planes, faces and locations for\nworkplanes so creation of an explicit workplane is often not required. Being\nable to work on multiple workplanes at once allows for features to be created\non multiple side of an object - say both the top and bottom - which is convenient\nfor symmetric parts.","api_names":"BuildLine BuildPart BuildSketch center Circle display edges extrude faces fillet filter_by filter_by_position GridLocations make_face normal_at offset Plane Polyline RectangleRounded XY","synonyms":"array bevel edge channel fit gap groove hollow path cut pattern repeat round edge shell tolerance wall thickness"},"43":{"title":"Builder Common API Reference","body":"The following are common to all the builders.","api_names":"","synonyms":""},"44":{"title":"Enums","body":".. py:module:: build_enums\n\n.. autoclass:: Align\n.. autoclass:: CenterOf\n.. autoclass:: FontStyle\n.. autoclass:: GeomType\n.. autoclass:: Keep\n.. autoclass:: Kind\n.. autoclass:: Mode\n.. autoclass:: Select\n.. autoclass:: SortBy\n.. autoclass:: Transition\n.. autoclass:: Until","api_names":"Align CenterOf FontStyle GeomType Keep Kind Mode Select SortBy Transition Until","synonyms":""},"45":{"title":"Locations","body":".. autoclass:: build_common::Locations\n.. autoclass:: build_common::GridLocations\n.. autoclass:: build_common::HexLocations\n.. autoclass:: build_common::PolarLocations","api_names":"build_common","synonyms":"array pattern repeat"},"46":{"title":"Selector Methods","body":".. automethod:: build_common::Builder.vertices\n.. automethod:: build_common::Builder.faces\n.. automethod:: build_common::Builder.edges\n.. automethod:: build_common::Builder.wires\n.. automethod:: build_common::Builder.solids","api_names":"build_common","synonyms":""},"47":{"title":"Builders","body":"The following sections describe each of the build123d stateful context builders.\n\n.. toctree::\n :maxdepth: 2\n\n build_line.rst\n build_sketch.rst\n build_part.rst","api_names":"","synonyms":""},"48":{"title":"CAD Object Centers","body":"Finding the center of a CAD object is a surprisingly complex operation. To illustrate\nlet's consider two examples: a simple isosceles triangle and a curved line (their bounding\nboxes are shown with dashed lines):\n\n.. image:: assets/center.svg\n :width: 49%\n\n.. image:: assets/one_d_center.svg\n :width: 49%\n\n\nOne can see that there is are significant differences between the different types of \ncenters. To allow the designer to choose the center that makes the most sense for the given\nshape there are three possible values for the :class:`~build_enums.CenterOf` Enum:\n\n============================== ====== == == == ========\n:class:`~build_enums.CenterOf` Symbol 1D 2D 3D Compound\n============================== ====== == == == ========\nCenterOf.BOUNDING_BOX □ ✓ ✓ ✓ ✓\nCenterOf.GEOMETRY △ ✓ ✓ \nCenterOf.MASS ○ ✓ ✓ ✓ ✓\n============================== ====== == == == ========","api_names":"CenterOf line","synonyms":""},"49":{"title":"Cheat Sheet","body":".. card:: Stateful Contexts\n\n | :class:`~build_line.BuildLine` :class:`~build_part.BuildPart` :class:`~build_sketch.BuildSketch`\n | :class:`~build_common.GridLocations` :class:`~build_common.HexLocations` :class:`~build_common.Locations` :class:`~build_common.PolarLocations`\n\n.. card:: Objects\n\n .. grid:: 3\n\n .. grid-item-card:: 1D - BuildLine\n\n | :class:`~objects_curve.Airfoil`\n | :class:`~objects_curve.ArcArcTangentArc`\n | :class:`~objects_curve.ArcArcTangentLine`\n | :class:`~objects_curve.Bezier`\n | :class:`~objects_curve.BlendCurve`\n | :class:`~objects_curve.BSpline`\n | :class:`~objects_curve.CenterArc`\n | :class:`~objects_curve.ConstrainedArcs`\n | :class:`~objects_curve.ConstrainedLines`\n | :class:`~objects_curve.DoubleTangentArc`\n | :class:`~objects_curve.EllipticalCenterArc`\n | :class:`~objects_curve.ParabolicCenterArc`\n | :class:`~objects_curve.HyperbolicCenterArc`\n | :class:`~objects_curve.FilletPolyline`\n | :class:`~objects_curve.Helix`\n | :class:`~objects_curve.IntersectingLine`\n | :class:`~objects_curve.JernArc`\n | :class:`~objects_curve.Line`\n | :class:`~objects_curve.PointArcTangentArc`\n | :class:`~objects_curve.PointArcTangentLine`\n | :class:`~objects_curve.PolarLine`\n | :class:`~objects_curve.Polyline`\n | :class:`~objects_curve.RadiusArc`\n | :class:`~objects_curve.SagittaArc`\n | :class:`~objects_curve.Spline`\n | :class:`~objects_curve.TangentArc`\n | :class:`~objects_curve.ThreePointArc`\n\n .. grid-item-card:: 2D - BuildSketch\n\n | :class:`~drafting.Arrow`\n | :class:`~drafting.ArrowHead`\n | :class:`~objects_sketch.Circle`\n | :class:`~drafting.DimensionLine`\n | :class:`~objects_sketch.Ellipse`\n | :class:`~drafting.ExtensionLine`\n | :class:`~objects_sketch.Polygon`\n | :class:`~objects_sketch.Rectangle`\n | :class:`~objects_sketch.RectangleRounded`\n | :class:`~objects_sketch.RegularPolygon`\n | :class:`~objects_sketch.SlotArc`\n | :class:`~objects_sketch.SlotCenterPoint`\n | :class:`~objects_sketch.SlotCenterToCenter`\n | :class:`~objects_sketch.SlotOverall`\n | :class:`~objects_sketch.Text`\n | :class:`~drafting.TechnicalDrawing`\n | :class:`~objects_sketch.Trapezoid`\n | :class:`~objects_sketch.Triangle`\n\n .. grid-item-card:: 3D - BuildPart\n\n | :class:`~objects_part.Box`\n | :class:`~objects_part.Cone`\n | :class:`~objects_part.ConvexPolyhedron`\n | :class:`~objects_part.CounterBoreHole`\n | :class:`~objects_part.CounterSinkHole`\n | :class:`~objects_part.Cylinder`\n | :class:`~objects_part.Hole`\n | :class:`~objects_part.Sphere`\n | :class:`~objects_part.Torus`\n | :class:`~objects_part.Wedge`\n\n.. card:: Operations\n\n .. grid:: 3\n\n .. grid-item-card:: 1D - BuildLine\n\n | :func:`~operations_generic.add`\n | :func:`~operations_generic.bounding_box`\n | :func:`~operations_generic.mirror`\n | :func:`~operations_generic.offset`\n | :func:`~operations_generic.project`\n | :func:`~operations_generic.scale`\n | :func:`~operations_generic.split`\n\n .. grid-item-card:: 2D - BuildSketch\n\n | :func:`~operations_generic.add`\n | :func:`~operations_generic.chamfer`\n | :func:`~operations_generic.fillet`\n | :func:`~operations_sketch.full_round`\n | :func:`~operations_sketch.make_face`\n | :func:`~operations_sketch.make_hull`\n | :func:`~operations_generic.mirror`\n | :func:`~operations_generic.offset`\n | :func:`~operations_generic.project`\n | :func:`~operations_generic.scale`\n | :func:`~operations_generic.split`\n | :func:`~operations_generic.sweep`\n | :func:`~operations_sketch.trace`\n\n .. grid-item-card:: 3D - BuildPart\n\n | :func:`~operations_generic.add`\n | :func:`~operations_generic.chamfer`\n | :func:`~operations_part.draft`\n | :func:`~operations_part.extrude`\n | :func:`~operations_generic.fillet`\n | :func:`~operations_part.loft`\n | :func:`~operations_part.make_brake_formed`\n | :func:`~operations_generic.mirror`\n | :func:`~operations_generic.offset`\n | :func:`~operations_generic.project`\n | :func:`~operations_part.revolve`\n | :func:`~operations_generic.scale`\n | :func:`~operations_part.section`\n | :func:`~operations_generic.split`\n | :func:`~operations_generic.sweep`\n\n.. card:: Selectors\n\n .. grid:: 3\n\n .. grid-item-card:: 1D - BuildLine\n\n | :meth:`~build_common.Builder.vertices`\n | :meth:`~build_common.Builder.edges`\n | :meth:`~build_common.Builder.wires`\n\n .. grid-item-card:: 2D - BuildSketch\n\n | :meth:`~build_common.Builder.vertices`\n | :meth:`~build_common.Builder.edges`\n | :meth:`~build_common.Builder.wires`\n | :meth:`~build_common.Builder.faces`\n\n .. grid-item-card:: 3D - BuildPart\n\n | :meth:`~build_common.Builder.vertices`\n | :meth:`~build_common.Builder.edges`\n | :meth:`~build_common.Builder.wires`\n | :meth:`~build_common.Builder.faces`\n | :meth:`~build_common.Builder.solids`\n\n.. card:: Selector Operators\n\n +----------+---------------------------------------------------------------------------------------------------------+------------------------------------------------+\n | Operator | Operand | Method |\n +==========+=========================================================================================================+================================================+\n | > | :class:`~geometry.Axis`, :class:`~topology.Edge`, :class:`~topology.Wire`, :class:`~build_enums.SortBy` | :meth:`~topology.ShapeList.sort_by` |\n +----------+---------------------------------------------------------------------------------------------------------+------------------------------------------------+\n | < | :class:`~geometry.Axis`, :class:`~topology.Edge`, :class:`~topology.Wire`, :class:`~build_enums.SortBy` | :meth:`~topology.ShapeList.sort_by` |\n +----------+---------------------------------------------------------------------------------------------------------+------------------------------------------------+\n | >> | :class:`~geometry.Axis`, :class:`~topology.Edge`, :class:`~topology.Wire`, :class:`~build_enums.SortBy` | :meth:`~topology.ShapeList.group_by`\\[-1\\] |\n +----------+---------------------------------------------------------------------------------------------------------+------------------------------------------------+\n | << | :class:`~geometry.Axis`, :class:`~topology.Edge`, :class:`~topology.Wire`, :class:`~build_enums.SortBy` | :meth:`~topology.ShapeList.group_by`\\[0\\] |\n +----------+---------------------------------------------------------------------------------------------------------+------------------------------------------------+\n | \\| | :class:`~geometry.Axis`, :class:`~geometry.Plane`, :class:`~build_enums.GeomType` | :meth:`~topology.ShapeList.filter_by` |\n +----------+---------------------------------------------------------------------------------------------------------+------------------------------------------------+\n | [] | | python indexing / slicing |\n +----------+---------------------------------------------------------------------------------------------------------+------------------------------------------------+\n | | :class:`~geometry.Axis` | :meth:`~topology.ShapeList.filter_by_position` |\n +----------+---------------------------------------------------------------------------------------------------------+------------------------------------------------+\n\n.. card:: Edge and Wire Operators\n\n +----------+---------------------+-----------------------------------------+---------------------------------+\n | Operator | Operand | Method | Description |\n +==========+=====================+=========================================+=================================+\n | @ | 0.0 <= float <= 1.0 | :meth:`~topology.Mixin1D.position_at` | Position as Vector along object |\n +----------+---------------------+-----------------------------------------+---------------------------------+\n | % | 0.0 <= float <= 1.0 | :meth:`~topology.Mixin1D.tangent_at` | Tangent as Vector along object |\n +----------+---------------------+-----------------------------------------+---------------------------------+\n | ^ | 0.0 <= float <= 1.0 | :meth:`~topology.Mixin1D.location_at` | Location along object |\n +----------+---------------------+-----------------------------------------+---------------------------------+\n\n.. card:: Shape Operators\n\n +----------+---------------------------+-----------------------------------------+---------------------------------------------+\n | Operator | Operand | Method | Description |\n +==========+===========================+=========================================+=============================================+\n | == | Any | :meth:`~topology.Shape.is_same` | Compare CAD objects not including meta data |\n +----------+---------------------------+-----------------------------------------+---------------------------------------------+\n | \\+ | Shape \\| Iterable[Shape] | | Add CAD objects |\n +----------+---------------------------+-----------------------------------------+---------------------------------------------+\n | \\- | Shape \\| Iterable[Shape] | | Subtract CAD objects |\n +----------+---------------------------+-----------------------------------------+---------------------------------------------+\n | \\& | Shape \\| Iterable[Shape] | | Intersect CAD objects |\n +----------+---------------------------+-----------------------------------------+---------------------------------------------+\n\n.. card:: Plane Operators\n\n +----------+--------------------------------------+-----------------------------+\n | Operator | Operand | Description |\n +==========+======================================+=============================+\n | == | :class:`~geometry.Plane` | Check for equality |\n +----------+--------------------------------------+-----------------------------+\n | != | :class:`~geometry.Plane` | Check for inequality |\n +----------+--------------------------------------+-----------------------------+\n | \\- | :class:`~geometry.Plane` | Reverse direction of normal |\n +----------+--------------------------------------+-----------------------------+\n | \\* | :class:`~geometry.Location` \\| Shape | Relocate |\n +----------+--------------------------------------+-----------------------------+\n\n.. card:: Location Operators\n\n +----------+-----------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+\n | Operator | Operand | Description |\n +==========+=========================================================================================================================================+=============================+\n | == | :class:`~geometry.Location` | Check for equality |\n +----------+-----------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+\n | != | :class:`~geometry.Location` | Check for inequality |\n +----------+-----------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+\n | \\- | :class:`~geometry.Location` | Reverse direction of normal |\n +----------+-----------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+\n | \\& | :class:`~geometry.Axis` \\| :class:`~geometry.Location` \\| :class:`~geometry.Plane` \\| ``VectorLike`` \\| :class:`~topology.Shape` | Intersect |\n +----------+-----------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+\n | \\* | :class:`~geometry.Shape` \\| :class:`~geometry.Location` \\| Iterable[:class:`~geometry.Location`] | Relocate |\n +----------+-----------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+\n\n.. card:: Vector Operators\n\n +----------+------------------------------+-------------------------------------+---------------------+\n | Operator | Operand | Method | Description |\n +==========+==============================+=====================================+=====================+\n | \\+ | :class:`~geometry.Vector` | :meth:`~geometry.Vector.add` | add |\n +----------+------------------------------+-------------------------------------+---------------------+\n | \\- | :class:`~geometry.Vector` | :meth:`~geometry.Vector.sub` | subtract |\n +----------+------------------------------+-------------------------------------+---------------------+\n | \\* | ``float`` | :meth:`~geometry.Vector.multiply` | multiply by scalar |\n +----------+------------------------------+-------------------------------------+---------------------+\n | \\/ | ``float`` | :meth:`~geometry.Vector.multiply` | divide by scalar |\n +----------+------------------------------+-------------------------------------+---------------------+\n\n.. card:: Vertex Operators\n\n +----------+-----------------------------+-------------------------------------+\n | Operator | Operand | Method |\n +==========+=============================+=====================================+\n | \\+ | :class:`~topology.Vertex` | :meth:`~topology.Vertex.add` |\n +----------+-----------------------------+-------------------------------------+\n | \\- | :class:`~topology.Vertex` | :meth:`~topology.Vertex.sub` |\n +----------+-----------------------------+-------------------------------------+\n\n.. card:: Enums\n\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.Align` | MIN, CENTER, MAX |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.ApproxOption` | ARC, NONE, SPLINE |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.AngularDirection` | CLOCKWISE, COUNTER_CLOCKWISE |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.CenterOf` | GEOMETRY, MASS, BOUNDING_BOX |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.Extrinsic` | XYZ, XZY, YZX, YXZ, ZXY, ZYX, XYX, XZX, YZY, YXY, ZXZ, ZYZ |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.FontStyle` | REGULAR, BOLD, BOLDITALIC, ITALIC |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.FrameMethod` | CORRECTED, FRENET |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.GeomType` | BEZIER, BSPLINE, CIRCLE, CONE, CYLINDER, ELLIPSE, EXTRUSION, HYPERBOLA, LINE, OFFSET, OTHER, PARABOLA, PLANE, REVOLUTION, SPHERE, TORUS |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.Intrinsic` | XYZ, XZY, YZX, YXZ, ZXY, ZYX, XYX, XZX, YZY, YXY, ZXZ, ZYZ |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.HeadType` | CURVED, FILLETED, STRAIGHT |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.Keep` | ALL, TOP, BOTTOM, BOTH, INSIDE, OUTSIDE |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.Kind` | ARC, INTERSECTION, TANGENT |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.LengthMode` | DIAGONAL, HORIZONTAL, VERTICAL |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.MeshType` | OTHER, MODEL, SUPPORT, SOLIDSUPPORT |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.Mode` | ADD, SUBTRACT, INTERSECT, REPLACE, PRIVATE |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.NumberDisplay` | DECIMAL, FRACTION |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.PageSize` | A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, LEDGER, LEGAL, LETTER |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.PositionMode` | LENGTH, PARAMETER |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.PrecisionMode` | LEAST, AVERAGE, GREATEST, SESSION |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.Select` | ALL, LAST, NEW |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.Side` | BOTH, LEFT, RIGHT |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.SortBy` | LENGTH, RADIUS, AREA, VOLUME, DISTANCE |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.TextAlign` | BOTTOM, CENTER, LEFT, RIGHT, TOP, TOPFIRSTLINE |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.Transition` | RIGHT, ROUND, TRANSFORMED |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.Unit` | MC, MM, CM, M, IN, FT |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+\n | :class:`~build_enums.Until` | FIRST, LAST, NEXT, PREVIOUS |\n +----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+","api_names":"add Airfoil Align AngularDirection ApproxOption ArcArcTangentArc ArcArcTangentLine Arrow ArrowHead Axis Bezier BlendCurve bounding_box Box BSpline BuildLine BuildPart BuildSketch CenterArc CenterOf chamfer Circle Cone ConstrainedArcs ConstrainedLines ConvexPolyhedron CounterBoreHole CounterSinkHole Cylinder DimensionLine DoubleTangentArc draft Edge edges Ellipse EllipticalCenterArc ExtensionLine Extrinsic extrude faces fillet FilletPolyline filter_by filter_by_position FontStyle FrameMethod full_round GeomType GridLocations group_by HeadType Helix HexLocations Hole HyperbolicCenterArc IntersectingLine Intrinsic is_same JernArc Keep Kind LengthMode Line Location location_at Locations loft make_brake_formed make_face make_hull MeshType mirror Mode multiply NumberDisplay offset PageSize ParabolicCenterArc Plane PointArcTangentArc PointArcTangentLine PolarLine PolarLocations Polygon Polyline position_at PositionMode PrecisionMode project RadiusArc Rectangle RectangleRounded RegularPolygon revolve SagittaArc scale section Select Shape Side SlotArc SlotCenterPoint SlotCenterToCenter SlotOverall solids sort_by SortBy Sphere Spline split sub sweep tangent_at TangentArc TechnicalDrawing Text TextAlign ThreePointArc Torus trace Transition Trapezoid Triangle Unit Until Vector VectorLike Vertex vertices Wedge Wire wires","synonyms":"array axisymmetric bevel edge blend profiles bore channel coil control points cross sections cut in half drill fit gap groove hollow interpolation lathe path cut pattern recessed fastener reflect repeat round edge shell slice smooth curve spiral symmetry thread path tolerance transition trim turned wall thickness"},"50":{"title":"Debugging & Logging","body":"Debugging problems with your build123d design involves the same techniques\none would use to debug any Python source code; however, there are some\nspecific techniques that might be of assistance. The following sections\ndescribe these techniques.","api_names":"","synonyms":""},"51":{"title":"Logging","body":"Build123d support standard python logging and generates its own log stream.\nIf one is using **cq-editor** as a display system there is a built in\n``Log viewer`` tab that shows the current log stream - here is an example\nof a log stream:\n\n.. code-block:: bash\n\n [18:43:44.678646] INFO: Entering BuildPart with mode=Mode.ADD which is in different scope as parent\n [18:43:44.679233] INFO: WorkplaneList is pushing 1 workplanes: [Plane(o=(0.00, 0.00, 0.00), x=(1.00, 0.00, 0.00), z=(0.00, 0.00, 1.00))]\n [18:43:44.679888] INFO: LocationList is pushing 1 points: [(p=(0.00, 0.00, 0.00), o=(-0.00, 0.00, -0.00))]\n [18:43:44.681751] INFO: BuildPart context requested by Box\n [18:43:44.685950] INFO: Completed integrating 1 object(s) into part with Mode=Mode.ADD\n [18:43:44.690072] INFO: GridLocations is pushing 4 points: [(p=(-30.00, -20.00, 0.00), o=(-0.00, 0.00, -0.00)), (p=(-30.00, 20.00, 0.00), o=(-0.00, 0.00, -0.00)), (p=(30.00, -20.00, 0.00), o=(-0.00, 0.00, -0.00)), (p=(30.00, 20.00, 0.00), o=(-0.00, 0.00, -0.00))]\n [18:43:44.691604] INFO: BuildPart context requested by Hole\n [18:43:44.724628] INFO: Completed integrating 4 object(s) into part with Mode=Mode.SUBTRACT\n [18:43:44.728681] INFO: GridLocations is popping 4 points\n [18:43:44.747358] INFO: BuildPart context requested by chamfer\n [18:43:44.762429] INFO: Completed integrating 1 object(s) into part with Mode=Mode.REPLACE\n [18:43:44.765380] INFO: LocationList is popping 1 points\n [18:43:44.766106] INFO: WorkplaneList is popping 1 workplanes\n [18:43:44.766729] INFO: Exiting BuildPart\n\nThe build123d logger is defined by:\n\n.. code-block:: python\n\n logging.getLogger(\"build123d\").addHandler(logging.NullHandler())\n logger = logging.getLogger(\"build123d\")\n\nTo export logs to a file, the following configuration is recommended:\n\n.. code-block:: python\n\n logging.basicConfig(\n filename=\"myapp.log\",\n level=logging.INFO,\n format=\"%(name)s-%(levelname)s %(asctime)s - [%(filename)s:%(lineno)s - \\\n %(funcName)20s() ] - %(message)s\",\n )\n\nLogs can be easily placed in your code - here is an example:\n\n.. code-block:: python\n\n logger.info(\"Exiting %s\", type(self).__name__)","api_names":"addHandler basicConfig getLogger info Log NullHandler object Plane type","synonyms":"array bevel edge bore channel drill groove path cut pattern recessed fastener repeat round edge"},"52":{"title":"Printing","body":"Sometimes the best debugging aid is just placing a print statement in your code. Many\nof the build123d classes are setup to provide useful information beyond their class and\nlocation in memory, as follows:\n\n.. code-block:: build123d\n\n plane = Plane.XY.offset(1)\n print(f\"{plane=}\")\n\n.. code-block:: bash\n\n plane=Plane(o=(0.00, 0.00, 1.00), x=(1.00, 0.00, 0.00), z=(0.00, 0.00, 1.00))\n\nwhich shows the origin, x direction, and z direction of the plane.","api_names":"offset Plane","synonyms":"fit gap hollow shell tolerance wall thickness"},"53":{"title":"Python Debugger","body":"Many Python IDEs have step by step debugging systems that can be used to\nwalk through your code monitoring its operation with full visibility\nof all Python objects. Here is a screenshot of the Visual Studio Code\ndebugger in action:\n\n.. image:: assets/VSC_debugger.png\n :align: center\n\nThis shows that a break-point has been encountered and the code operation\nhas been stopped. From here all of the Python variables are visible and\nthe system is waiting on input from the user on how to proceed. One can\nenter the code that assigns ``top_face`` by pressing the down arrow button\non the top right. Following code execution like this is a very powerful\ndebug technique.","api_names":"top_face","synonyms":""},"54":{"title":"Direct API Reference","body":"The Direct API is an interface layer between the primary user interface API\n(the Builders) and the OpenCascade (OCCT) API. This API is based on the CadQuery\nDirect API (thank you to all of the CadQuery contributors that made this possible)\nwith the following major changes:\n\n* PEP8 compliance\n* New Axis class\n* New ShapeList class enabling sorting and filtering of shape objects\n* Literal strings replaced with Enums","api_names":"API OpenCascade","synonyms":""},"55":{"title":"Geometric Objects","body":"The geometric classes defined by build123d are defined below. This parameters to the\nCAD objects described in the following section are frequently of these types.\n\n.. inheritance-diagram:: geometry\n :parts: 1\n\n.. py:module:: geometry\n\n.. autoclass:: Axis\n :special-members: __copy__,__deepcopy__, __neg__\n.. autoclass:: BoundBox\n.. autoclass:: Color\n :special-members: __copy__,__deepcopy__\n.. autoclass:: Location\n :special-members: __copy__,__deepcopy__, __mul__, __pow__, __eq__, __neg__\n.. autoclass:: LocationEncoder\n.. autoclass:: Pos\n.. autoclass:: Rot\n.. autoclass:: Matrix\n :special-members: __copy__,__deepcopy__\n.. autoclass:: Plane\n :special-members: __copy__,__deepcopy__, __eq__, __ne__, __neg__, __mul__\n.. autoclass:: Rotation\n.. autoclass:: Vector\n :special-members: __add__, __sub__, __mul__, __truediv__, __rmul__, __neg__, __abs__, __eq__, __copy__, __deepcopy__","api_names":"Axis BoundBox Color Location LocationEncoder Matrix Plane Pos Rot Rotation Vector","synonyms":""},"56":{"title":"Import/Export","body":"Methods and functions specific to exporting and importing build123d objects are defined below.\n\n.. py:module:: importers\n :noindex:\n\n.. autofunction:: import_brep\n :noindex:\n.. autofunction:: import_step\n :noindex:\n.. autofunction:: import_stl\n :noindex:\n.. autofunction:: import_svg\n :noindex:\n.. autofunction:: import_svg_as_buildline_code\n :noindex:","api_names":"import_brep import_step import_stl import_svg import_svg_as_buildline_code","synonyms":""},"57":{"title":"Joint Object","body":"Base Joint class which is used to position Solid and Compound objects relative to each\nother are defined below. The :ref:`joints` section contains the class description of the\nderived Joint classes.\n\n.. py:module:: topology\n :noindex:\n\n.. autoclass:: Joint","api_names":"Joint","synonyms":""},"58":{"title":"Topological Objects","body":"The topological object classes defined by build123d are defined below.\n\nNote that the :class:`~topology.Mixin1D` and :class:`~topology.Mixin3D` classes add\nsupplementary functionality specific to 1D\n(:class:`~topology.Edge` and :class:`~topology.Wire`) and 3D (:class:`~topology.Compound` and\n`~topology.Solid`) objects respectively.\nNote that a :class:`~topology.Compound` may be contain only 1D, 2D (:class:`~topology.Face`) or 3D objects.\n\n.. inheritance-diagram:: topology.shape_core topology.zero_d topology.one_d topology.two_d topology.three_d topology.composite topology.utils\n :parts: 1\n\n.. py:module:: topology\n\n.. autoclass:: Compound\n.. autoclass:: Edge\n.. autoclass:: Face\n :special-members: __neg__\n.. autoclass:: Mixin1D\n :special-members: __matmul__, __mod__\n.. autoclass:: Mixin2D\n.. autoclass:: Mixin3D\n.. autoclass:: Shape\n :special-members: __add__, __sub__, __and__, __rmul__, __eq__, __copy__, __deepcopy__, __hash__\n.. autoclass:: ShapeList\n :special-members: __gt__, __lt__, __rshift__, __lshift__, __or__, __and__, __sub__, __getitem__\n.. autoclass:: Shell\n.. autoclass:: Solid\n.. autoclass:: Wire\n.. autoclass:: Vertex\n :special-members: __add__, __sub__\n.. autoclass:: Curve\n :special-members: __matmul__, __mod__\n.. autoclass:: Part\n.. autoclass:: Sketch","api_names":"Compound Curve Edge Face Mixin1D Mixin2D Mixin3D Part Shape ShapeList Shell Sketch Solid Vertex Wire","synonyms":""},"59":{"title":"Benchy","body":".. image:: assets/examples/example_benchy_01.png\n :align: center\n\n\nThe Benchy examples shows how to import a STL model as a `Solid` object with the class `Mesher` and\nmodify it by replacing chimney with a BREP version.\n\n- Benchy STL model: :download:`low_poly_benchy.stl <../examples/low_poly_benchy.stl>`\n\n\n.. note\n\n *Attribution:*\n The low-poly-benchy used in this example is by `reddaugherty`, see\n https://www.printables.com/model/151134-low-poly-benchy.\n\n\n.. dropdown:: Gallery\n\n .. image:: assets/examples/example_benchy_02.png\n :align: center\n\n\n .. image:: assets/examples/example_benchy_03.png\n :align: center\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n # Import the benchy as a Solid model\n importer = Mesher()\n benchy_stl = importer.read(\"low_poly_benchy.stl\")[0]\n \n with BuildPart() as benchy:\n add(benchy_stl)\n \n # Determine the plane that defines the top of the roof\n vertices = benchy.vertices()\n roof_vertices = vertices.filter_by_position(Axis.Z, 38, 42)\n roof_plane_vertices = [\n roof_vertices.group_by(Axis.Y, tol_digits=2)[-1].sort_by(Axis.X)[0],\n roof_vertices.sort_by(Axis.Z)[0],\n roof_vertices.group_by(Axis.Y, tol_digits=2)[0].sort_by(Axis.X)[0],\n ]\n roof_plane = Plane(\n Face(Wire.make_polygon([v.to_tuple() for v in roof_plane_vertices]))\n )\n # Remove the faceted smoke stack\n split(bisect_by=roof_plane, keep=Keep.BOTTOM)\n \n # Determine the position and size of the smoke stack\n smoke_stack_vertices = vertices.group_by(Axis.Z, tol_digits=0)[-1]\n smoke_stack_center = sum(\n [Vector(v.X, v.Y, v.Z) for v in smoke_stack_vertices], Vector()\n ) * (1 / len(smoke_stack_vertices))\n smoke_stack_radius = max(\n [\n (Vector(*v.to_tuple()) - smoke_stack_center).length\n for v in smoke_stack_vertices\n ]\n )\n \n # Create the new smoke stack\n with BuildSketch(Plane(smoke_stack_center)):\n Circle(smoke_stack_radius)\n Circle(smoke_stack_radius - 2 * MM, mode=Mode.SUBTRACT)\n extrude(amount=-3 * MM)\n with BuildSketch(Plane(smoke_stack_center)):\n Circle(smoke_stack_radius - 0.5 * MM)\n Circle(smoke_stack_radius - 2 * MM, mode=Mode.SUBTRACT)\n extrude(amount=roof_plane_vertices[1].Z - smoke_stack_center.Z)\n \n show(benchy)\n\n.. ----------------------------------------------------------------------------------------------\n\n.. _examples-bicycle_tire:","api_names":"add BuildPart BuildSketch Circle extrude Face filter_by_position group_by Implementation make_polygon Mesher Plane read show sort_by split to_tuple Vector vertices","synonyms":"channel cut in half groove path cut slice trim"},"60":{"title":"Bicycle Tire","body":".. image:: assets/examples/bicycle_tire.png\n :align: center\n\nThis example demonstrates how to model a realistic bicycle tire with a\npatterned tread using build123d. The key concept showcased here is the\nuse of wrap_faces to project 2D planar geometry onto a curved 3D\nsurface.\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n import copy\n from build123d import *\n from ocp_vscode import show\n \n wheel_diameter = 740 * MM\n \n with BuildSketch() as tire_profile:\n with BuildLine() as build_profile:\n l00 = Bezier((0.0, 0.0), (7.05, 0.0), (12.18, 1.54), (15.13, 4.54))\n l01 = Bezier(l00 @ 1, (15.81, 5.22), (15.98, 5.44), (16.5, 6.23))\n l02 = Bezier(l01 @ 1, (18.45, 9.19), (19.61, 13.84), (19.94, 20.06))\n l03 = Bezier(l02 @ 1, (20.1, 23.24), (19.93, 27.48), (19.56, 29.45))\n l04 = Bezier(l03 @ 1, (19.13, 31.69), (18.23, 33.67), (16.91, 35.32))\n l05 = Bezier(l04 @ 1, (16.26, 36.12), (15.57, 36.77), (14.48, 37.58))\n l06 = Bezier(l05 @ 1, (12.77, 38.85), (11.51, 40.28), (10.76, 41.78))\n l07 = Bezier(l06 @ 1, (10.07, 43.16), (10.15, 43.81), (11.03, 43.98))\n l08 = Bezier(l07 @ 1, (11.82, 44.13), (12.15, 44.55), (12.08, 45.33))\n l09 = Bezier(l08 @ 1, (12.01, 46.07), (11.84, 46.43), (11.43, 46.69))\n l10 = Bezier(l09 @ 1, (10.98, 46.97), (10.07, 46.7), (9.47, 46.1))\n l11 = Bezier(l10 @ 1, (9.03, 45.65), (8.88, 45.31), (8.84, 44.65))\n l12 = Bezier(l11 @ 1, (8.78, 43.6), (9.11, 42.26), (9.72, 41.0))\n l13 = Bezier(l12 @ 1, (10.43, 39.54), (11.52, 38.2), (12.78, 37.22))\n l14 = Bezier(l13 @ 1, (15.36, 35.23), (16.58, 33.76), (17.45, 31.62))\n l15 = Bezier(l14 @ 1, (17.91, 30.49), (18.22, 29.27), (18.4, 27.8))\n l16 = Bezier(l15 @ 1, (18.53, 26.78), (18.52, 23.69), (18.37, 22.61))\n l17 = Bezier(l16 @ 1, (17.8, 18.23), (16.15, 14.7), (13.39, 11.94))\n l18 = Bezier(l17 @ 1, (11.89, 10.45), (10.19, 9.31), (8.09, 8.41))\n l19 = Bezier(l18 @ 1, (3.32, 6.35), (0.0, 6.64))\n mirror(about=Plane.YZ)\n make_face()\n \n tire = revolve(Pos(Y=-wheel_diameter / 2) * tire_profile.face(), Axis.X)\n \n with BuildSketch() as tread_pattern:\n with Locations((1, 1)):\n Trapezoid(15, 12, 60, 120, align=Align.MIN)\n with Locations((1, 8)):\n with GridLocations(0, 5, 1, 2):\n Rectangle(50, 2, mode=Mode.SUBTRACT)\n \n # Define the surface and path that the tread pattern will be wrapped onto\n half_road_surface = Face.revolve(Pos(Y=-wheel_diameter / 2) * l00, 360, Axis.X)\n tread_path = half_road_surface.edges().sort_by(Axis.X)[0]\n \n # Wrap the planar tread pattern onto the tire's outside surface\n tread_faces = half_road_surface.wrap_faces(tread_pattern.faces(), tread_path)\n \n # Mirror the faces to the other half of the tire\n tread_faces.extend([mirror(t, Plane.YZ) for t in tread_faces])\n \n # Thicken the tread to become solid nubs\n # tread_prime = [Solid.thicken(f, 3 * MM) for f in tread_faces]\n tread_prime = [thicken(f, 3 * MM) for f in tread_faces]\n \n # Copy the nubs around the whole tire\n tread = [Rot(X=r) * copy.copy(t) for t in tread_prime for r in range(0, 360, 2)]\n \n show(tire, tread)\n\n\n.. _examples-bracelet:","api_names":"Bezier BuildLine BuildSketch copy edges extend face faces GridLocations Implementation Locations make_face mirror Pos Rectangle revolve Rot show sort_by thicken Trapezoid wrap_faces","synonyms":"array axisymmetric bore channel drill groove lathe path cut pattern recessed fastener reflect repeat symmetry turned"},"61":{"title":"Bracelet","body":".. image:: assets/examples/bracelet.png\n :align: center\n\nDoubly-curved bracelet with an embossed label\n\nThis model is a good “stress test” for OCCT because most of the final boundary\nsurfaces are *freeform* (not analytic planes/cylinders/spheres). The geometry\nis assembled from:\n\n- a swept center section (using a curved solid end-face as the sweep profile)\n- two freeform “tip caps” built as Gordon surfaces (network of curves)\n- an optional embossed text label projected onto a curved solid\n- alignment holes for splitting/printing/assembly\n\nKey techniques demonstrated:\n\n- using location_at/position_at/tangent (%) to extract local frames & tangents\n- projecting curves onto a non-planar surface to create “true” 3D guide curves\n- Gordon surfaces to build high-quality doubly-curved skins\n- projecting faces (text) onto a complex solid and thickening them\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import show\n \n # Define input parameters\n # - radii: ellipse radii (X, Y) controlling the bracelet centerline shape\n # - width: bracelet width (along Z for the center sweep)\n # - thickness: bracelet thickness (radial thickness of the cross section)\n # - opening_angle: the missing angle that creates the wrist opening\n # - label_str: optional text to emboss on the outside surface\n # - Define input parameters\n # radii, width, thickness, opening_angle, label_str = (45, 30), 25, 5, 80, \"build123d\"\n radii, width, thickness, opening_angle, label_str = (45, 30), 25, 5, 80, \"\"\n \n # Step 1: Create an elliptical arc defining the *centerline* of the bracelet.\n # The arc is truncated to leave an opening (the \"gap\" where the bracelet goes on).\n # Angles are in degrees; 270° points downward, which keeps the opening centered at the bottom.\n center_arc = EllipticalCenterArc(\n (0, 0), *radii, 270 + opening_angle / 2, arc_size=360 - opening_angle\n )\n \n # Step 2: Create HALF of the end cross-section, positioned at the end of the arc.\n # We build only half so we can later mirror it to enforce symmetry and reduce\n # curve-network complexity when building the freeform tip.\n #\n # location_at(1) returns a local coordinate frame at the arc end (tangent-aware).\n # x_dir is chosen so the section’s local \"X\" is well-defined and stable.\n end_center_arc = center_arc.location_at(1, x_dir=(0, 0, 1))\n half_x_section = EllipticalCenterArc(\n (0, 0), width / 2, thickness / 2, 90, arc_size=180\n ).locate(end_center_arc)\n \n # Step 3: Create a doubly-curved \"tip edge\" curve.\n # The tip edge must live in 3D and conform to the outside of the bracelet.\n # To do that, we:\n # 1) create a surface by extruding the center_arc into a sheet (a ribbon surface)\n # 2) build a planar arc in a local frame at the end of that surface\n # 3) project the planar arc onto the curved surface to get a true 3D curve\n #\n # The resulting tip_arc is a 3D edge that naturally matches the bracelet curvature.\n center_surface = -Face.extrude(center_arc, (0, 0, 2 * width)).moved(\n Location((0, 0, -width), (0, 0, 180))\n )\n tip_center_loc = -center_surface.location_at(center_arc @ 1, x_dir=(1, 0, 0))\n normal_at_tip_center = tip_center_loc.z_axis.direction\n \n # A planar arc that would represent the outer boundary of the tip *if* the surface\n # were flat. We immediately project it to make it truly conformal in 3D.\n planar_tip_arc = CenterArc((0, 0), width / 2, 270, 180).locate(tip_center_loc).edge()\n tip_arc = planar_tip_arc.project_to_shape(center_surface, -normal_at_tip_center)[0]\n \n # Step 4: Build the tip as a Gordon surface (a surface fit through a curve network).\n # Gordon surfaces are ideal when:\n # - you don’t have an obvious analytic surface\n # - curvature changes in two directions (doubly-curved \"cap\")\n # - you can define a consistent set of profile curves + guide curves\n #\n # Here:\n # - profiles define \"across the tip\" shape (section -> bulged spline -> mirrored section)\n # - guides define \"along the tip\" rails (start point -> projected 3D arc -> end point)\n #\n # Tangents are used to encourage smoothness where the tip joins the swept center section.\n profile = Spline(\n half_x_section @ 0,\n tip_arc @ 0.5,\n half_x_section @ 1,\n tangents=(center_arc % 1, -(center_arc % 1)),\n )\n tip_surface = Face.make_gordon_surface(\n profiles=[half_x_section, profile, half_x_section.mirror(Plane.XY)],\n guides=[half_x_section @ 0, tip_arc, half_x_section @ 1],\n )\n \n # Step 5: Close the tip surface into a watertight Solid.\n # tip_surface is the outer \"skin\"; we create a side face from its boundary wire\n # and make a shell, then a solid.\n tip_side = Face(tip_surface.wire())\n tip = Solid(Shell([tip_side, tip_surface]))\n \n # Step 6: Sweep the *flat end face* of the tip around the center arc.\n # This is the trick that makes the center section compatible with the freeform tip:\n # the sweep profile is the same face that bounds the tip, so the join is naturally aligned.\n center_section = sweep(tip_side, center_arc).solid()\n \n # Step 7: Assemble the bracelet from the center and two mirrored tips.\n # Mirror across YZ to create the opposite end cap.\n bracelet = Solid() + [tip, center_section, tip.mirror(Plane.YZ)]\n \n # Step 8: Add an embossed label.\n # This is often the hardest operation for OCCT in this model:\n # projecting text onto a doubly-curved surface can create many small faces/edges,\n # and thickening them adds even more boolean complexity.\n if label_str:\n label = Text(label_str, font_size=width * 0.8, align=Align.CENTER)\n \n # Project the text onto the bracelet using a path-based placement along center_arc.\n # The parameter offsets the label so it sits centered along arc-length.\n p_labels = bracelet.project_faces(\n label, center_arc, 0.5 - 0.5 * (label.bounding_box().size.X) / center_arc.length\n )\n # Turn the projected faces into solids via thickening (embossing).\n embossed_label = [Solid.thicken(f, 0.5) for f in p_labels.faces()]\n bracelet += embossed_label\n \n # Step 9: Add alignment holes to aid assembly after 3D printing in two halves.\n # These are placed at evenly spaced locations along the arc (including both ends).\n # A small clearance (+0.15) is included for typical FDM tolerances.\n alignment_holes = [\n Pos(p) * Cylinder(1.75 / 2 + 0.15, 8)\n for p in [center_arc.position_at(i / 4) for i in range(5)]\n ]\n bracelet -= alignment_holes\n \n show(bracelet)\n\n.. _examples-build123d_logo:","api_names":"arc bounding_box CenterArc clearance Cylinder directions edge EllipticalCenterArc end extrude Face faces Implementation locate Location location_at make_gordon_surface mirror moved opening Pos position_at project_faces project_to_shape radii rails section shape sheet Shell show solid Solid Spline surface surfaces sweep tangent Text thicken thickening thickness width wire","synonyms":"array bore channel control points cut in half drill fit gap groove hollow interpolation path cut pattern recessed fastener reflect repeat shell slice smooth curve symmetry tolerance trim wall thickness"},"62":{"title":"Canadian Flag Blowing in The Wind","body":".. image:: assets/examples/example_canadian_flag_01.png\n :align: center\n\n\n\nA Canadian Flag blowing in the wind created by projecting planar faces onto a non-planar face (the_wind).\n\nThis example also demonstrates building complex lines that snap to existing features.\n\n\n.. dropdown:: More Images\n\n .. image:: assets/examples/example_canadian_flag_02.png\n :align: center\n\n .. image:: assets/examples/example_canadian_flag_03.png\n :align: center\n\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n \n \n def surface(amplitude, u, v):\n \"\"\"Calculate the surface displacement of the flag at a given position\"\"\"\n return v * amplitude / 20 * cos(3.5 * pi * u) + amplitude / 10 * v * sin(\n 1.1 * pi * v\n )\n \n \n # Note that the surface to project on must be a little larger than the faces\n # being projected onto it to create valid projected faces\n the_wind = Face.make_surface_from_array_of_points(\n [\n [\n Vector(\n width * (v * 1.1 / 40 - 0.05),\n height * (u * 1.2 / 40 - 0.1),\n height * surface(wave_amplitude, u / 40, v / 40) / 2,\n )\n for u in range(41)\n ]\n for v in range(41)\n ]\n )\n with BuildSketch(Plane.XY.offset(10)) as west_field_builder:\n Rectangle(width / 4, height, align=(Align.MIN, Align.MIN))\n west_field_planar = west_field_builder.sketch.faces()[0]\n east_field_planar = west_field_planar.mirror(Plane.YZ.offset(width / 2))\n \n with BuildSketch(Plane((width / 2, 0, 10))) as center_field_builder:\n Rectangle(width / 2, height, align=(Align.CENTER, Align.MIN))\n with BuildSketch(\n Plane((width / 2, 0, 10)), mode=Mode.SUBTRACT\n ) as maple_leaf_builder:\n with BuildLine() as outline:\n l1 = Polyline((0.0000, 0.0771), (0.0187, 0.0771), (0.0094, 0.2569))\n l2 = Polyline((0.0325, 0.2773), (0.2115, 0.2458), (0.1873, 0.3125))\n RadiusArc(l1 @ 1, l2 @ 0, 0.0271)\n l3 = Polyline((0.1915, 0.3277), (0.3875, 0.4865), (0.3433, 0.5071))\n TangentArc(l2 @ 1, l3 @ 0, tangent=l2 % 1)\n l4 = Polyline((0.3362, 0.5235), (0.375, 0.6427), (0.2621, 0.6188))\n SagittaArc(l3 @ 1, l4 @ 0, 0.003)\n l5 = Polyline((0.2469, 0.6267), (0.225, 0.6781), (0.1369, 0.5835))\n ThreePointArc(\n l4 @ 1, (l4 @ 1 + l5 @ 0) * 0.5 + Vector(-0.002, -0.002), l5 @ 0\n )\n l6 = Polyline((0.1138, 0.5954), (0.1562, 0.8146), (0.0881, 0.7752))\n Spline(\n l5 @ 1,\n l6 @ 0,\n tangents=(l5 % 1, l6 % 0),\n tangent_scalars=(2, 2),\n )\n l7 = Line((0.0692, 0.7808), (0.0000, 0.9167))\n TangentArc(l6 @ 1, l7 @ 0, tangent=l6 % 1)\n mirror(outline.edges(), Plane.YZ)\n make_face()\n scale(by=height)\n maple_leaf_planar = maple_leaf_builder.sketch.faces()[0]\n center_field_planar = center_field_builder.sketch.faces()[0]\n \n west_field = west_field_planar.project_to_shape(the_wind, (0, 0, -1))[0]\n west_field.color = Color(\"red\")\n east_field = east_field_planar.project_to_shape(the_wind, (0, 0, -1))[0]\n east_field.color = Color(\"red\")\n center_field = center_field_planar.project_to_shape(the_wind, (0, 0, -1))[0]\n center_field.color = Color(\"white\")\n maple_leaf = maple_leaf_planar.project_to_shape(the_wind, (0, 0, -1))[0]\n maple_leaf.color = Color(\"red\")\n \n canadian_flag = Compound(children=[west_field, east_field, center_field, maple_leaf])\n show(Rot(90, 0, 0) * canadian_flag)\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n def surface(amplitude, u, v):\n \"\"\"Calculate the surface displacement of the flag at a given position\"\"\"\n return v * amplitude / 20 * cos(3.5 * pi * u) + amplitude / 10 * v * sin(\n 1.1 * pi * v\n )\n \n \n # Note that the surface to project on must be a little larger than the faces\n # being projected onto it to create valid projected faces\n the_wind = Face.make_surface_from_array_of_points(\n [\n [\n Vector(\n width * (v * 1.1 / 40 - 0.05),\n height * (u * 1.2 / 40 - 0.1),\n height * surface(wave_amplitude, u / 40, v / 40) / 2,\n )\n for u in range(41)\n ]\n for v in range(41)\n ]\n )\n \n field_planar = Plane.XY.offset(10) * Rectangle(width / 4, height, align=Align.MIN)\n west_field_planar = field_planar.faces()[0]\n east_field_planar = mirror(west_field_planar, Plane.YZ.offset(width / 2))\n \n l1 = Polyline((0.0000, 0.0771), (0.0187, 0.0771), (0.0094, 0.2569))\n l2 = Polyline((0.0325, 0.2773), (0.2115, 0.2458), (0.1873, 0.3125))\n r1 = RadiusArc(l1 @ 1, l2 @ 0, 0.0271)\n l3 = Polyline((0.1915, 0.3277), (0.3875, 0.4865), (0.3433, 0.5071))\n r2 = TangentArc(l2 @ 1, l3 @ 0, tangent=l2 % 1)\n l4 = Polyline((0.3362, 0.5235), (0.375, 0.6427), (0.2621, 0.6188))\n r3 = SagittaArc(l3 @ 1, l4 @ 0, 0.003)\n l5 = Polyline((0.2469, 0.6267), (0.225, 0.6781), (0.1369, 0.5835))\n r4 = ThreePointArc(l4 @ 1, (l4 @ 1 + l5 @ 0) * 0.5 + Vector(-0.002, -0.002), l5 @ 0)\n l6 = Polyline((0.1138, 0.5954), (0.1562, 0.8146), (0.0881, 0.7752))\n s = Spline(\n l5 @ 1,\n l6 @ 0,\n tangents=(l5 % 1, l6 % 0),\n tangent_scalars=(2, 2),\n )\n l7 = Line((0.0692, 0.7808), (0.0000, 0.9167))\n r5 = TangentArc(l6 @ 1, l7 @ 0, tangent=l6 % 1)\n \n outline = l1 + [l2, r1, l3, r2, l4, r3, l5, r4, l6, s, l7, r5]\n outline += mirror(outline, Plane.YZ)\n \n maple_leaf_planar = make_face(outline)\n \n center_field_planar = (\n Rectangle(1, 1, align=(Align.CENTER, Align.MIN)) - maple_leaf_planar\n )\n \n \n def scale_move(obj):\n return Plane((width / 2, 0, 10)) * scale(obj, height)\n \n \n def project(obj):\n return obj.faces()[0].project_to_shape(the_wind, (0, 0, -1))[0]\n \n \n maple_leaf_planar = scale_move(maple_leaf_planar)\n center_field_planar = scale_move(center_field_planar)\n \n west_field = project(west_field_planar)\n west_field.color = Color(\"red\")\n east_field = project(east_field_planar)\n east_field.color = Color(\"red\")\n center_field = project(center_field_planar)\n center_field.color = Color(\"white\")\n maple_leaf = project(maple_leaf_planar)\n maple_leaf.color = Color(\"red\")\n \n canadian_flag = Compound(children=[west_field, east_field, center_field, maple_leaf])\n show(Rot(90, 0, 0) * canadian_flag)\n\n\n.. _examples-circuit_board:","api_names":"BuildLine BuildSketch Color Compound cos edges face faces Implementation Line make_face make_surface_from_array_of_points mirror offset Plane Polyline project project_to_shape RadiusArc Rectangle Rot SagittaArc scale scale_move show sin Spline surface TangentArc ThreePointArc Vector","synonyms":"channel control points fit gap groove hollow interpolation path cut reflect shell smooth curve symmetry tolerance wall thickness"},"63":{"title":"Cast Bearing Unit","body":".. image:: assets/examples/cast_bearing_unit.png\n :align: center\n\nThis example demonstrates the creation of a castable flanged bearing housing\nusing the `draft` operation to add appropriate draft angles for mold release.\n\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import show\n \n A, A1, Db2, H, J = 26, 11, 57, 98.5, 76.5\n with BuildPart() as oval_flanged_bearing_unit:\n with BuildSketch() as plan:\n housing = Circle(Db2 / 2)\n with GridLocations(J, 0, 2, 1) as bolt_centers:\n Circle((H - J) / 2)\n make_hull()\n extrude(amount=A1)\n extrude(housing, amount=A)\n drafted_faces = oval_flanged_bearing_unit.faces().filter_by(Axis.Z, reverse=True)\n draft(drafted_faces, Plane.XY, 4)\n fillet(oval_flanged_bearing_unit.edges(), 1)\n with Locations(oval_flanged_bearing_unit.faces().sort_by(Axis.Z)[-1]):\n CounterBoreHole(14 / 2, 47 / 2, 14)\n with Locations(*bolt_centers):\n Hole(5)\n \n oval_flanged_bearing_unit.part.color = Color(0x4C6377)\n \n show(oval_flanged_bearing_unit)\n\n.. _examples-canadian_flag:","api_names":"BuildPart BuildSketch Circle Color CounterBoreHole draft edges extrude faces fillet filter_by GridLocations Hole Implementation Locations make_hull show sort_by","synonyms":"array bevel edge bore drill pattern recessed fastener repeat round edge"},"64":{"title":"Circuit Board With Holes","body":".. image:: assets/examples/example_circuit_board_01.png\n :align: center\n\n\n\nThis example demonstrates placing holes around a part.\n\n- Builder mode uses `Locations` context to place the positions.\n- Algebra mode uses `product` and `range` to calculate the positions.\n\n\n\n.. dropdown:: More Images\n\n .. image:: assets/examples/example_circuit_board_02.png\n :align: center\n\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n with BuildPart() as pcb:\n with BuildSketch():\n Rectangle(pcb_length, pcb_width)\n \n for i in range(65 // 5):\n x = i * 5 - 30\n with Locations((x, -15), (x, -10), (x, 10), (x, 15)):\n Circle(1, mode=Mode.SUBTRACT)\n for i in range(30 // 5 - 1):\n y = i * 5 - 10\n with Locations((30, y), (35, y)):\n Circle(1, mode=Mode.SUBTRACT)\n with GridLocations(60, 20, 2, 2):\n Circle(2, mode=Mode.SUBTRACT)\n extrude(amount=pcb_height)\n \n show_object(pcb.part.wrapped)\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n x_coords = product(range(65 // 5), (-15, -10, 10, 15))\n y_coords = product((30, 35), range(30 // 5 - 1))\n \n pcb = Rectangle(pcb_length, pcb_width)\n pcb -= [Pos(i * 5 - 30, y) * Circle(1) for i, y in x_coords]\n pcb -= [Pos(x, i * 5 - 10) * Circle(1) for x, i in y_coords]\n pcb -= [loc * Circle(2) for loc in GridLocations(60, 20, 2, 2)]\n \n pcb = extrude(pcb, pcb_height)\n \n show(pcb)\n\n\n.. _clock_face:","api_names":"BuildPart BuildSketch Circle extrude GridLocations Implementation Locations Pos product Rectangle show show_object","synonyms":"array bore channel drill groove path cut pattern recessed fastener repeat"},"65":{"title":"Clock Face","body":".. image:: assets/examples/clock_face.png\n :align: center\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n clock_radius = 10\n with BuildSketch() as minute_indicator:\n with BuildLine() as outline:\n l1 = CenterArc((0, 0), clock_radius * 0.975, 0.75, 4.5)\n l2 = CenterArc((0, 0), clock_radius * 0.925, 0.75, 4.5)\n Line(l1 @ 0, l2 @ 0)\n Line(l1 @ 1, l2 @ 1)\n make_face()\n fillet(minute_indicator.vertices(), radius=clock_radius * 0.01)\n \n with BuildSketch() as clock_face:\n Circle(clock_radius)\n with PolarLocations(0, 60):\n add(minute_indicator.sketch, mode=Mode.SUBTRACT)\n with PolarLocations(clock_radius * 0.875, 12):\n SlotOverall(clock_radius * 0.05, clock_radius * 0.025, mode=Mode.SUBTRACT)\n for hour in range(1, 13):\n with PolarLocations(clock_radius * 0.75, 1, -hour * 30 + 90, 360, rotate=False):\n Text(\n str(hour),\n font_size=clock_radius * 0.175,\n font_style=FontStyle.BOLD,\n mode=Mode.SUBTRACT,\n )\n \n show(clock_face)\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n clock_radius = 10\n \n l1 = CenterArc((0, 0), clock_radius * 0.975, 0.75, 4.5)\n l2 = CenterArc((0, 0), clock_radius * 0.925, 0.75, 4.5)\n l3 = Line(l1 @ 0, l2 @ 0)\n l4 = Line(l1 @ 1, l2 @ 1)\n minute_indicator = make_face([l1, l3, l2, l4])\n minute_indicator = fillet(minute_indicator.vertices(), radius=clock_radius * 0.01)\n \n clock_face = Circle(clock_radius)\n clock_face -= PolarLocations(0, 60) * minute_indicator\n clock_face -= PolarLocations(clock_radius * 0.875, 12) * SlotOverall(\n clock_radius * 0.05, clock_radius * 0.025\n )\n \n clock_face -= [\n loc\n * Text(\n str(hour + 1),\n font_size=clock_radius * 0.175,\n font_style=FontStyle.BOLD,\n align=Align.CENTER,\n )\n for hour, loc in enumerate(\n PolarLocations(clock_radius * 0.75, 12, 60, -360, rotate=False)\n )\n ]\n \n show(clock_face)\n\nThe Python code utilizes the build123d library to create a 3D model of a clock face.\nIt defines a minute indicator with arcs and lines, applying fillets, and then\nintegrates it into the clock face sketch. The clock face includes a circular outline,\nhour labels, and slots at specified positions. The resulting 3D model represents\na detailed and visually appealing clock design.\n\n:class:`~build_common.PolarLocations` are used to position features on the clock face.\n\n.. _fast_grid_holes:","api_names":"add BuildLine BuildSketch CenterArc Circle fillet Implementation Line make_face PolarLocations show SlotOverall Text vertices","synonyms":"array bevel edge bore channel drill groove path cut pattern recessed fastener repeat round edge"},"66":{"title":"Fast Grid Holes","body":".. image:: assets/examples/fast_grid_holes.png\n :align: center\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n import timeit\n from build123d import *\n from ocp_vscode import show\n \n start_time = timeit.default_timer()\n \n # Calculate the locations of 625 holes\n major_r = 10\n hole_locs = HexLocations(major_r, 25, 25)\n \n # Create wires for both the perimeter and all the holes\n face_perimeter = Rectangle(500, 600).wire()\n hex_hole = RegularPolygon(major_r - 1, 6, major_radius=True).wire()\n holes = hole_locs * hex_hole\n \n # Create a new Face from the perimeter and hole wires\n grid_pattern = Face(face_perimeter, holes)\n \n # Extrude to a 3D part\n grid = extrude(grid_pattern, 1)\n \n print(f\"Time: {timeit.default_timer() - start_time:0.3f}s\")\n show(grid)\n\nThis example demonstrates an efficient approach to creating a large number of holes\n(625 in this case) in a planar part using build123d.\n\nInstead of modeling and subtracting 3D solids for each hole-which is computationally\nexpensive-this method constructs a 2D Face from an outer perimeter wire and a list of\nhole wires. The entire face is then extruded in a single operation to form the final\n3D object. This approach significantly reduces modeling time and complexity.\n\nThe hexagonal hole pattern is generated using HexLocations, and each location is\npopulated with a hexagonal wire. These wires are passed directly to the Face constructor\nas holes. On a typical Linux laptop, this script completes in approximately 1.02 seconds,\ncompared to substantially longer runtimes for boolean subtraction of individual holes in 3D.\n\n\n.. _handle:","api_names":"default_timer extrude Face HexLocations holes Implementation Rectangle RegularPolygon show wire","synonyms":"array bore drill pattern recessed fastener repeat"},"67":{"title":"Former build123d Logo","body":".. image:: assets/examples/example_build123d_logo_01.png\n :align: center\n\n\nThis example creates the former build123d logo (new logo was created in the end of 2023).\n\nUsing text and lines to create the first build123d logo.\nThe builder mode example also generates the SVG file `logo.svg`.\n\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n with BuildSketch() as logo_text:\n Text(\"123d\", font_size=10, align=(Align.MIN, Align.MIN))\n font_height = logo_text.vertices().sort_by(Axis.Y)[-1].Y\n \n with BuildSketch() as build_text:\n Text(\"build\", font_size=5, align=(Align.CENTER, Align.CENTER))\n build_bb = bounding_box(build_text.sketch, mode=Mode.PRIVATE)\n build_vertices = build_bb.vertices().sort_by(Axis.X)\n build_width = build_vertices[-1].X - build_vertices[0].X\n \n with BuildLine() as one:\n l1 = Line((font_height * 0.3, 0), (font_height * 0.3, font_height))\n TangentArc(l1 @ 1, (0, font_height * 0.7), tangent=(l1 % 1) * -1)\n \n with BuildSketch() as two:\n with Locations((font_height * 0.35, 0)):\n Text(\"2\", font_size=10, align=(Align.MIN, Align.MIN))\n \n with BuildPart() as three_d:\n with BuildSketch(Plane((font_height * 1.1, 0))):\n Text(\"3d\", font_size=10, align=(Align.MIN, Align.MIN))\n extrude(amount=font_height * 0.3)\n logo_width = three_d.vertices().sort_by(Axis.X)[-1].X\n \n with BuildLine() as arrow_left:\n t1 = TangentArc((0, 0), (1, 0.75), tangent=(1, 0))\n mirror(t1, Plane.XZ)\n \n ext_line_length = font_height * 0.5\n dim_line_length = (logo_width - build_width - 2 * font_height * 0.05) / 2\n with BuildLine() as extension_lines:\n l1 = Line((0, -font_height * 0.1), (0, -ext_line_length - font_height * 0.1))\n l2 = Line(\n (logo_width, -font_height * 0.1),\n (logo_width, -ext_line_length - font_height * 0.1),\n )\n with Locations(l1 @ 0.5):\n add(arrow_left.line)\n with Locations(l2 @ 0.5):\n add(arrow_left.line, rotation=180.0)\n Line(l1 @ 0.5, l1 @ 0.5 + Vector(dim_line_length, 0))\n Line(l2 @ 0.5, l2 @ 0.5 - Vector(dim_line_length, 0))\n \n # Precisely center the build Faces\n with BuildSketch() as build:\n with Locations(\n (l1 @ 0.5 + l2 @ 0.5) / 2\n - Vector((build_vertices[-1].X + build_vertices[0].X) / 2, 0)\n ):\n add(build_text.sketch)\n \n \n if True:\n logo = Compound(\n children=[\n one.line,\n two.sketch,\n three_d.part,\n extension_lines.line,\n build.sketch,\n ]\n )\n \n # logo.export_step(\"logo.step\")\n def add_svg_shape(svg: ExportSVG, shape: Shape, color: tuple[float, float, float]):\n global counter\n try:\n counter += 1\n except:\n counter = 1\n \n visible, _hidden = shape.project_to_viewport(\n (-5, 1, 10), viewport_up=(0, 1, 0), look_at=(0, 0, 0)\n )\n if color is not None:\n svg.add_layer(str(counter), fill_color=color, line_weight=1)\n else:\n svg.add_layer(str(counter), line_weight=1)\n svg.add_shape(visible, layer=str(counter))\n \n svg = ExportSVG(scale=20)\n add_svg_shape(svg, logo, None)\n # add_svg_shape(svg, Compound(children=[one.line, extension_lines.line]), None)\n # add_svg_shape(svg, Compound(children=[two.sketch, build.sketch]), (170, 204, 255))\n # add_svg_shape(svg, three_d.part, (85, 153, 255))\n svg.write(\"logo.svg\")\n \n show_object(one, name=\"one\")\n show_object(two, name=\"two\")\n show_object(three_d, name=\"three_d\")\n show_object(extension_lines, name=\"extension_lines\")\n show_object(build, name=\"build\")\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n logo_text = Text(\"123d\", font_size=10, align=Align.MIN)\n font_height = logo_text.vertices().sort_by(Axis.Y).last.Y\n \n build_text = Text(\"build\", font_size=5, align=Align.CENTER)\n build_bb = build_text.bounding_box()\n build_width = build_bb.max.X - build_bb.min.X\n \n l1 = Line((font_height * 0.3, 0), (font_height * 0.3, font_height))\n one = l1 + TangentArc(l1 @ 1, (0, font_height * 0.7), tangent=(l1 % 1) * -1)\n \n two = Pos(font_height * 0.35, 0) * Text(\"2\", font_size=10, align=Align.MIN)\n \n three_d = Text(\"3d\", font_size=10, align=Align.MIN)\n three_d = Pos(font_height * 1.1, 0) * extrude(three_d, amount=font_height * 0.3)\n logo_width = three_d.vertices().sort_by(Axis.X).last.X\n \n t1 = TangentArc((0, 0), (1, 0.75), tangent=(1, 0))\n arrow_left = t1 + mirror(t1, Plane.XZ)\n \n ext_line_length = font_height * 0.5\n dim_line_length = (logo_width - build_width - 2 * font_height * 0.05) / 2\n \n l1 = Line((0, -font_height * 0.1), (0, -ext_line_length - font_height * 0.1))\n l2 = Line(\n (logo_width, -font_height * 0.1),\n (logo_width, -ext_line_length - font_height * 0.1),\n )\n extension_lines = Curve() + (l1 + l2)\n extension_lines += Pos(*(l1 @ 0.5)) * arrow_left\n extension_lines += (Pos(*(l2 @ 0.5)) * Rot(Z=180)) * arrow_left\n extension_lines += Line(l1 @ 0.5, l1 @ 0.5 + Vector(dim_line_length, 0))\n extension_lines += Line(l2 @ 0.5, l2 @ 0.5 - Vector(dim_line_length, 0))\n \n # Precisely center the build Faces\n p1 = Pos((l1 @ 0.5 + l2 @ 0.5) / 2 - Vector((build_bb.max.X + build_bb.min.X) / 2, 0))\n build = p1 * build_text\n \n cmpd = Compound([three_d, two, one, build, extension_lines])\n \n show_object(cmpd, name=\"compound\")\n \n\n\n.. _examples-cast_bearing_unit:","api_names":"add add_layer add_shape add_svg_shape bounding_box BuildLine BuildPart BuildSketch Compound Curve export_step ExportSVG extrude Implementation Line Locations logo mirror Plane Pos project_to_viewport Rot show_object sort_by TangentArc Text Vector vertices write","synonyms":"array pattern reflect repeat symmetry"},"68":{"title":"Handle","body":".. image:: assets/examples/handle.png\n :align: center\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show_object\n \n segment_count = 6\n \n with BuildPart() as handle:\n # Create a path for the sweep along the handle - added to pending_edges\n with BuildLine() as handle_center_line:\n Spline(\n (-10, 0, 0),\n (0, 0, 5),\n (10, 0, 0),\n tangents=((0, 0, 1), (0, 0, -1)),\n tangent_scalars=(1.5, 1.5),\n )\n \n # Create the cross sections - added to pending_faces\n for i in range(segment_count + 1):\n with BuildSketch(handle_center_line.line ^ (i / segment_count)) as section:\n if i % segment_count == 0:\n Circle(1)\n else:\n Rectangle(1.25, 3)\n fillet(section.vertices(), radius=0.2)\n # Record the sections for display\n sections = handle.pending_faces\n \n # Create the handle by sweeping along the path\n sweep(multisection=True)\n \n assert abs(handle.part.volume - 94.77361455046953) < 1e-3\n \n show_object(handle_center_line.line, name=\"handle_center_line\")\n for i, section in enumerate(sections):\n show_object(section, name=\"section\" + str(i))\n show_object(handle.part, name=\"handle\", options=dict(alpha=0.6))\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show_object\n \n segment_count = 6\n \n # Create a path for the sweep along the handle - added to pending_edges\n handle_center_line = Spline(\n (-10, 0, 0),\n (0, 0, 5),\n (10, 0, 0),\n tangents=((0, 0, 1), (0, 0, -1)),\n tangent_scalars=(1.5, 1.5),\n )\n \n # Create the cross sections - added to pending_faces\n sections = Sketch()\n for i in range(segment_count + 1):\n location = handle_center_line ^ (i / segment_count)\n if i % segment_count == 0:\n circle = location * Circle(1)\n else:\n circle = location * Rectangle(1.25, 3)\n circle = fillet(circle.vertices(), radius=0.2)\n sections += circle\n \n # Create the handle by sweeping along the path\n handle = sweep(sections, path=handle_center_line, multisection=True)\n \n show_object(handle_center_line, name=\"handle_path\")\n for i, circle in enumerate(sections):\n show_object(circle, name=\"section\" + str(i))\n show_object(handle, name=\"handle\", options=dict(alpha=0.6))\n\nThis example demonstrates multisection sweep creating a drawer handle.\n\n.. _heat_exchanger:","api_names":"abs BuildLine BuildPart BuildSketch Circle fillet Implementation Rectangle show_object Sketch Spline sweep vertices","synonyms":"bevel edge channel control points groove interpolation path cut round edge smooth curve"},"69":{"title":"Heat Exchanger","body":".. image:: assets/examples/heat_exchanger.png\n :align: center\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n exchanger_diameter = 10 * CM\n exchanger_length = 30 * CM\n plate_thickness = 5 * MM\n # 149 tubes\n tube_diameter = 5 * MM\n tube_spacing = 2 * MM\n tube_wall_thickness = 0.5 * MM\n tube_extension = 3 * MM\n bundle_diameter = exchanger_diameter - 2 * tube_diameter\n fillet_radius = tube_spacing / 3\n assert tube_extension > fillet_radius\n \n # Build the heat exchanger\n with BuildPart() as heat_exchanger:\n # Generate list of tube locations\n tube_locations = [\n l\n for l in HexLocations(\n radius=(tube_diameter + tube_spacing) / 2,\n x_count=exchanger_diameter // tube_diameter,\n y_count=exchanger_diameter // tube_diameter,\n )\n if l.position.length < bundle_diameter / 2\n ]\n tube_count = len(tube_locations)\n with BuildSketch() as tube_plan:\n with Locations(*tube_locations):\n Circle(radius=tube_diameter / 2)\n Circle(radius=tube_diameter / 2 - tube_wall_thickness, mode=Mode.SUBTRACT)\n extrude(amount=exchanger_length / 2)\n with BuildSketch(\n Plane(\n origin=(0, 0, exchanger_length / 2 - tube_extension - plate_thickness),\n z_dir=(0, 0, 1),\n )\n ) as plate_plan:\n Circle(radius=exchanger_diameter / 2)\n with Locations(*tube_locations):\n Circle(radius=tube_diameter / 2 - tube_wall_thickness, mode=Mode.SUBTRACT)\n extrude(amount=plate_thickness)\n half_volume_before_fillet = heat_exchanger.part.volume\n # Simulate welded tubes by adding a fillet to the outside radius of the tubes\n fillet(\n heat_exchanger.edges()\n .filter_by(GeomType.CIRCLE)\n .sort_by(SortBy.RADIUS)\n .sort_by(Axis.Z, reverse=True)[2 * tube_count : 3 * tube_count],\n radius=fillet_radius,\n )\n half_volume_after_fillet = heat_exchanger.part.volume\n mirror(about=Plane.XY)\n \n fillet_volume = 2 * (half_volume_after_fillet - half_volume_before_fillet)\n assert abs(fillet_volume - 469.88331045553787) < 1e-3\n \n show(heat_exchanger)\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n exchanger_diameter = 10 * CM\n exchanger_length = 30 * CM\n plate_thickness = 5 * MM\n # 149 tubes\n tube_diameter = 5 * MM\n tube_spacing = 2 * MM\n tube_wall_thickness = 0.5 * MM\n tube_extension = 3 * MM\n bundle_diameter = exchanger_diameter - 2 * tube_diameter\n fillet_radius = tube_spacing / 3\n assert tube_extension > fillet_radius\n \n # Build the heat exchanger\n tube_locations = [\n l\n for l in HexLocations(\n radius=(tube_diameter + tube_spacing) / 2,\n x_count=exchanger_diameter // tube_diameter,\n y_count=exchanger_diameter // tube_diameter,\n )\n if l.position.length < bundle_diameter / 2\n ]\n \n ring = Circle(tube_diameter / 2) - Circle(tube_diameter / 2 - tube_wall_thickness)\n tube_plan = Sketch() + tube_locations * ring\n \n heat_exchanger = extrude(tube_plan, exchanger_length / 2)\n \n plate_plane = Plane(\n origin=(0, 0, exchanger_length / 2 - tube_extension - plate_thickness),\n z_dir=(0, 0, 1),\n )\n plate = Circle(radius=exchanger_diameter / 2) - tube_locations * Circle(\n radius=tube_diameter / 2 - tube_wall_thickness\n )\n \n heat_exchanger += extrude(plate_plane * plate, plate_thickness)\n edges = (\n heat_exchanger.edges()\n .filter_by(GeomType.CIRCLE)\n .group_by(SortBy.RADIUS)[1]\n .group_by()[2]\n )\n half_volume_before_fillet = heat_exchanger.volume\n heat_exchanger = fillet(edges, radius=fillet_radius)\n half_volume_after_fillet = heat_exchanger.volume\n heat_exchanger += mirror(heat_exchanger, Plane.XY)\n \n fillet_volume = 2 * (half_volume_after_fillet - half_volume_before_fillet)\n assert abs(fillet_volume - 469.88331045553787) < 1e-3\n \n show(heat_exchanger)\n\nThis example creates a model of a parametric heat exchanger core. The positions\nof the tubes are defined with :class:`~build_common.HexLocations` and further\nlimited to fit within the circular end caps. The ends of the tubes are filleted\nto the end plates to simulate welding.\n\n.. _key_cap:","api_names":"abs BuildPart BuildSketch Circle edges extrude fillet filter_by group_by HexLocations Implementation Locations mirror Plane show Sketch sort_by","synonyms":"array bevel edge channel groove path cut pattern reflect repeat round edge symmetry"},"70":{"title":"Key Cap","body":".. image:: assets/examples/key_cap.png\n :align: center\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import *\n \n with BuildPart() as key_cap:\n # Start with the plan of the key cap and extrude it\n with BuildSketch() as plan:\n Rectangle(18 * MM, 18 * MM)\n extrude(amount=10 * MM, taper=15)\n # Create a dished top\n with Locations((0, -3 * MM, 47 * MM)):\n Sphere(40 * MM, mode=Mode.SUBTRACT, rotation=(90, 0, 0))\n # Fillet all the edges except the bottom\n fillet(\n key_cap.edges().filter_by_position(Axis.Z, 0, 30 * MM, inclusive=(False, True)),\n radius=1 * MM,\n )\n # Hollow out the key by subtracting a scaled version\n scale(by=(0.925, 0.925, 0.85), mode=Mode.SUBTRACT)\n \n # Add supporting ribs while leaving room for switch activation\n with BuildSketch(Plane(origin=(0, 0, 4 * MM))):\n Rectangle(15 * MM, 0.5 * MM)\n Rectangle(0.5 * MM, 15 * MM)\n Circle(radius=5.5 * MM / 2)\n # Extrude the mount and ribs to the key cap underside\n extrude(until=Until.NEXT)\n # Find the face on the bottom of the ribs to build onto\n rib_bottom = key_cap.faces().filter_by_position(Axis.Z, 4 * MM, 4 * MM)[0]\n # Add the switch socket\n with BuildSketch(rib_bottom) as cruciform:\n Circle(radius=5.5 * MM / 2)\n Rectangle(4.1 * MM, 1.17 * MM, mode=Mode.SUBTRACT)\n Rectangle(1.17 * MM, 4.1 * MM, mode=Mode.SUBTRACT)\n extrude(amount=3.5 * MM, mode=Mode.ADD)\n \n assert abs(key_cap.part.volume - 644.8900473617498) < 1e-3\n \n show(key_cap, alphas=[0.3])\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import *\n \n # Taper Extrude and Extrude to \"next\" while creating a Cherry MX key cap\n # See: https://www.cherrymx.de/en/dev.html\n \n plan = Rectangle(18 * MM, 18 * MM)\n key_cap = extrude(plan, amount=10 * MM, taper=15)\n \n # Create a dished top\n key_cap -= Location((0, -3 * MM, 47 * MM), (90, 0, 0)) * Sphere(40 * MM)\n \n # Fillet all the edges except the bottom\n key_cap = fillet(\n key_cap.edges().filter_by_position(Axis.Z, 0, 30 * MM, inclusive=(False, True)),\n radius=1 * MM,\n )\n \n # Hollow out the key by subtracting a scaled version\n key_cap -= scale(key_cap, (0.925, 0.925, 0.85))\n \n \n # Add supporting ribs while leaving room for switch activation\n ribs = Rectangle(17.5 * MM, 0.5 * MM)\n ribs += Rectangle(0.5 * MM, 17.5 * MM)\n ribs += Circle(radius=5.51 * MM / 2)\n \n # Extrude the mount and ribs to the key cap underside\n key_cap += extrude(Pos(0, 0, 4 * MM) * ribs, until=Until.NEXT, target=key_cap)\n \n \n # Find the face on the bottom of the ribs to build onto\n rib_bottom = key_cap.faces().filter_by_position(Axis.Z, 4 * MM, 4 * MM)[0]\n \n # Add the switch socket\n socket = Circle(radius=5.5 * MM / 2)\n socket -= Rectangle(4.1 * MM, 1.17 * MM)\n socket -= Rectangle(1.17 * MM, 4.1 * MM)\n key_cap += extrude(Plane(rib_bottom) * socket, amount=3.5 * MM)\n \n show(key_cap, alphas=[0.3])\n\nThis example demonstrates the design of a Cherry MX key cap by using\nextrude with a taper and extrude until next.\n\n.. _maker_coin:","api_names":"abs BuildPart BuildSketch Circle edges extrude faces fillet filter_by_position Implementation Location Locations Plane Pos Rectangle scale show Sphere","synonyms":"array bevel edge channel groove path cut pattern repeat round edge"},"71":{"title":"Maker Coin","body":".. image:: assets/examples/maker_coin.png\n :align: center\n\nThis example creates the maker coin as defined by Angus on the Maker's Muse\nYouTube channel. There are two key features:\n\n#. the use of :class:`~objects_curve.DoubleTangentArc` to create a smooth\n transition from the central dish to the outside arc, and\n\n#. embossing the text into the top of the coin not just as a simple\n extrude but from a projection which results in text with even depth.\n\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n # Coin Parameters\n diameter, thickness = 50 * MM, 10 * MM\n \n with BuildPart() as maker_coin:\n # On XZ plane draw the profile of half the coin\n with BuildSketch(Plane.XZ) as profile:\n with BuildLine() as outline:\n l1 = Polyline((0, thickness * 0.6), (0, 0), ((diameter - thickness) / 2, 0))\n l2 = JernArc(\n start=l1 @ 1, tangent=l1 % 1, radius=thickness / 2, arc_size=300\n ) # extend the arc beyond the intersection but not closed\n l3 = DoubleTangentArc(l1 @ 0, tangent=(1, 0), other=l2)\n make_face() # make it a 2D shape\n revolve() # revolve 360°\n \n # Pattern the detents around the coin\n with BuildSketch() as detents:\n with PolarLocations(radius=(diameter + 5) / 2, count=8):\n Circle(thickness * 1.4 / 2)\n extrude(amount=thickness, mode=Mode.SUBTRACT) # cut away the detents\n \n fillet(maker_coin.edges(Select.NEW), 2) # fillet the cut edges\n \n # Add an embossed label\n with BuildSketch(Plane.XY.offset(thickness)) as label: # above coin\n Text(\"OS\", font_size=15)\n project() # label on top of coin\n extrude(amount=-thickness / 5, mode=Mode.SUBTRACT) # emboss label\n \n show(maker_coin)\n\n\n.. _multi_sketch_loft:","api_names":"BuildLine BuildPart BuildSketch Circle DoubleTangentArc edges extrude fillet Implementation JernArc make_face offset PolarLocations Polyline project revolve show Text","synonyms":"array axisymmetric bevel edge blend profiles channel cross sections fit gap groove hollow lathe path cut pattern repeat round edge shell tolerance transition turned wall thickness"},"72":{"title":"Multi-Sketch Loft","body":".. image:: assets/examples/loft.png\n :align: center\n\nThis example demonstrates lofting a set of sketches, selecting\nthe top and bottom by type, and shelling.\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n \n from math import pi, sin\n from build123d import *\n from ocp_vscode import show\n \n with BuildPart() as art:\n slice_count = 10\n for i in range(slice_count + 1):\n with BuildSketch(Plane(origin=(0, 0, i * 3), z_dir=(0, 0, 1))) as slice:\n Circle(10 * sin(i * pi / slice_count) + 5)\n loft()\n top_bottom = art.faces().filter_by(GeomType.PLANE)\n offset(openings=top_bottom, amount=0.5)\n \n want = 1306.3405290344635\n got = art.part.volume\n delta = abs(got - want)\n tolerance = want * 1e-5\n assert delta < tolerance, f\"{delta=} is greater than {tolerance=}; {got=}, {want=}\"\n \n show(art, names=[\"art\"])\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n \n from math import pi, sin\n from build123d import *\n from ocp_vscode import show\n \n slice_count = 10\n \n art = Sketch()\n for i in range(slice_count + 1):\n plane = Plane(origin=(0, 0, i * 3), z_dir=(0, 0, 1))\n art += plane * Circle(10 * sin(i * pi / slice_count) + 5)\n \n art = loft(art)\n top_bottom = art.faces().filter_by(GeomType.PLANE)\n art = offset(art, openings=top_bottom, amount=0.5)\n \n show(art, names=[\"art\"])\n\n\n.. _peg_board_hook:","api_names":"abs BuildPart BuildSketch Circle faces filter_by Implementation loft offset Plane show sin Sketch","synonyms":"blend profiles cross sections fit gap hollow shell tolerance transition wall thickness"},"73":{"title":"Overview","body":"In the GitHub repository you will find an `examples folder `_.\n\nMost of the examples show the builder and algebra modes.\n\n.. ----------------------------------------------------------------------------------------------\n.. Index Section\n.. ----------------------------------------------------------------------------------------------\n\n\n.. grid:: 3\n\n .. grid-item-card:: Benchy |Builder|\n :img-top: assets/examples/thumbnail_benchy_01.png\n :link: examples-benchy\n :link-type: ref\n\n .. grid-item-card:: Bicycle Tire |Builder|\n :img-top: assets/examples/bicycle_tire.png\n :link: examples-bicycle_tire\n :link-type: ref\n\n .. grid-item-card:: Bracelet |Algebra|\n :img-top: assets/examples/bracelet.png\n :link: examples-bracelet\n :link-type: ref\n\n .. grid-item-card:: Canadian Flag Blowing in The Wind |Builder| |Algebra|\n :img-top: assets/examples/example_canadian_flag_01.png\n :link: examples-canadian_flag\n :link-type: ref\n\n .. grid-item-card:: Cast Bearing Unit |Builder|\n :img-top: assets/examples/cast_bearing_unit.png\n :link: examples-cast_bearing_unit\n :link-type: ref\n\n .. grid-item-card:: Circuit Board With Holes |Builder| |Algebra|\n :img-top: assets/examples/thumbnail_circuit_board_01.png\n :link: examples-circuit_board\n :link-type: ref\n\n .. grid-item-card:: Clock Face |Builder| |Algebra|\n :img-top: assets/examples/clock_face.png\n :link: clock_face\n :link-type: ref\n\n .. grid-item-card:: Fast Grid Holes |Algebra|\n :img-top: assets/examples/fast_grid_holes.png\n :link: fast_grid_holes\n :link-type: ref\n\n .. grid-item-card:: Handle |Builder| |Algebra|\n :img-top: assets/examples/handle.png\n :link: handle\n :link-type: ref\n\n .. grid-item-card:: Heat Exchanger |Builder| |Algebra|\n :img-top: assets/examples/heat_exchanger.png\n :link: heat_exchanger\n :link-type: ref\n\n .. grid-item-card:: Key Cap |Builder| |Algebra|\n :img-top: assets/examples/key_cap.png\n :link: key_cap\n :link-type: ref\n\n .. grid-item-card:: (former) build123d Logo |Builder| |Algebra|\n :img-top: assets/examples/thumbnail_build123d_logo_01.png\n :link: examples-build123d_logo\n :link-type: ref\n\n .. grid-item-card:: Maker Coin |Builder|\n :img-top: assets/examples/maker_coin.png\n :link: maker_coin\n :link-type: ref\n\n .. grid-item-card:: Multi-Sketch Loft |Builder| |Algebra|\n :img-top: assets/examples/loft.png\n :link: multi_sketch_loft\n :link-type: ref\n\n .. grid-item-card:: Peg Board J Hook |Builder| |Algebra|\n :img-top: assets/examples/peg_board_hook.png\n :link: peg_board_hook\n :link-type: ref\n\n .. grid-item-card:: Platonic Solids |Algebra|\n :img-top: assets/examples/platonic_solids.png\n :link: platonic_solids\n :link-type: ref\n\n .. grid-item-card:: Playing Cards |Builder|\n :img-top: assets/examples/playing_cards.png\n :link: playing_cards\n :link-type: ref\n\n .. grid-item-card:: Stud Wall |Algebra|\n :img-top: assets/examples/stud_wall.png\n :link: stud_wall\n :link-type: ref\n\n .. grid-item-card:: Tea Cup |Builder| |Algebra|\n :img-top: assets/examples/tea_cup.png\n :link: tea_cup\n :link-type: ref\n\n .. grid-item-card:: Toy Truck |Builder|\n :img-top: assets/examples/toy_truck.png\n :link: toy_truck\n :link-type: ref\n\n .. grid-item-card:: Vase |Builder| |Algebra|\n :img-top: assets/examples/vase.png\n :link: vase\n :link-type: ref\n\n.. NOTE 01: insert new example thumbnails above this line\n\n.. TODO: Copy this block to add the example thumbnails here\n .. grid-item-card:: name-of-your-example-with-spaces |Builder| |Algebra|\n :img-top: assets/examples/thumbnail_{name-of-your-example}_01.{extension}\n :link: examples-{name-of-your-example}\n :link-type: ref\n\n.. ----------------------------------------------------------------------------------------------\n.. Details Section\n.. ----------------------------------------------------------------------------------------------\n\n.. _examples-benchy:","api_names":"","synonyms":"blend profiles bore cross sections drill recessed fastener transition"},"74":{"title":"Peg Board Hook","body":".. image:: assets/examples/peg_board_hook.png\n :align: center\n\nThis script creates a a J-shaped pegboard hook. These hooks are commonly used for\norganizing tools in garages, workshops, or other spaces where tools and equipment\nneed to be stored neatly and accessibly. The hook is created by defining a complex\npath and then sweeping it to define the hook. The sides of the hook are flattened\nto aid 3D printing.\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n pegd = 6.35 + 0.1 # mm ~0.25inch\n c2c = 25.4 # mm 1.0inch\n arcd = 7.2\n both = 10\n topx = 6\n midx = 8\n maind = 0.82 * pegd\n midd = 1.0 * pegd\n hookd = 23\n hookx = 10\n splitz = maind / 2 - 0.1\n topangs = 70\n \n with BuildPart() as mainp:\n with BuildLine(mode=Mode.PRIVATE) as sprof:\n l1 = Line((-both, 0), (c2c - arcd / 2 - 0.5, 0))\n l2 = JernArc(start=l1 @ 1, tangent=l1 % 1, radius=arcd / 2, arc_size=topangs)\n l3 = PolarLine(\n start=l2 @ 1,\n length=topx,\n direction=l2 % 1,\n )\n l4 = JernArc(start=l3 @ 1, tangent=l3 % 1, radius=arcd / 2, arc_size=-topangs)\n l5 = PolarLine(\n start=l4 @ 1,\n length=topx,\n direction=l4 % 1,\n )\n l6 = JernArc(\n start=l1 @ 0, tangent=(l1 % 0).reverse(), radius=hookd / 2, arc_size=170\n )\n l7 = PolarLine(\n start=l6 @ 1,\n length=hookx,\n direction=l6 % 1,\n )\n with BuildSketch(Plane.YZ):\n Circle(radius=maind / 2)\n sweep(path=sprof.wires()[0])\n with BuildLine(mode=Mode.PRIVATE) as stub:\n l7 = Line((0, 0), (0, midx + maind / 2))\n with BuildSketch(Plane.XZ):\n Circle(radius=midd / 2)\n sweep(path=stub.wires()[0])\n # splits help keep the object 3d printable by reducing overhang\n split(bisect_by=Plane(origin=(0, 0, -splitz)))\n split(bisect_by=Plane(origin=(0, 0, splitz)), keep=Keep.BOTTOM)\n \n show(mainp)\n\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n pegd = 6.35 + 0.1 # mm ~0.25inch\n c2c = 25.4 # mm 1.0inch\n arcd = 7.2\n both = 10\n topx = 6\n midx = 8\n maind = 0.82 * pegd\n midd = 1.0 * pegd\n hookd = 23\n hookx = 10\n splitz = maind / 2 - 0.1\n topangs = 70\n \n l1 = Line((-both, 0), (c2c - arcd / 2 - 0.5, 0))\n l2 = JernArc(start=l1 @ 1, tangent=l1 % 1, radius=arcd / 2, arc_size=topangs)\n l3 = PolarLine(\n start=l2 @ 1,\n length=topx,\n direction=l2 % 1,\n )\n l4 = JernArc(start=l3 @ 1, tangent=l3 % 1, radius=arcd / 2, arc_size=-topangs)\n l5 = PolarLine(\n start=l4 @ 1,\n length=topx,\n direction=l4 % 1,\n )\n l6 = JernArc(start=l1 @ 0, tangent=(l1 % 0).reverse(), radius=hookd / 2, arc_size=170)\n l7 = PolarLine(\n start=l6 @ 1,\n length=hookx,\n direction=l6 % 1,\n )\n sprof = Curve() + (l1, l2, l3, l4, l5, l6, l7)\n wire = Wire(sprof.edges()) # TODO sprof.wires() fails\n mainp = sweep(Plane.YZ * Circle(radius=maind / 2), path=wire)\n \n stub = Line((0, 0), (0, midx + maind / 2))\n mainp += sweep(Plane.XZ * Circle(radius=midd / 2), path=stub)\n \n \n # splits help keep the object 3d printable by reducing overhang\n mainp = split(mainp, Plane(origin=(0, 0, -splitz)))\n mainp = split(mainp, Plane(origin=(0, 0, splitz)), keep=Keep.BOTTOM)\n \n show(mainp)\n\n\n.. _platonic_solids:","api_names":"BuildLine BuildPart BuildSketch Circle Curve edges Implementation JernArc Line Plane PolarLine reverse show split sweep Wire wires","synonyms":"channel cut in half groove path cut slice trim"},"75":{"title":"Platonic Solids","body":".. image:: assets/examples/platonic_solids.png\n :align: center\n\nThis example creates a custom Part object PlatonicSolid.\n\nPlatonic solids are five three-dimensional shapes that are highly symmetrical,\nknown since antiquity and named after the ancient Greek philosopher Plato.\nThese solids are unique because their faces are congruent regular polygons,\nwith the same number of faces meeting at each vertex. The five Platonic solids\nare the tetrahedron (4 triangular faces), cube (6 square faces), octahedron\n(8 triangular faces), dodecahedron (12 pentagonal faces), and icosahedron\n(20 triangular faces). Each solid represents a unique way in which identical\npolygons can be arranged in three dimensions to form a convex polyhedron,\nembodying ideals of symmetry and balance.\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n from build123d import *\n from math import sqrt\n from typing import Union, Literal\n from scipy.spatial import ConvexHull\n \n from ocp_vscode import show\n \n PHI = (1 + sqrt(5)) / 2 # The Golden Ratio\n \n \n class PlatonicSolid(BasePartObject):\n \"\"\"Part Object: Platonic Solid\n \n Create one of the five convex Platonic solids.\n \n Args:\n face_count (Literal[4,6,8,12,20]): number of faces\n diameter (float): double distance to vertices, i.e. maximum size\n rotation (RotationLike, optional): angles to rotate about axes. Defaults to (0, 0, 0).\n align (Union[None, Align, tuple[Align, Align, Align]], optional): align min, center,\n or max of object. Defaults to None.\n mode (Mode, optional): combine mode. Defaults to Mode.ADD.\n \"\"\"\n \n tetrahedron_vertices = [(1, 1, 1), (1, -1, -1), (-1, 1, -1), (-1, -1, 1)]\n \n cube_vertices = [(i, j, k) for i in [-1, 1] for j in [-1, 1] for k in [-1, 1]]\n \n octahedron_vertices = (\n [(i, 0, 0) for i in [-1, 1]]\n + [(0, i, 0) for i in [-1, 1]]\n + [(0, 0, i) for i in [-1, 1]]\n )\n \n dodecahedron_vertices = (\n [(i, j, k) for i in [-1, 1] for j in [-1, 1] for k in [-1, 1]]\n + [(0, i / PHI, j * PHI) for i in [-1, 1] for j in [-1, 1]]\n + [(i / PHI, j * PHI, 0) for i in [-1, 1] for j in [-1, 1]]\n + [(i * PHI, 0, j / PHI) for i in [-1, 1] for j in [-1, 1]]\n )\n \n icosahedron_vertices = (\n [(0, i, j * PHI) for i in [-1, 1] for j in [-1, 1]]\n + [(i, j * PHI, 0) for i in [-1, 1] for j in [-1, 1]]\n + [(i * PHI, 0, j) for i in [-1, 1] for j in [-1, 1]]\n )\n \n vertices_lookup = {\n 4: tetrahedron_vertices,\n 6: cube_vertices,\n 8: octahedron_vertices,\n 12: dodecahedron_vertices,\n 20: icosahedron_vertices,\n }\n _applies_to = [BuildPart._tag]\n \n def __init__(\n self,\n face_count: Literal[4, 6, 8, 12, 20],\n diameter: float = 1.0,\n rotation: RotationLike = (0, 0, 0),\n align: Union[None, Align, tuple[Align, Align, Align]] = None,\n mode: Mode = Mode.ADD,\n ):\n try:\n platonic_vertices = PlatonicSolid.vertices_lookup[face_count]\n except KeyError:\n raise ValueError(\n f\"face_count must be one of 4, 6, 8, 12, or 20 not {face_count}\"\n )\n \n # Create a convex hull from the vertices\n hull = ConvexHull(platonic_vertices).simplices.tolist()\n \n # Create faces from the vertex indices\n platonic_faces = []\n for face_vertex_indices in hull:\n corner_vertices = [platonic_vertices[i] for i in face_vertex_indices]\n platonic_faces.append(Face(Wire.make_polygon(corner_vertices)))\n \n # Create the solid from the Faces\n platonic_solid = Solid(Shell(platonic_faces)).clean()\n \n # By definition, all vertices are the same distance from the origin so\n # scale proportionally to this distance\n platonic_solid = platonic_solid.scale(\n (diameter / 2) / Vector(platonic_solid.vertices()[0]).length\n )\n \n super().__init__(part=platonic_solid, rotation=rotation, align=align, mode=mode)\n \n \n solids = [\n Rot(0, 0, 72 * i) * Pos(1, 0, 0) * PlatonicSolid(faces)\n for i, faces in enumerate([4, 6, 8, 12, 20])\n ]\n show(solids)\n \n\n.. _playing_cards:","api_names":"__init__ align append clean ConvexHull cube diameter dodecahedron Face face_count icosahedron Implementation make_polygon mode octahedron PlatonicSolid Pos Rot rotation scale Shell show Solid sqrt super tetrahedron to tolist ValueError Vector vertices","synonyms":""},"76":{"title":"Playing Cards","body":".. image:: assets/examples/playing_cards.png\n :align: center\n\nThis example creates a customs Sketch objects: Club, Spade, Heart, Diamond,\nand PlayingCard in addition to a two part playing card box which has suit\ncutouts in the lid. The four suits are created with Bézier curves that were\nimported as code from an SVG file and modified to the code found here.\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n \n from typing import Literal\n from build123d import *\n from ocp_vscode import show_object\n \n \n # [Club]\n class Club(BaseSketchObject):\n def __init__(\n self,\n height: float,\n rotation: float = 0,\n align: tuple[Align, Align] = (Align.CENTER, Align.CENTER),\n mode: Mode = Mode.ADD,\n ):\n with BuildSketch() as club:\n with BuildLine():\n l0 = Line((0, -188), (76, -188))\n b0 = Bezier(l0 @ 1, (61, -185), (33, -173), (17, -81))\n b1 = Bezier(b0 @ 1, (49, -128), (146, -145), (167, -67))\n b2 = Bezier(b1 @ 1, (187, 9), (94, 52), (32, 18))\n b3 = Bezier(b2 @ 1, (92, 57), (113, 188), (0, 188))\n mirror(about=Plane.YZ)\n make_face()\n scale(by=height / club.sketch.bounding_box().size.Y)\n super().__init__(obj=club.sketch, rotation=rotation, align=align, mode=mode)\n \n \n # [Club]\n \n \n class Spade(BaseSketchObject):\n def __init__(\n self,\n height: float,\n rotation: float = 0,\n align: tuple[Align, Align] = (Align.CENTER, Align.CENTER),\n mode: Mode = Mode.ADD,\n ):\n with BuildSketch() as spade:\n with BuildLine():\n b0 = Bezier((0, 198), (6, 190), (41, 127), (112, 61))\n b1 = Bezier(b0 @ 1, (242, -72), (114, -168), (11, -105))\n b2 = Bezier(b1 @ 1, (31, -174), (42, -179), (53, -198))\n l0 = Line(b2 @ 1, (0, -198))\n mirror(about=Plane.YZ)\n make_face()\n scale(by=height / spade.sketch.bounding_box().size.Y)\n super().__init__(obj=spade.sketch, rotation=rotation, align=align, mode=mode)\n \n \n class Heart(BaseSketchObject):\n def __init__(\n self,\n height: float,\n rotation: float = 0,\n align: tuple[Align, Align] = (Align.CENTER, Align.CENTER),\n mode: Mode = Mode.ADD,\n ):\n with BuildSketch() as heart:\n with BuildLine():\n b1 = Bezier((0, 146), (20, 169), (67, 198), (97, 198))\n b2 = Bezier(b1 @ 1, (125, 198), (151, 186), (168, 167))\n b3 = Bezier(b2 @ 1, (197, 133), (194, 88), (158, 31))\n b4 = Bezier(b3 @ 1, (126, -13), (94, -48), (62, -95))\n b5 = Bezier(b4 @ 1, (40, -128), (0, -198))\n mirror(about=Plane.YZ)\n make_face()\n scale(by=height / heart.sketch.bounding_box().size.Y)\n super().__init__(obj=heart.sketch, rotation=rotation, align=align, mode=mode)\n \n \n class Diamond(BaseSketchObject):\n def __init__(\n self,\n height: float,\n rotation: float = 0,\n align: tuple[Align, Align] = (Align.CENTER, Align.CENTER),\n mode: Mode = Mode.ADD,\n ):\n with BuildSketch() as diamond:\n with BuildLine():\n Bezier((135, 0), (94, 69), (47, 134), (0, 198))\n mirror(about=Plane.XZ)\n mirror(about=Plane.YZ)\n make_face()\n scale(by=height / diamond.sketch.bounding_box().size.Y)\n super().__init__(obj=diamond.sketch, rotation=rotation, align=align, mode=mode)\n \n \n card_width = 2.5 * IN\n card_length = 3.5 * IN\n deck = 0.5 * IN\n wall = 4 * MM\n gap = 0.5 * MM\n \n with BuildPart() as box_builder:\n with BuildSketch() as plan:\n Rectangle(card_width + 2 * wall, card_length + 2 * wall)\n fillet(plan.vertices(), radius=card_width / 15)\n extrude(amount=wall / 2)\n with BuildSketch(box_builder.faces().sort_by(Axis.Z)[-1]) as walls:\n add(plan.sketch)\n offset(plan.sketch, amount=-wall, mode=Mode.SUBTRACT)\n extrude(amount=deck / 2)\n with BuildSketch(box_builder.faces().sort_by(Axis.Z)[-1]) as inset_walls:\n offset(plan.sketch, amount=-(wall + gap) / 2, mode=Mode.ADD)\n offset(plan.sketch, amount=-wall, mode=Mode.SUBTRACT)\n extrude(amount=deck / 2)\n \n with BuildPart() as lid_builder:\n with BuildSketch() as outset_walls:\n add(plan.sketch)\n offset(plan.sketch, amount=-(wall - gap) / 2, mode=Mode.SUBTRACT)\n extrude(amount=deck / 2)\n with BuildSketch(lid_builder.faces().sort_by(Axis.Z)[-1]) as top:\n add(plan.sketch)\n extrude(amount=wall / 2)\n with BuildSketch(lid_builder.faces().sort_by(Axis.Z)[-1]):\n holes = GridLocations(\n 3 * card_width / 5, 3 * card_length / 5, 2, 2\n ).local_locations\n for i, hole in enumerate(holes):\n with Locations(hole) as hole_loc:\n if i == 0:\n Heart(card_length / 5)\n elif i == 1:\n Diamond(card_length / 5)\n elif i == 2:\n Spade(card_length / 5)\n elif i == 3:\n Club(card_length / 5)\n extrude(amount=-wall, mode=Mode.SUBTRACT)\n \n box = Compound(\n [box_builder.part, lid_builder.part.moved(Location((0, 0, (wall + deck) / 2)))]\n )\n visible, hidden = box.project_to_viewport((70, -50, 120))\n max_dimension = max(*Compound(children=visible + hidden).bounding_box().size)\n exporter = ExportSVG(scale=100 / max_dimension)\n exporter.add_layer(\"Visible\")\n exporter.add_layer(\"Hidden\", line_color=(99, 99, 99), line_type=LineType.ISO_DOT)\n exporter.add_shape(visible, layer=\"Visible\")\n exporter.add_shape(hidden, layer=\"Hidden\")\n # exporter.write(f\"assets/card_box.svg\")\n \n \n class PlayingCard(BaseSketchObject):\n \"\"\"PlayingCard\n \n A standard playing card modelled as a Face.\n \n Args:\n rank (Literal['A', '2' .. '10', 'J', 'Q', 'K']): card rank\n suit (Literal['Clubs', 'Spades', 'Hearts', 'Diamonds']): card suit\n \"\"\"\n \n width = 2.5 * IN\n height = 3.5 * IN\n suits = {\"Clubs\": Club, \"Spades\": Spade, \"Hearts\": Heart, \"Diamonds\": Diamond}\n ranks = [\"A\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"J\", \"Q\", \"K\"]\n \n def __init__(\n self,\n rank: Literal[\"A\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"J\", \"Q\", \"K\"],\n suit: Literal[\"Clubs\", \"Spades\", \"Hearts\", \"Diamonds\"],\n rotation: float = 0,\n align: tuple[Align, Align] = (Align.CENTER, Align.CENTER),\n mode: Mode = Mode.ADD,\n ):\n with BuildSketch() as playing_card:\n Rectangle(\n PlayingCard.width, PlayingCard.height, align=(Align.MIN, Align.MIN)\n )\n fillet(playing_card.vertices(), radius=PlayingCard.width / 15)\n with Locations(\n (\n PlayingCard.width / 7,\n 8 * PlayingCard.height / 9,\n )\n ):\n Text(\n txt=rank,\n font_size=PlayingCard.width / 7,\n mode=Mode.SUBTRACT,\n )\n with Locations(\n (\n PlayingCard.width / 7,\n 7 * PlayingCard.height / 9,\n )\n ):\n PlayingCard.suits[suit](\n height=PlayingCard.width / 12, mode=Mode.SUBTRACT\n )\n with Locations(\n (\n 6 * PlayingCard.width / 7,\n 1 * PlayingCard.height / 9,\n )\n ):\n Text(\n txt=rank,\n font_size=PlayingCard.width / 7,\n rotation=180,\n mode=Mode.SUBTRACT,\n )\n with Locations(\n (\n 6 * PlayingCard.width / 7,\n 2 * PlayingCard.height / 9,\n )\n ):\n PlayingCard.suits[suit](\n height=PlayingCard.width / 12, rotation=180, mode=Mode.SUBTRACT\n )\n rank_int = PlayingCard.ranks.index(rank) + 1\n rank_int = rank_int if rank_int < 10 else 1\n with Locations((PlayingCard.width / 2, PlayingCard.height / 2)):\n center_radius = 0 if rank_int == 1 else PlayingCard.width / 3.5\n suit_rotation = 0 if rank_int == 1 else -90\n suit_height = (\n 0.00159 * rank_int**2 - 0.0380 * rank_int + 0.37\n ) * PlayingCard.width\n with PolarLocations(\n radius=center_radius,\n count=rank_int,\n start_angle=90 if rank_int > 1 else 0,\n ):\n PlayingCard.suits[suit](\n height=suit_height,\n rotation=suit_rotation,\n mode=Mode.SUBTRACT,\n )\n super().__init__(\n obj=playing_card.sketch, rotation=rotation, align=align, mode=mode\n )\n \n \n ace_spades = PlayingCard(rank=\"A\", suit=\"Spades\", align=Align.MIN)\n ace_spades.color = Color(\"white\")\n king_hearts = PlayingCard(rank=\"K\", suit=\"Hearts\", align=Align.MIN)\n king_hearts.color = Color(\"white\")\n queen_clubs = PlayingCard(rank=\"Q\", suit=\"Clubs\", align=Align.MIN)\n queen_clubs.color = Color(\"white\")\n jack_diamonds = PlayingCard(rank=\"J\", suit=\"Diamonds\", align=Align.MIN)\n jack_diamonds.color = Color(\"white\")\n ten_spades = PlayingCard(rank=\"10\", suit=\"Spades\", align=Align.MIN)\n ten_spades.color = Color(\"white\")\n \n hand = Compound(\n children=[\n Rot(0, 0, -20) * Pos(0, 0, 0) * ace_spades,\n Rot(0, 0, -10) * Pos(0, 0, -1) * king_hearts,\n Rot(0, 0, 0) * Pos(0, 0, -2) * queen_clubs,\n Rot(0, 0, 10) * Pos(0, 0, -3) * jack_diamonds,\n Rot(0, 0, 20) * Pos(0, 0, -4) * ten_spades,\n ]\n )\n \n show_object(Pos(-20, 40) * hand)\n show_object(box_builder.part, \"box_builder\")\n show_object(\n Pos(0, 0, (wall + deck) / 2) * lid_builder.part,\n \"lid_builder\",\n options={\"alpha\": 0.7},\n )\n\n.. _stud_wall:","api_names":"__init__ add add_layer add_shape Bezier bounding_box BuildLine BuildPart BuildSketch Club Color Compound Diamond ExportSVG extrude faces fillet GridLocations Heart Implementation index Line Location Locations make_face mirror moved offset PlayingCard PolarLocations Pos project_to_viewport rank Rectangle Rot scale show_object sort_by Spade suit super Text vertices write","synonyms":"array bevel edge bore channel drill fit gap groove hollow path cut pattern recessed fastener reflect repeat round edge shell symmetry tolerance wall thickness"},"77":{"title":"Stud Wall","body":".. image:: assets/examples/stud_wall.png\n :align: center\n\nThis example demonstrates creating custom `Part` objects and putting them into\nassemblies. The custom object is a `Stud` used in the building industry while\nthe assembly is a `StudWall` created from copies of `Stud` objects for efficiency.\nBoth the `Stud` and `StudWall` objects use `RigidJoints` to define snap points which\nare used to position all of objects.\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n class Stud(BasePartObject):\n \"\"\"Part Object: Stud\n \n Create a dimensional framing stud.\n \n Args:\n length (float): stud size\n width (float): stud size\n thickness (float): stud size\n rotation (RotationLike, optional): angles to rotate about axes. Defaults to (0, 0, 0).\n align (Union[Align, tuple[Align, Align, Align]], optional): align min, center,\n or max of object. Defaults to (Align.CENTER, Align.CENTER, Align.MIN).\n mode (Mode, optional): combine mode. Defaults to Mode.ADD.\n \"\"\"\n \n _applies_to = [BuildPart._tag]\n \n def __init__(\n self,\n length: float = 8 * FT,\n width: float = 3.5 * IN,\n thickness: float = 1.5 * IN,\n rotation: RotationLike = (0, 0, 0),\n align: Union[None, Align, tuple[Align, Align, Align]] = (\n Align.CENTER,\n Align.CENTER,\n Align.MIN,\n ),\n mode: Mode = Mode.ADD,\n ):\n self.length = length\n self.width = width\n self.thickness = thickness\n \n # Create the basic shape\n with BuildPart() as stud:\n with BuildSketch():\n RectangleRounded(thickness, width, 0.25 * IN)\n extrude(amount=length)\n \n # Create a Part object with appropriate alignment and rotation\n super().__init__(part=stud.part, rotation=rotation, align=align, mode=mode)\n \n # Add joints to the ends of the stud\n RigidJoint(\"end0\", self, Location())\n RigidJoint(\"end1\", self, Location((0, 0, length), (1, 0, 0), 180))\n \n \n class StudWall(Compound):\n \"\"\"StudWall\n \n A simple stud wall assembly with top and sole plates.\n \n Args:\n length (float): wall length\n depth (float, optional): stud width. Defaults to 3.5*IN.\n height (float, optional): wall height. Defaults to 8*FT.\n stud_spacing (float, optional): center-to-center. Defaults to 16*IN.\n stud_thickness (float, optional): Defaults to 1.5*IN.\n \"\"\"\n \n def __init__(\n self,\n length: float,\n depth: float = 3.5 * IN,\n height: float = 8 * FT,\n stud_spacing: float = 16 * IN,\n stud_thickness: float = 1.5 * IN,\n ):\n # Create the object that will be used for top and sole plates\n plate = Stud(\n length,\n depth,\n rotation=(0, -90, 0),\n align=(Align.MIN, Align.CENTER, Align.MAX),\n )\n # Define where studs will go on the plates\n stud_locations = Pos(stud_thickness / 2, 0, stud_thickness) * GridLocations(\n stud_spacing, 0, int(length / stud_spacing) + 1, 1, align=Align.MIN\n )\n stud_locations.append(Pos(length - stud_thickness / 2, 0, stud_thickness))\n \n # Create a single stud that will be copied for efficiency\n stud = Stud(height - 2 * stud_thickness, depth, stud_thickness)\n \n # For efficiency studs in the walls are copies with their own position\n studs = []\n for i, loc in enumerate(stud_locations):\n stud_joint = RigidJoint(f\"stud{i}\", plate, loc)\n stud_copy = copy.copy(stud)\n stud_joint.connect_to(stud_copy.joints[\"end0\"])\n studs.append(stud_copy)\n top_plate = copy.copy(plate)\n sole_plate = copy.copy(plate)\n \n # Position the top plate relative to the top of the first stud\n studs[0].joints[\"end1\"].connect_to(top_plate.joints[\"stud0\"])\n \n # Build the assembly of parts\n super().__init__(children=[top_plate, sole_plate] + studs)\n \n # Add joints to the wall\n RigidJoint(\"inside0\", self, Location((depth / 2, depth / 2, 0), (0, 0, 1), 90))\n RigidJoint(\"end0\", self, Location())\n \n \n x_wall = StudWall(13 * FT)\n y_wall = StudWall(9 * FT)\n x_wall.joints[\"inside0\"].connect_to(y_wall.joints[\"end0\"])\n \n show(x_wall, y_wall, render_joints=False)\n\n.. _tea_cup:","api_names":"__init__ align append BuildPart BuildSketch connect_to copy depth extrude GridLocations height Implementation length Location mode Pos RectangleRounded RigidJoint rotation show Stud stud_spacing stud_thickness StudWall super thickness to width","synonyms":"array pattern repeat"},"78":{"title":"Tea Cup","body":".. image:: assets/examples/tea_cup.png\n :align: center\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n wall_thickness = 3 * MM\n fillet_radius = wall_thickness * 0.49\n \n with BuildPart() as tea_cup:\n # Create the bowl of the cup as a revolved cross section\n with BuildSketch(Plane.XZ) as bowl_section:\n with BuildLine():\n # Start & end points with control tangents\n s = Spline(\n (30 * MM, 10 * MM),\n (69 * MM, 105 * MM),\n tangents=((1, 0.5), (0.7, 1)),\n tangent_scalars=(1.75, 1),\n )\n # Lines to finish creating ½ the bowl shape\n Polyline(s @ 0, s @ 0 + (10 * MM, -10 * MM), (0, 0), (0, (s @ 1).Y), s @ 1)\n make_face() # Create a filled 2D shape\n revolve(axis=Axis.Z)\n # Hollow out the bowl with openings on the top and bottom\n offset(amount=-wall_thickness, openings=tea_cup.faces().filter_by(GeomType.PLANE))\n # Add a bottom to the bowl\n with Locations((0, 0, (s @ 0).Y)):\n Cylinder(radius=(s @ 0).X, height=wall_thickness)\n # Smooth out all the edges\n fillet(tea_cup.edges(), radius=fillet_radius)\n \n # Determine where the handle contacts the bowl\n handle_intersections = [\n tea_cup.part.find_intersection_points(\n Axis(origin=(0, 0, vertical_offset), direction=(1, 0, 0))\n )[-1][0]\n for vertical_offset in [35 * MM, 80 * MM]\n ]\n # Create a path for handle creation\n with BuildLine(Plane.XZ) as handle_path:\n Spline(\n handle_intersections[0] - (wall_thickness / 2, 0),\n handle_intersections[0] + (35 * MM, 30 * MM),\n handle_intersections[0] + (40 * MM, 60 * MM),\n handle_intersections[1] - (wall_thickness / 2, 0),\n tangents=((1, 1.25), (-0.2, -1)),\n )\n # Align the cross section to the beginning of the path\n with BuildSketch(handle_path.line ^ 0) as handle_cross_section:\n RectangleRounded(wall_thickness, 8 * MM, fillet_radius)\n sweep() # Sweep handle cross section along path\n \n assert abs(tea_cup.part.volume - 130326) < 1\n \n show(tea_cup, names=[\"tea cup\"])\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n wall_thickness = 3 * MM\n fillet_radius = wall_thickness * 0.49\n \n # Create the bowl of the cup as a revolved cross section\n \n # Start & end points with control tangents\n s = Spline(\n (30 * MM, 10 * MM),\n (69 * MM, 105 * MM),\n tangents=((1, 0.5), (0.7, 1)),\n tangent_scalars=(1.75, 1),\n )\n # Lines to finish creating ½ the bowl shape\n s += Polyline(s @ 0, s @ 0 + (10 * MM, -10 * MM), (0, 0), (0, (s @ 1).Y), s @ 1)\n bowl_section = Plane.XZ * make_face(s) # Create a filled 2D shape\n tea_cup = revolve(bowl_section, axis=Axis.Z)\n \n # Hollow out the bowl with openings on the top and bottom\n tea_cup = offset(\n tea_cup, -wall_thickness, openings=tea_cup.faces().filter_by(GeomType.PLANE)\n )\n \n # Add a bottom to the bowl\n tea_cup += Pos(0, 0, (s @ 0).Y) * Cylinder(radius=(s @ 0).X, height=wall_thickness)\n \n # Smooth out all the edges\n tea_cup = fillet(tea_cup.edges(), radius=fillet_radius)\n \n # Determine where the handle contacts the bowl\n handle_intersections = [\n tea_cup.find_intersection_points(\n Axis(origin=(0, 0, vertical_offset), direction=(1, 0, 0))\n )[-1][0]\n for vertical_offset in [35 * MM, 80 * MM]\n ]\n \n # Create a path for handle creation\n path_spline = Spline(\n handle_intersections[0] - (wall_thickness / 2, 0, 0),\n handle_intersections[0] + (35 * MM, 0, 30 * MM),\n handle_intersections[0] + (40 * MM, 0, 60 * MM),\n handle_intersections[1] - (wall_thickness / 2, 0, 0),\n tangents=((1, 0, 1.25), (-0.2, 0, -1)),\n )\n \n # Align the cross section to the beginning of the path\n location = path_spline ^ 0\n handle_cross_section = location * RectangleRounded(wall_thickness, 8 * MM, fillet_radius)\n \n # Sweep handle cross section along path\n tea_cup += sweep(handle_cross_section, path=path_spline)\n \n # assert abs(tea_cup.part.volume - 130326.77052487945) < 1e-3\n \n show(tea_cup, names=[\"tea cup\"])\n\nThis example demonstrates the creation a tea cup, which serves as an example of\nconstructing complex, non-flat geometrical shapes programmatically.\n\nThe tea cup model involves several CAD techniques, such as:\n\n* Revolve Operations: There is 1 occurrence of a revolve operation. This is used\n to create the main body of the tea cup by revolving a profile around an axis,\n a common technique for generating symmetrical objects like cups.\n* Sweep Operations: There are 2 occurrences of sweep operations. The handle are\n created by sweeping a profile along a path to generate non-planar surfaces.\n* Offset/Shell Operations: the bowl of the cup is hollowed out with the offset\n operation leaving the top open.\n* Fillet Operations: There is 1 occurrence of a fillet operation which is used to\n round the edges for aesthetic improvement and to mimic real-world objects more\n closely.\n\n\n.. _toy_truck:","api_names":"abs Axis BuildLine BuildPart BuildSketch Cylinder edges faces fillet filter_by find_intersection_points Implementation Locations make_face offset Polyline Pos RectangleRounded revolve show Spline sweep","synonyms":"array axisymmetric bevel edge channel control points fit gap groove hollow interpolation lathe path cut pattern repeat round edge shell smooth curve tolerance turned wall thickness"},"79":{"title":"The build123d Examples","body":".. |siren| replace:: 🚨\n.. |Builder| replace:: 🔨\n.. |Algebra| replace:: ✏️","api_names":"","synonyms":""},"80":{"title":"Toy Truck","body":".. image:: assets/examples/toy_truck.png\n :align: center\n\n.. image:: assets/examples/toy_truck_picture.jpg\n :align: center\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import show\n \n # Toy Truck Blue\n truck_color = Color(0x4683CE)\n \n # Create the main truck body - from bumper to bed, excluding the cab\n with BuildPart() as body:\n # The body has two axes of symmetry, so we start with a centered sketch.\n # The default workplane is Plane.XY.\n with BuildSketch() as body_skt:\n Rectangle(20, 35)\n # Fillet all the corners of the sketch.\n # Alternatively, you could use RectangleRounded.\n fillet(body_skt.vertices(), 1)\n \n # Extrude the body shape upward\n extrude(amount=10, taper=4)\n # Reuse the sketch by accessing it explicitly\n extrude(body_skt.sketch, amount=8, taper=2)\n \n # Create symmetric fenders on Plane.YZ\n with BuildSketch(Plane.YZ) as fender:\n # The trapezoid has asymmetric angles (80°, 88°)\n Trapezoid(18, 6, 80, 88, align=Align.MIN)\n # Fillet top edge vertices (Y-direction highest group)\n fillet(fender.vertices().group_by(Axis.Y)[-1], 1.5)\n \n # Extrude the fender in both directions\n extrude(amount=10.5, both=True)\n \n # Create wheel wells with a shifted sketch on Plane.YZ\n with BuildSketch(Plane.YZ.shift_origin((0, 3.5, 0))) as wheel_well:\n Trapezoid(12, 4, 70, 85, align=Align.MIN)\n fillet(wheel_well.vertices().group_by(Axis.Y)[-1], 2)\n \n # Subtract the wheel well geometry\n extrude(amount=10.5, both=True, mode=Mode.SUBTRACT)\n \n # Fillet the top edges of the body\n fillet(body.edges().group_by(Axis.Z)[-1], 1)\n \n # Isolate a set of body edges and preview before filleting\n body_edges = body.edges().group_by(Axis.Z)[-6]\n fillet(body_edges, 0.1)\n \n # Combine edge groups from both sides of the fender and fillet them\n fender_edges = body.edges().group_by(Axis.X)[0] + body.edges().group_by(Axis.X)[-1]\n fender_edges = fender_edges.group_by(Axis.Z)[1:]\n fillet(fender_edges, 0.4)\n \n # Create a sketch on the front of the truck for the grill\n with BuildSketch(\n Plane.XZ.offset(-body.vertices().sort_by(Axis.Y)[-1].Y - 0.5)\n ) as grill:\n Rectangle(16, 8.5, align=(Align.CENTER, Align.MIN))\n fillet(grill.vertices().group_by(Axis.Y)[-1], 1)\n \n # Add headlights (subtractive circles)\n with Locations((0, 6.5)):\n with GridLocations(12, 0, 2, 1):\n Circle(1, mode=Mode.SUBTRACT)\n \n # Add air vents (subtractive slots)\n with Locations((0, 3)):\n with GridLocations(0, 0.8, 1, 4):\n SlotOverall(10, 0.5, mode=Mode.SUBTRACT)\n \n # Extrude the grill forward\n extrude(amount=2)\n \n # Fillet only the outer grill edges (exclude headlight/vent cuts)\n grill_perimeter = body.faces().sort_by(Axis.Y)[-1].outer_wire()\n fillet(grill_perimeter.edges(), 0.2)\n \n # Create the bumper as a separate part inside the body\n with BuildPart() as bumper:\n # Find the midpoint of a front edge and shift slightly to position the bumper\n front_cnt = body.edges().group_by(Axis.Z)[0].sort_by(Axis.Y)[-1] @ 0.5 - (0, 3)\n \n with BuildSketch() as bumper_plan:\n # Use BuildLine to draw an elliptical arc and offset\n with BuildLine():\n EllipticalCenterArc(front_cnt, 20, 4, start_angle=60, arc_size=60)\n offset(amount=1)\n make_face()\n \n # Extrude the bumper symmetrically\n extrude(amount=1, both=True)\n fillet(bumper.edges(), 0.25)\n \n # Define a joint on top of the body to connect the cab later\n RigidJoint(\"body_top\", joint_location=Location((0, -7.5, 10)))\n body.part.color = truck_color\n \n # Create the cab as an independent part to mount on the body\n with BuildPart() as cab:\n with BuildSketch() as cab_plan:\n RectangleRounded(16, 16, 1)\n # Split the sketch to work on one symmetric half\n split(bisect_by=Plane.YZ)\n \n # Extrude the cab forward and upward at an angle\n extrude(amount=7, dir=(0, 0.15, 1))\n fillet(cab.edges().group_by(Axis.Z)[-1].group_by(Axis.X)[1:], 1)\n \n # Rear window\n with BuildSketch(Plane.XZ.shift_origin((0, 0, 3))) as rear_window:\n RectangleRounded(8, 4, 0.75)\n extrude(amount=10, mode=Mode.SUBTRACT)\n \n # Front window\n with BuildSketch(Plane.XZ) as front_window:\n RectangleRounded(15.2, 11, 0.75)\n extrude(amount=-10, mode=Mode.SUBTRACT)\n \n # Side windows\n with BuildSketch(Plane.YZ) as side_window:\n with Locations((3.5, 0)):\n with GridLocations(10, 0, 2, 1):\n Trapezoid(9, 5.5, 80, 100, align=(Align.CENTER, Align.MIN))\n fillet(side_window.vertices().group_by(Axis.Y)[-1], 0.5)\n extrude(amount=12, both=True, mode=Mode.SUBTRACT)\n \n # Mirror to complete the cab\n mirror(about=Plane.YZ)\n \n # Define joint on cab base\n RigidJoint(\"cab_base\", joint_location=Location((0, 0, 0)))\n cab.part.color = truck_color\n \n # Attach the cab to the truck body using joints\n body.joints[\"body_top\"].connect_to(cab.joints[\"cab_base\"])\n \n # Show the result\n show(body.part, cab.part)\n\nThis example demonstrates how to design a toy truck using BuildPart and\nBuildSketch in Builder mode. The model includes a detailed body, cab, grill,\nand bumper, showcasing techniques like sketch reuse, symmetry, tapered\nextrusions, selective filleting, and the use of joints for part assembly.\nIdeal for learning complex part construction and hierarchical modeling in\nbuild123d.\n\n.. _vase:","api_names":"angles BuildLine BuildPart BuildSketch Circle Color connect_to edges EllipticalCenterArc extrude faces fillet GridLocations group_by headlights Implementation Location Locations make_face mirror offset outer_wire Rectangle RectangleRounded RigidJoint shift_origin show SlotOverall sort_by split Trapezoid vents vertices","synonyms":"array bevel edge channel cut in half fit gap groove hollow path cut pattern reflect repeat round edge shell slice symmetry tolerance trim wall thickness"},"81":{"title":"Vase","body":".. image:: assets/examples/vase.png\n :align: center\n\n.. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show_object\n \n with BuildPart() as vase:\n with BuildSketch() as profile:\n with BuildLine() as outline:\n l1 = Line((0, 0), (12, 0))\n l2 = RadiusArc(l1 @ 1, (15, 20), 50)\n l3 = Spline(l2 @ 1, (22, 40), (20, 50), tangents=(l2 % 1, (-0.75, 1)))\n l4 = RadiusArc(l3 @ 1, l3 @ 1 + Vector(0, 5), 5)\n l5 = Spline(\n l4 @ 1,\n l4 @ 1 + Vector(2.5, 2.5),\n l4 @ 1 + Vector(0, 5),\n tangents=(l4 % 1, (-1, 0)),\n )\n Polyline(\n l5 @ 1,\n l5 @ 1 + Vector(0, 1),\n (0, (l5 @ 1).Y + 1),\n l1 @ 0,\n )\n make_face()\n revolve(axis=Axis.Y)\n offset(openings=vase.faces().filter_by(Axis.Y)[-1], amount=-1)\n top_edges = (\n vase.edges().filter_by_position(Axis.Y, 60, 62).filter_by(GeomType.CIRCLE)\n )\n fillet(top_edges, radius=0.25)\n fillet(vase.edges().sort_by(Axis.Y)[0], radius=0.5)\n \n \n show_object(Rot(90, 0, 0) * vase.part, name=\"vase\")\n\n.. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show_object\n \n l1 = Line((0, 0), (12, 0))\n l2 = RadiusArc(l1 @ 1, (15, 20), 50)\n l3 = Spline(l2 @ 1, (22, 40), (20, 50), tangents=(l2 % 1, (-0.75, 1)))\n l4 = RadiusArc(l3 @ 1, l3 @ 1 + Vector(0, 5), 5)\n l5 = Spline(\n l4 @ 1,\n l4 @ 1 + Vector(2.5, 2.5),\n l4 @ 1 + Vector(0, 5),\n tangents=(l4 % 1, (-1, 0)),\n )\n outline = l1 + l2 + l3 + l4 + l5\n outline += Polyline(\n l5 @ 1,\n l5 @ 1 + Vector(0, 1),\n (0, (l5 @ 1).Y + 1),\n l1 @ 0,\n )\n profile = make_face(outline.edges())\n vase = revolve(profile, Axis.Y)\n vase = offset(vase, openings=vase.faces().sort_by(Axis.Y).last, amount=-1)\n \n top_edges = vase.edges().filter_by(GeomType.CIRCLE).filter_by_position(Axis.Y, 60, 62)\n vase = fillet(top_edges, radius=0.25)\n \n vase = fillet(vase.edges().sort_by(Axis.Y).first, radius=0.5)\n \n show_object(Rot(90, 0, 0) * vase, name=\"vase\")\n\nThis example demonstrates the build123d techniques involving the creation of a vase.\nSpecifically, it showcases the processes of revolving a sketch, shelling\n(creating a hollow object by removing material from its interior), and\nselecting edges by position range and type for the application of fillets\n(rounding off the edges).\n\n* Sketching: Drawing a 2D profile or outline that represents the side view of\n the vase.\n* Revolving: Rotating the sketch around an axis to create a 3D object. This\n step transforms the 2D profile into a 3D vase shape.\n* Offset/Shelling: Removing material from the interior of the solid vase to\n create a hollow space, making it resemble a real vase more closely.\n* Edge Filleting: Selecting specific edges of the vase for filleting, which\n involves rounding those edges. The edges are selected based on their position\n and type.\n\n\n.. NOTE 02: insert new example thumbnails above this line\n\n\n.. TODO: Copy this block to add your example details here\n .. _examples-{name-of-your-example}:\n\n {name-of-your-example-with-spaces}\n --------------------------------\n .. image:: assets/examples/example_{name-of-your-example}_01.{extension}\n :align: center\n\n .. image:: assets/examples/example_{name-of-your-example}_02.{extension}\n :align: center\n\n .. dropdown:: info\n\n TODO: add more information about your example\n\n .. dropdown:: |Builder| Reference Implementation (Builder Mode)\n\n .. code-block:: build123d\n\n with bd.BuildPart() as bp:\n bd.Box(3, 3, 3)\n with bd.BuildSketch(*bp.faces()):\n bd.Rectangle(1, 2, rotation=45)\n bd.extrude(amount=0.1)\n \n assert abs(bp.part.volume - (3**3 + 6 * (1 * 2 * 0.1)) < 1e-3)\n \n if \"show_object\" in locals():\n show_object(bp.part.wrapped, name=\"box on faces\")\n\n .. dropdown:: |Algebra| Reference Implementation (Algebra Mode)\n\n .. code-block:: build123d\n\n b = Box(3, 3, 3)\n b2 = Rot(0, 0, 45) * extrude(Rectangle(1, 2), 0.1)\n for plane in [Plane(f) for f in b.faces()]:\n b += plane * b2\n \n if \"show_object\" in locals():\n show_object(b, name=\"box on faces\")","api_names":"abs Box BuildLine BuildPart BuildSketch edges extrude faces fillet fillets filter_by filter_by_position Implementation Line locals make_face offset Plane Polyline RadiusArc Rectangle revolve Rot shelling show_object sort_by Spline Vector","synonyms":"axisymmetric bevel edge control points fit gap hollow interpolation lathe round edge shell smooth curve tolerance turned wall thickness"},"82":{"title":"bd_beams_and_bars","body":"2D sections and 3D beams generation (UPN, IPN, UPE, flat bars, ...)\n\nSee: `bd_beams_and_bars `_","api_names":"generation","synonyms":""},"83":{"title":"bd_vslot","body":"A library of V-Slot linear rail components, including V-Slot rails.\n\nSee: `bd_vslot `_","api_names":"","synonyms":""},"84":{"title":"bd_warehouse","body":"On-demand generation of parametric parts that seamlessly integrate into\nbuild123d projects.\n\nParts available include:\n\n * fastener - Nuts, Screws, Washers and custom holes\n * flange - Standardized parametric flanges\n * pipe - Standardized parametric pipes\n * thread - Parametric helical threads (Iso, Acme, Plastic, etc.)\n\nSee: `bd_warehouse `_","api_names":"threads","synonyms":"bore drill recessed fastener"},"85":{"title":"blendquery","body":"CadQuery and build123d integration for Blender.\n\nSee: `blendquery `_","api_names":"","synonyms":""},"86":{"title":"cq-editor fork","body":"GUI editor based on PyQT. This fork has changes from jdegenstein to allow easier use with build123d.\n\nSee: `jdegenstein's fork of cq-editor `_","api_names":"","synonyms":""},"87":{"title":"dl4to4ocp","body":"Library that helps perform `topology optimization `_ on\nyour `OCP `_-based CAD\nmodels (`CadQuery `_/`Build123d `_/...) using\nthe `dl4to `_ library.\n\nSee: `dl4to4ocp `_","api_names":"models","synonyms":""},"88":{"title":"Editors & Viewers","body":"","api_names":"","synonyms":""},"89":{"title":"External Tools and Libraries","body":"The following sections describe tools and libraries external to build123d\nthat extend its functionality.","api_names":"","synonyms":""},"90":{"title":"makerrepo-cli","body":"Command-line tool (available as ``makerrepo-cli`` or ``mr``) to build artifacts,\nrun generators, snapshot artifacts, and manage cache locally. It scans the\ncurrent directory for Python packages and modules that use the MakerRepo library\ndecorators.\n\nSee `MakerRepo CLI `_ for\ndocumentation and `LaunchPlatform/makerrepo-cli `_\nfor source code.","api_names":"makerrepo mr tool","synonyms":""},"91":{"title":"MakerRepo library (mr)","body":"The ``makerrepo`` Python package (imported as ``mr``) is a lightweight library that\nprovides decorators such as ``@artifact``, ``@customizable``, and ``@cached`` to\nannotate functions that build your models. The decorators have no effect on your\nexisting build123d code until it is discovered and run by tools such as the\n`makerrepo-cli `_ or\n`MakerRepo.com `_ CI. The goal is to enable a code-driven\nworkflow locally (e.g. command-line tools) or in CI. The library does not assume\nhow it will be consumed, so annotated functions can be used with other tools and\nframeworks as well.\n\nSee `MakerRepo Library Docs `_ for\nmore information and `LaunchPlatform/makerrepo `_\nfor source code.","api_names":"library locally makerrepo mr package","synonyms":""},"92":{"title":"nething","body":"3D generative AI for CAD modeling. Now everyone is an engineer. Make your ideas real.\n\nSee: `nething `_\n\nListen to the following podcast which discusses **nething** in detail:\n`The Next Byte Podcast `_","api_names":"","synonyms":""},"93":{"title":"ocp-freecad-cam","body":"CAM for CadQuery and Build123d by leveraging FreeCAD library. Visualizes in CQ-Editor \nand ocp-cad-viewer. Spiritual successor of `cq-cam `_\n\nSee: `ocp-freecad-cam `_","api_names":"","synonyms":""},"94":{"title":"ocp-vscode","body":"A viewer for OCP based Code-CAD (CadQuery, build123d) integrated into\nVS Code.\n\nSee: `ocp-vscode `_\n(formerly known as cq_vscode)\n\nWatch Jern create three build123d designs in realtime with Visual\nStudio Code and the ocp-vscode viewer extension in a timed event from the TooTallToby 2024 Spring Open Tournament: \n`build123d entry video `_","api_names":"_ CAD","synonyms":""},"95":{"title":"OCP.wasm","body":"This project ports the low-level dependencies required for build123d to run in a browser. \nFor a fully featured frontend, check out ``Yet Another CAD Viewer`` (see above).\n\nSee: `OCP.wasm `_","api_names":"Yet","synonyms":""},"96":{"title":"Part Libraries","body":"","api_names":"","synonyms":""},"97":{"title":"PartCAD","body":"A package manager for CAD models. Build123d is the most supported Code-CAD framework,\nbut CadQuery and OpenSCAD are also supported. It can be used by build123d designs\n`to import parts `_\nfrom PartCAD repositories, and to\n`publish build123d designs `_\nto be consumed by others.","api_names":"","synonyms":""},"98":{"title":"PartCAD VS Code extension","body":"A wrapper around ``ocp-vscode`` (see above) which requires build123d scripts to be\npackaged using ``PartCAD`` (see below). While it requires the overhead of maintaining\nthe package, it provides some convenience features (such as UI controls to export models)\nas well as functional features (such as UI controls to pass parameters into build123d scripts\nand AI-based generative design tools).\n\nIt's also the most convenient tool to create new packages and parts. More PDM and PLM features are expected to arrive soon.","api_names":"features ocp PartCAD","synonyms":""},"99":{"title":"partomatic","body":"Partomatic provides a standardized system for building parametric models in build123d.\nThe open nature of build123d is its strength, but it makes it difficult to build\nstandardized tooling to interface with your projects. It makes it easy to:\n\n * import and export configuration files\n * easily export models for projects that provide large numbers of intersectional options\n * share the built-in web interface allowing end-users to change properties and see the results quickly\n * generate logs for compilation and web interface events that can be consumed by an OpenTelemetry platform\n\nSee: `Partomatic `_","api_names":"","synonyms":""},"100":{"title":"Public PartCAD repository","body":"See `partcad.org `_ for all the models packaged and published\nusing ``PartCAD`` (see below). This repository contains individual parts,\nas well as large assemblies created using those parts. See\n`the OpenVMP robot `_\nas an example of an assembly","api_names":"PartCAD","synonyms":""},"101":{"title":"py_gearworks generator","body":"A gear generation framework that allows easy creation of a wide range of gears and drives.\n\nSee `py_gearworks `_","api_names":"","synonyms":""},"102":{"title":"Superellipses & Superellipsoids","body":"Superellipses are a more sophisticated alternative to rounded\nrectangles, with smoothly changing curvature. They are flexible\nshapes that can be adjusted by changing the \"exponent\" to get a\nresult that varies between rectangular and elliptical, or from\nsquare, through squircle, to circle, and beyond...\n\nSuperellipses can be found:\n\n * in typefaces such as Melior, Eurostyle, and Computer Modern\n * as the shape of airliner windows, tables, plates\n * clipping the outline of iOS app icons\n\nThey were named and popularized in the 1950s-1960s by the Danish\nmathematician and poet Piet Hein, who used them in the winning\ndesign for the Sergels Torg roundabout in Stockholm.\n\nSee: `Superellipses & Superellipsoids `_","api_names":"","synonyms":""},"103":{"title":"Tools","body":"","api_names":"","synonyms":""},"104":{"title":"Yet Another CAD Viewer","body":"A web-based CAD viewer for OCP models (CadQuery/build123d) that runs in any modern browser and supports\nstatic site deployment. Features include interactive inspection of faces, edges, and vertices, \nmeasurement tools, per-model clipping planes, transparency control, and hot reloading via ``yacv-server``. \nIt also has a build123d playground for editing and sharing models directly in the browser \n(`demo `_).\n\nSee: `Yet Another CAD Viewer `_","api_names":"browser models yacv","synonyms":""},"105":{"title":"2D Importers","body":".. py:module:: import_dxf\n.. autofunction:: import_dxf\n\n.. py:module:: importers\n.. autofunction:: import_svg\n.. autofunction:: import_svg_as_buildline_code","api_names":"import_dxf import_svg import_svg_as_buildline_code","synonyms":""},"106":{"title":"3D Exporters","body":".. py:module:: exporters3d\n\n.. autofunction:: export_brep\n :noindex:\n\n.. autofunction:: export_gltf\n :noindex:\n\n.. autofunction:: export_step\n :noindex:\n\n.. autofunction:: export_stl\n :noindex:","api_names":"export_brep export_gltf export_step export_stl","synonyms":""},"107":{"title":"3D Importers","body":".. autofunction:: import_brep\n.. autofunction:: import_step\n.. autofunction:: import_stl","api_names":"import_brep import_step import_stl","synonyms":""},"108":{"title":"3D Mesh Export","body":"Both 3MF and STL export (and import) are provided with the :class:`~mesher.Mesher` class.\nAs mentioned above, the 3MF format it provides is feature-rich and therefore has a slightly\nmore complex API than the simple Shape exporters.\n\nFor example:\n\n.. code-block:: build123d\n\n # Create the shapes and assign attributes\n blue_shape = Solid.make_cone(20, 0, 50)\n blue_shape.color = Color(\"blue\")\n blue_shape.label = \"blue\"\n blue_uuid = uuid.uuid1()\n red_shape = Solid.make_cylinder(5, 50).move(Location((0, -30, 0)))\n red_shape.color = Color(\"red\")\n red_shape.label = \"red\"\n\n # Create a Mesher instance as an exporter, add shapes and write\n exporter = Mesher()\n exporter.add_shape(blue_shape, part_number=\"blue-1234-5\", uuid_value=blue_uuid)\n exporter.add_shape(red_shape)\n exporter.add_meta_data(\n name_space=\"custom\",\n name=\"test_meta_data\",\n value=\"hello world\",\n metadata_type=\"str\",\n must_preserve=False,\n )\n exporter.add_code_to_metadata()\n exporter.write(\"example.3mf\")\n exporter.write(\"example.stl\")\n\n.. autoclass:: mesher.Mesher\n\n.. note::\n\n If you need to align multiple components for 3D printing, you can use the :ref:`pack() ` function to arrange the objects side by side and align them on the same plane. This ensures that your components are well-organized and ready for the printing process.","api_names":"add_code_to_metadata add_meta_data add_shape Color export Location make_cone make_cylinder Mesher move pack uuid1 write","synonyms":""},"109":{"title":"3D Mesh Import","body":"Both 3MF and STL import (and export) are provided with the :class:`~mesher.Mesher` class.\n\nFor example:\n\n.. code-block:: build123d\n\n importer = Mesher()\n cone, cyl = importer.read(\"example.3mf\")\n print(\n f\"{importer.mesh_count=}, {importer.vertex_counts=}, {importer.triangle_counts=}\"\n )\n print(f\"Imported model unit: {importer.model_unit}\")\n print(f\"{cone.label=}\")\n print(f\"{cone.color.to_tuple()=}\")\n print(f\"{cyl.label=}\")\n print(f\"{cyl.color.to_tuple()=}\")\n\n.. code-block:: none\n\n importer.mesh_count=2, importer.vertex_counts=[66, 52], importer.triangle_counts=[128, 100]\n Imported model unit: Unit.MM\n cone.label='blue'\n cone.color.to_tuple()=(0.0, 0.0, 1.0, 1.0)\n cyl.label='red'\n cyl.color.to_tuple()=(1.0, 0.0, 0.0, 1.0)","api_names":"import Mesher read to_tuple","synonyms":""},"110":{"title":"3D to 2D Projection","body":"There are a couple ways to generate a 2D drawing of a 3D part:\n\n* Generate a section: The :func:`~operations_part.section` operation can be used to\n create a 2D cross section of a 3D part at a given plane.\n* Generate a projection: The :meth:`~topology.Shape.project_to_viewport` method can be\n used to create a 2D projection of a 3D scene. Similar to a camera, the ``viewport_origin``\n defines the location of camera, the ``viewport_up`` defines the orientation of the camera,\n and the ``look_at`` parameter defined where the camera is pointed. By default, \n ``viewport_up`` is the positive z axis and ``look_up`` is the center of the shape. The\n return value is a tuple of lists of edges, the first the visible edges and the second\n the hidden edges. \n \nEach of these Edges and Faces can be assigned different line color/types and fill colors\nas described below (as ``project_to_viewport`` only generates Edges, fill doesn't apply). \nThe shapes generated from the above steps are to be added as shapes \nin one of the exporters described below and written as either a DXF or SVG file as shown\nin this example:\n\n.. code-block:: build123d\n\n view_port_origin=(-100, -50, 30)\n visible, hidden = part.project_to_viewport(view_port_origin)\n max_dimension = max(*Compound(children=visible + hidden).bounding_box().size)\n exporter = ExportSVG(scale=100 / max_dimension)\n exporter.add_layer(\"Visible\")\n exporter.add_layer(\"Hidden\", line_color=(99, 99, 99), line_type=LineType.ISO_DOT)\n exporter.add_shape(visible, layer=\"Visible\")\n exporter.add_shape(hidden, layer=\"Hidden\")\n exporter.write(\"part_projection.svg\")","api_names":"add_layer add_shape below bounding_box Compound ExportSVG look_at look_up project_to_viewport section viewport_origin viewport_up write","synonyms":""},"111":{"title":"3MF","body":"The 3MF (3D Manufacturing Format) file format is a versatile and modern standard \nfor representing 3D models used in additive manufacturing, 3D printing, and other \napplications. Developed by the 3MF Consortium, it aims to overcome the limitations \nof traditional 3D file formats by providing a more efficient and feature-rich solution. \nThe 3MF format supports various advanced features like color information, texture mapping, \nmulti-material definitions, and precise geometry representation, enabling seamless \ncommunication between design software, 3D printers, and other manufacturing devices. \nIts open and extensible nature makes it an ideal choice for exchanging complex 3D data \nin a compact and interoperable manner.","api_names":"","synonyms":""},"112":{"title":"BREP","body":"The BREP (Boundary Representation) file format is a widely used data format in \ncomputer-aided design (CAD) and computer-aided engineering (CAE) applications. \nBREP represents 3D geometry using topological entities like vertices, edges, \nand faces, along with their connectivity information. It provides a precise \nand comprehensive representation of complex 3D models, making it suitable for \nadvanced modeling and analysis tasks. BREP files are widely supported by various \nCAD software, enabling seamless data exchange between different systems. Its ability \nto represent both geometric shapes and their topological relationships makes it a \nfundamental format for storing and sharing detailed 3D models.","api_names":"BREP design engineering","synonyms":""},"113":{"title":"DXF","body":"The DXF (Drawing Exchange Format) file format is a widely used standard for \nrepresenting 2D and 3D drawings, primarily used in computer-aided design (CAD) \napplications. Developed by Autodesk, DXF files store graphical and geometric data, \nsuch as lines, arcs, circles, and text, as well as information about layers, colors, \nand line weights. Due to its popularity, DXF files can be easily exchanged and \nshared between different CAD software. The format's simplicity and human-readable \nstructure make it a versatile choice for sharing designs, drawings, and models \nacross various CAD platforms, facilitating seamless collaboration in engineering \nand architectural projects.","api_names":"design DXF","synonyms":""},"114":{"title":"ExportDXF","body":".. autoclass:: exporters.ExportDXF\n :noindex:","api_names":"ExportDXF","synonyms":""},"115":{"title":"ExportSVG","body":".. autoclass:: exporters.ExportSVG\n :noindex:","api_names":"ExportSVG","synonyms":""},"116":{"title":"File Formats","body":"","api_names":"","synonyms":""},"117":{"title":"glTF","body":"The glTF (GL Transmission Format) is a royalty-free specification for the efficient \ntransmission and loading of 3D models and scenes by applications. Developed by the \nKhronos Group, glTF is designed as a compact, interoperable format that enables the \nquick display of assets across various platforms and devices. glTF supports a rich \nfeature set, including detailed meshes, materials, textures, skeletal animations, \nand more, facilitating complex 3D visualizations. It streamlines the process of \nsharing and deploying 3D content in web applications, game engines, and other \nvisualization tools, making it the \"JPEG of 3D.\" glTF's versatility and efficiency \nhave led to its widespread adoption in the 3D content industry.","api_names":"glTF","synonyms":""},"118":{"title":"Import/Export","body":"Methods and functions specific to exporting and importing build123d objects are defined below.\n\nFor example:\n\n.. code-block:: build123d\n\n with BuildPart() as box_builder:\n Box(1, 1, 1)\n export_step(box_builder.part, \"box.step\")","api_names":"Box BuildPart export_step","synonyms":""},"119":{"title":"LineType","body":"ANSI (American National Standards Institute) and ISO (International Organization for \nStandardization) standards both define line types in drawings used in DXF and SVG\nexported drawings:\n\n* ANSI Standards:\n * ANSI/ASME Y14.2 - \"Line Conventions and Lettering\" is the standard that defines \n line types, line weights, and line usage in engineering drawings in the United States.\n\n* ISO Standards:\n * ISO 128 - \"Technical drawings -- General principles of presentation\" is the ISO \n standard that covers the general principles of technical drawing presentation, \n including line types and line conventions.\n * ISO 13567 - \"Technical product documentation (TPD) -- Organization and naming of \n layers for CAD\" provides guidelines for the organization and naming of layers in \n Computer-Aided Design (CAD) systems, which may include line type information.\n\nThese standards help ensure consistency and clarity in technical drawings, making it \neasier for engineers, designers, and manufacturers to communicate and interpret the \ninformation presented in the drawings.\n\nThe line types used by the 2D Exporters are defined by the :class:`~exporters.LineType` \nEnum and are shown in the following diagram:\n\n.. image:: assets/line_types.svg\n :align: center","api_names":"ANSI Design documentation ISO LineType","synonyms":""},"120":{"title":"STEP","body":"The STEP (Standard for the Exchange of Product model data) file format is a widely \nused standard for representing 3D product and manufacturing data in computer-aided \ndesign (CAD) and computer-aided engineering (CAE) applications. It is an ISO standard \n(ISO 10303) and supports the representation of complex 3D geometry, product structure, \nand metadata. STEP files store information in a neutral and standardized format, \nmaking them highly interoperable across different CAD/CAM software systems. They \nenable seamless data exchange between various engineering disciplines, facilitating \ncollaboration and data integration throughout the entire product development and \nmanufacturing process.","api_names":"design engineering standard STEP","synonyms":""},"121":{"title":"STL","body":"The STL (STereoLithography) file format is a widely used file format in 3D printing \nand computer-aided design (CAD) applications. It represents 3D geometry using \ntriangular facets to approximate the surface of a 3D model. STL files are widely \nsupported and can store both the geometry and color information of the model. \nThey are used for rapid prototyping and 3D printing, as they provide a simple and \nefficient way to represent complex 3D objects. The format's popularity stems from \nits ease of use, platform independence, and ability to accurately describe the \nsurface of intricate 3D models with a minimal file size.","api_names":"design STL","synonyms":""},"122":{"title":"STL Reconstruction","body":"The :func:`~build123d.detect_primitives` helper can be used during STL\nreconstruction to detect analytic planes, cylinders, and spheres in a mesh-like\nshape and generate algebra-mode code fragments to aid manual redesign.\n\nSee :ref:`stl_reconstruction_tutorial` for the full workflow and limitations.\n\n.. autofunction:: build123d.detect_primitives","api_names":"detect_primitives","synonyms":""},"123":{"title":"SVG","body":"The SVG (Scalable Vector Graphics) file format is an XML-based standard used for \ndescribing 2D vector graphics. It is widely supported and can be displayed in modern \nweb browsers, making it suitable for web-based graphics and interactive applications. \nSVG files define shapes, paths, text, and images using mathematical equations, \nallowing for smooth scalability without loss of quality. The format is ideal for \nlogos, icons, illustrations, and other graphics that require resolution independence. \nSVG files are also easily editable in text editors or vector graphic software, making \nthem a popular choice for designers and developers seeking flexible and versatile graphic \nrepresentation.\n\n\n2D Exporters \n============\n\nExports to DXF (Drawing Exchange Format) and SVG (Scalable Vector Graphics) \nare provided by the 2D Exporters: ExportDXF and ExportSVG classes. \n\nDXF is a widely used file format for exchanging CAD (Computer-Aided Design) \ndata between different software applications. SVG is a widely used vector graphics\nformat that is supported by web browsers and various graphic editors. \n\nThe core concept to these classes is the creation of a DXF/SVG document with \nspecific properties followed by the addition of layers and shapes to the documents.\nOnce all of the layers and shapes have been added, the document can be written\nto a file.","api_names":"CAD DXF SVG","synonyms":""},"124":{"title":"About","body":"Build123d is a Python-based, parametric (BREP) modeling framework for 2D and 3D CAD. \nBuilt on the Open Cascade geometric kernel, it provides a clean, fully Pythonic interface \nfor creating precise models suitable for 3D printing, CNC machining, laser cutting, and \nother manufacturing processes. Models can be exported to popular CAD tools such as FreeCAD \nand SolidWorks.\n\nDesigned for modern, maintainable CAD-as-code, build123d combines clear architecture with \nexpressive, algebraic modeling. It offers:\n\n* Minimal or no internal state depending on mode\n* Explicit 1D, 2D, and 3D geometry classes with well-defined operations\n* Extensibility through subclassing and functional composition-no monkey patching\n* Standards-compliant code (PEP 8, mypy, pylint) with rich pylance type hints\n* Deep Python integration-selectors as lists, locations as iterables, and natural \n conversions (``Solid(shell)``, ``tuple(Vector)``)\n* Operator-driven modeling (``obj += sub_obj``, ``Plane.XZ * Pos(X=5) * Rectangle(1, 1)``) \n for algebraic, readable, and composable design logic\n\nWith build123d, intricate parametric models can be created in just a few lines of readable \nPython code-as demonstrated by the tea cup example below.\n\n.. dropdown:: Teacup Example\n\n .. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n wall_thickness = 3 * MM\n fillet_radius = wall_thickness * 0.49\n \n with BuildPart() as tea_cup:\n # Create the bowl of the cup as a revolved cross section\n with BuildSketch(Plane.XZ) as bowl_section:\n with BuildLine():\n # Start & end points with control tangents\n s = Spline(\n (30 * MM, 10 * MM),\n (69 * MM, 105 * MM),\n tangents=((1, 0.5), (0.7, 1)),\n tangent_scalars=(1.75, 1),\n )\n # Lines to finish creating ½ the bowl shape\n Polyline(s @ 0, s @ 0 + (10 * MM, -10 * MM), (0, 0), (0, (s @ 1).Y), s @ 1)\n make_face() # Create a filled 2D shape\n revolve(axis=Axis.Z)\n # Hollow out the bowl with openings on the top and bottom\n offset(amount=-wall_thickness, openings=tea_cup.faces().filter_by(GeomType.PLANE))\n # Add a bottom to the bowl\n with Locations((0, 0, (s @ 0).Y)):\n Cylinder(radius=(s @ 0).X, height=wall_thickness)\n # Smooth out all the edges\n fillet(tea_cup.edges(), radius=fillet_radius)\n \n # Determine where the handle contacts the bowl\n handle_intersections = [\n tea_cup.part.find_intersection_points(\n Axis(origin=(0, 0, vertical_offset), direction=(1, 0, 0))\n )[-1][0]\n for vertical_offset in [35 * MM, 80 * MM]\n ]\n # Create a path for handle creation\n with BuildLine(Plane.XZ) as handle_path:\n Spline(\n handle_intersections[0] - (wall_thickness / 2, 0),\n handle_intersections[0] + (35 * MM, 30 * MM),\n handle_intersections[0] + (40 * MM, 60 * MM),\n handle_intersections[1] - (wall_thickness / 2, 0),\n tangents=((1, 1.25), (-0.2, -1)),\n )\n # Align the cross section to the beginning of the path\n with BuildSketch(handle_path.line ^ 0) as handle_cross_section:\n RectangleRounded(wall_thickness, 8 * MM, fillet_radius)\n sweep() # Sweep handle cross section along path\n \n assert abs(tea_cup.part.volume - 130326) < 1\n \n show(tea_cup, names=[\"tea cup\"])\n\n.. raw:: html\n\n \n \n\n.. note::\n\n\n This documentation is available in\n `pdf `_ and\n `epub `_ formats\n for reference while offline.\n\n.. note::\n\n There is a `Discord `_ server (shared with CadQuery) where\n you can ask for help in the build123d channel.","api_names":"abs Axis BuildLine BuildPart BuildSketch code conversions Cylinder edges faces fillet filter_by find_intersection_points Locations make_face modeling obj offset parametric Polyline Pos Rectangle RectangleRounded revolve server show Solid Spline sweep XZ","synonyms":"array axisymmetric bevel edge channel control points fit gap groove hollow interpolation lathe path cut pattern repeat round edge shell smooth curve tolerance turned wall thickness"},"125":{"title":"Indices and tables","body":"* :ref:`genindex`\n* :ref:`modindex`\n* :ref:`search`","api_names":"","synonyms":""},"126":{"title":"Table Of Contents","body":".. toctree::\n :maxdepth: 2\n\n introduction.rst\n installation.rst\n key_concepts.rst\n key_concepts_builder.rst\n key_concepts_algebra.rst\n moving_objects.rst\n OpenSCAD.rst\n introductory_examples.rst\n tutorials.rst\n objects.rst\n operations.rst\n topology_selection.rst\n builders.rst\n joints.rst\n assemblies.rst\n tips.rst\n import_export.rst\n advanced.rst\n cheat_sheet.rst\n external.rst\n builder_api_reference.rst\n direct_api_reference.rst","api_names":"","synonyms":""},"127":{"title":"Adding a nicer GUI","body":"If you prefer to have a GUI available, your best option is to choose one from here: :ref:`external`","api_names":"","synonyms":""},"128":{"title":"Development install of build123d:","body":"**Warning**: it is highly recommended to upgrade pip to the latest version before installing\nbuild123d, especially in development mode. This can be done with the following command:\n\n.. doctest::\n\n\t>>> python3 -m pip install --upgrade pip\n\nOnce pip is up-to-date, you can install build123d\n`in development mode `_\nwith the following commands:\n\n.. doctest::\n\n\t>>> git clone https://github.com/gumyr/build123d.git\n\t>>> cd build123d\n\t>>> python3 -m pip install -e .\n\nPlease substitute ``python3`` with ``python`` in the lines above if you are using Windows.\n\nIf you're working directly with the OpenCascade ``OCP`` layer you will likely want to install\nthe OCP stubs as follows:\n\n.. doctest::\n\n\t>>> python3 -m pip install git+https://github.com/CadQuery/OCP-stubs@7.7.0","api_names":"OCP python python3","synonyms":""},"129":{"title":"Install build123d from GitHub:","body":"To get the latest non-released version of **build123d** one can install from GitHub using one of the following two commands:\n\nIn Linux/MacOS, use the following command:\n\n.. doctest::\n\n\t>>> python3 -m pip install git+https://github.com/gumyr/build123d\n\nIn Windows, use the following command:\n\n.. doctest::\n\n\t>>> python -m pip install git+https://github.com/gumyr/build123d\n\nIf you receive errors about conflicting dependencies, you can retry the installation after having\nupgraded pip to the latest version with the following command:\n\n.. doctest::\n\n\t>>> python3 -m pip install --upgrade pip\n\nIf you use `poetry `_ to install build123d, you can simply use:\n\n.. doctest::\n\n\t>>> poetry add build123d\n\nHowever, if you want the latest commit from GitHub you might need to specify\nthe branch that is used for git-based installs; until quite recently, poetry used to checkout the\n`master` branch when none was specified, and this fails on build123d that uses a `dev` branch.\n\nPip does not suffer from this issue because it correctly fetches the repository default branch.\n\nIf you are a poetry user, you can work around this issue by installing build123d in the following\nway:\n\n.. doctest::\n\n\t>>> poetry add git+https://github.com/gumyr/build123d.git@dev\n\nPlease note that always suffixing the URL with ``@dev`` is safe and will work with both older and\nrecent versions of poetry.","api_names":"","synonyms":""},"130":{"title":"Installation","body":"The recommended method for most users to install **build123d** is:\n\n.. doctest::\n\n\t>>> pip install build123d\n\n.. note::\n\n\tThe `ocp-vscode `_ viewer has\n\tthe ability to install **build123d**.","api_names":"","synonyms":""},"131":{"title":"Test your build123d installation:","body":"If all has gone well, you can open a command line/prompt, and type:\n\n.. doctest::\n\n\t>>> python\n\t>>> from build123d import *\n\t>>> print(Solid.make_box(1,2,3).show_topology(limit_class=\"Face\"))\n\nWhich should return something similar to:\n\n.. code::\n\n\t\tSolid at 0x165e75379f0, Center(0.5, 1.0, 1.5)\n\t\t└── Shell at 0x165eab056f0, Center(0.5, 1.0, 1.5)\n\t\t\t├── Face at 0x165b35a3570, Center(0.0, 1.0, 1.5)\n\t\t\t├── Face at 0x165e77957f0, Center(1.0, 1.0, 1.5)\n\t\t\t├── Face at 0x165b3e730f0, Center(0.5, 0.0, 1.5)\n\t\t\t├── Face at 0x165e8821570, Center(0.5, 2.0, 1.5)\n\t\t\t├── Face at 0x165e88218f0, Center(0.5, 1.0, 0.0)\n\t\t\t└── Face at 0x165eb21ee70, Center(0.5, 1.0, 3.0)","api_names":"Center make_box show_topology","synonyms":""},"132":{"title":"Advantages Over CadQuery","body":".. include:: advantages.rst","api_names":"","synonyms":""},"133":{"title":"Automated Documentation","body":"The Sphinx automated documentation system was used to create the page you are\nreading now and can be used for user design documentation as well. Such systems\nare used for several reasons:\n\n* Consistency: Sphinx and other automated documentation systems can generate\n documentation in a consistent format and style, which makes it easier to\n understand and use.\n* Automation: Sphinx can automatically generate documentation from source code\n and comments, which saves time and effort compared to manually writing\n documentation.\n* Up-to-date documentation: Automated documentation systems like Sphinx can\n update the documentation automatically when the code changes, ensuring that the\n documentation stays up-to-date with the code.\n* Searchability: Sphinx and other automated documentation systems can include\n search functionality, which makes it easy to find the information you need.\n* Cross-referencing: Sphinx can automatically create links between different\n parts of the documentation, making it easy to navigate and understand the\n relationships between different parts of the code.\n* Customizable: Sphinx and other automated documentation systems can be\n customized to match the look and feel of your company's documentation.\n* Multiple output formats: Sphinx can generate documentation in multiple formats\n such as HTML, PDF, ePub, and more.\n* Support for multiple languages: Sphinx can generate documentation in multiple\n languages, which can make it easier to support international users.\n* Integration with code management: Sphinx can be integrated with code\n management tools like Git, which allows documentation to be versioned along with\n the code.\n\nIn summary, automated documentation systems like Sphinx are used to generate\nconsistent, up-to-date, and searchable documentation from source code and\ncomments. They save time and effort compared to manual documentation, and can be\ncustomized to match the look and feel of your company's documentation. They also\nprovide multiple output formats, support for multiple languages and can be\nintegrated with code management tools.","api_names":"","synonyms":""},"134":{"title":"Automated Testing","body":"Users of source based CAD systems can benefit from automated testing which improves\ntheir source code by:\n\n* Finding bugs: Automated tests can detect bugs in the code, which can then be\n fixed before the code is released. This helps to ensure that the code is of\n higher quality and less likely to cause issues when used.\n* Regression testing: Automated tests can be used to detect regressions, which\n are bugs that are introduced by changes to the codebase. This helps to ensure\n that changes to the code do not break existing functionality.\n* Documenting code behavior: Automated tests can serve as documentation for how\n the code is supposed to behave. This makes it easier for developers to\n understand the code and make changes without breaking it.\n* Improving code design: Writing automated tests often requires a good\n understanding of the code and how it is supposed to behave. This can lead to a\n better design of the code, as developers will have a better understanding of the\n requirements and constraints.\n* Saving time and cost: Automated testing can save time and cost by reducing the\n need for manual testing. Automated tests can be run quickly and often, which\n means that bugs can be found and fixed early in the development process, which\n is less expensive than finding them later.\n* Continuous integration and delivery: Automated testing can be integrated into\n a continuous integration and delivery (CI/CD) pipeline. This means that tests\n are run automatically every time code is committed and can be integrated with\n other tools such as code coverage, static analysis and more.\n* Improving maintainability: Automated tests can improve the maintainability of\n the code by making it easier to refactor and change the codebase. This is\n because automated tests provide a safety net that ensures that changes to the\n code do not introduce new bugs.\n\nOverall, automated testing is an essential part of the software development\nprocess, it helps to improve the quality of the code by detecting bugs early,\ndocumenting code behavior, and reducing the cost of maintaining and updating the\ncode.","api_names":"delivery","synonyms":""},"135":{"title":"Boundary Representation (BREP) Modelling","body":"Boundary representation (BREP) and mesh-based CAD systems are both used to\ncreate and manipulate 3D models, but they differ in the way they represent and\nstore the models.\n\nAdvantages of BREP-based CAD systems (e.g. build123d & SolidWorks):\n\n* Precision: BREP-based CAD systems use mathematical representations to define\n the shape of an object, which allows for more precise and accurate modeling of\n complex shapes.\n* Topology: BREP-based CAD systems maintain topological information of the 3D\n model, such as edges, faces and vertices. This allows for more robust and stable\n modeling, such as Boolean operations.\n* Analytical modeling: BREP-based CAD systems can take advantage of the\n topological information to perform analytical operations such as collision\n detection, mass properties calculations, and finite element analysis.\n* Features-based modeling: BREP-based CAD systems are often feature-based, which\n means that the model is built by creating and modifying individual features,\n such as holes, fillets, and chamfers. This allows for parametric design and easy\n modification of the model.\n* Efficient storage: BREP-based CAD systems use a compact representation to\n store the 3D model, which is more efficient than storing a large number of\n triangles used in mesh-based systems.\n\n\nAdvantages of Mesh-based CAD systems (e.g. Blender, OpenSCAD):\n\n* Simplicity: Mesh-based CAD systems use a large number of triangles to\n represent the surface of an object, which makes them easy to use and understand.\n* Real-time rendering: Mesh-based CAD systems can be rendered in real-time,\n which is useful for applications such as video games and virtual reality.\n* Flexibility: Mesh-based CAD systems can be easily exported to other 3D\n modeling and animation software, which makes them a good choice for use in the\n entertainment industry.\n* Handling of freeform surfaces: Mesh-based systems are better equipped to\n handle freeform surfaces, such as those found in organic shapes, as they do not\n rely on mathematical representation.\n* Handling of large datasets: Mesh-based systems are more suitable for handling\n large datasets such as point clouds, as they can be easily converted into a mesh\n representation.","api_names":"representation Representation systems","synonyms":"bevel edge bore drill recessed fastener round edge"},"136":{"title":"Introduction","body":"","api_names":"","synonyms":""},"137":{"title":"Key Aspects","body":"The following sections describe some of the key aspects of build123d and illustrate\nwhy one might choose this open source system over proprietary options like SolidWorks,\nOnShape, Fusion 360, or even other open source systems like Blender, or OpenSCAD.","api_names":"","synonyms":""},"138":{"title":"Open Source Software","body":"Open source and proprietary software systems are different in several ways: B\nLicensing: Open source software is licensed in a way that allows users to view,\nmodify, and distribute the source code, while proprietary software is closed\nsource and the source code is not available to the public.\n\n* Ownership: Open source software is usually developed and maintained by a\n community of developers, while proprietary software is owned by a company or\n individual.\n* Cost: Open source software is typically free to use, while proprietary\n software may require payment for a license or subscription. Customization: Open\n source software can be modified and customized by users and developers, while\n proprietary software is typically not modifiable by users.\n* Support: Open source software may have a larger community of users who can\n provide support, while proprietary software may have a smaller community and\n relies on the company for support. Security: Open source software can be\n audited by a large community of developers, which can make it more secure, while\n proprietary software may have fewer eyes on the code and may be more vulnerable\n to security issues.\n* Interoperability: Open source software may have better interoperability with\n other software and platforms, while proprietary software may have more limited\n compatibility.\n* Reliability: Open source software can be considered as reliable as proprietary\n software. It is usually used by large companies, governments, and organizations\n and has been tested by a large number of users.\n\nIn summary, open source and proprietary software systems are different in terms\nof licensing, ownership, cost, customization, support, security,\ninteroperability, and reliability. Open source software is typically free to use\nand can be modified by users and developers, while proprietary software is\nclosed-source and may require payment for a license or subscription. Open source\nsoftware may have a larger community of users who can provide support, while\nproprietary software may have a smaller community and relies on the company for\nsupport.","api_names":"","synonyms":""},"139":{"title":"Parameterized Models","body":"Parametrized CAD systems are more effective than non-parametric CAD systems in\nseveral ways:\n\n* Reusability: Parametrized CAD models can be easily modified by changing a set\n of parameters, such as the length or width of an object, rather than having to\n manually edit the geometry. This makes it easy to create variations of a design\n without having to start from scratch.\n* Design exploration: Parametrized CAD systems allow for easy exploration of\n different design options by changing the parameters and quickly visualizing the\n results. This can save a lot of time and effort during the design process.\n* Constraints and relationships: Parametrized CAD systems allow for the\n definition of constraints and relationships between different parameters. This\n ensures that the model remains valid and functional even when parameters are\n changed.\n* Automation: Parametrized CAD systems can be automated to perform repetitive\n tasks, such as generating detailed drawings or creating parts lists. This can\n save a lot of time and effort and reduce the risk of errors.\n* Collaboration: Parametrized CAD systems allow different team members to work\n on different aspects of a design simultaneously and ensure that the model\n remains consistent across different stages of the development process.\n* Document management: Parametrized CAD systems can generate engineering\n drawings, BOMs, and other documents automatically, which makes it easier to\n manage and track the design history.\n\nIn summary, parametrized CAD systems are more effective than non-parametric CAD\nsystems because they provide a more efficient and flexible way to create and\nmodify designs, and can be easily integrated into the design, manufacturing, and\ndocumentation process.","api_names":"","synonyms":""},"140":{"title":"Python Programming Language","body":"Python is a popular, high-level programming language that has several advantages\nover other programming languages:\n\n* Readability: Python code is easy to read and understand, with a clear and\n consistent syntax. This makes it a great language for beginners and for teams of\n developers who need to collaborate on a project.\n* Versatility: Python is a general-purpose language that can be used for a wide\n range of tasks, including web development, scientific computing, data analysis,\n artificial intelligence, and more. This makes it a great choice for developers\n who need to work on multiple types of projects.\n* Large community: Python has a large and active community of developers who\n contribute to the language and its ecosystem. This means that there are many\n libraries and frameworks available for developers to use, which can save a lot\n of time and effort.\n* Good for data science, machine learning, and CAD: Python has a number of libraries\n such as numpy, pandas, scikit-learn, tensorflow, and cadquery which are popularly\n used in data science and machine learning and CAD.\n* High-level language: Python is a high-level language, which means it abstracts\n away many of the low-level details of the computer. This makes it easy to write\n code quickly and focus on solving the problem at hand.\n* Cross-platform: Python code runs on many different platforms, including\n Windows, Mac, and Linux, making it a great choice for developers who need to\n write code that runs on multiple operating systems.\n* Open-source: Python is an open-source programming language, which means it is\n free to use and distribute. This makes it accessible to developers of all\n levels and budgets.\n* Large number of libraries and modules: Python has a vast collection of\n libraries and modules that make it easy to accomplish complex tasks such as\n connecting to web servers, reading and modifying files, and connecting to\n databases.","api_names":"","synonyms":""},"141":{"title":"Source Code Control Systems","body":"Most GUI based CAD systems provide version control systems which represent the\nCAD design and its history. They allows developers to see changes made to the design\nover time, in a format that is easy to understand.\n\nOn the other hand, a source code control system like Git, is a command-line tool\nand it provides more granular control over the code. This makes it suitable for\nmore advanced users and developers who are comfortable working with command-line\ninterfaces. A source code control system like Git is more flexible and allows\ndevelopers to perform tasks like branching and merging, which are not easily\ndone with a GUI version control system. Systems like Git have several advantages,\nincluding:\n\n* Version control: Git allows developers to keep track of changes made to the\n code over time, making it easy to revert to a previous version if necessary.\n* Collaboration: Git makes it easy for multiple developers to work on the same\n codebase simultaneously, with the ability to merge changes from different\n branches of development.\n* Backup: Git provides a way to backup and store the codebase in a remote\n repository, like GitHub. This can serve as a disaster recovery mechanism, in\n case of data loss.\n* Branching: Git allows developers to create multiple branches of a project for\n different features or bug fixes, which can be easily merged into the main\n codebase once they are complete.\n* Auditing: Git allows you to see who made changes to the code, when and what\n changes were made, which is useful for auditing and debugging.\n* Open-source development: Git makes it easy for open-source developers to\n contribute to a project and share their work with the community.\n* Flexibility: Git is a distributed version control system, which means that\n developers can work independently and offline. They can then push their changes\n to a remote repository when they are ready to share them with others.\n\nIn summary, GUI version control systems are generally more user-friendly and\neasier to use, while source code control systems like Git offer more flexibility\nand control over the code. Both can be used to achieve the same goal, but they\ncater to different types of users and use cases.","api_names":"","synonyms":""},"142":{"title":"1. Simple Rectangular Plate","body":"Just about the simplest possible example, a rectangular :class:`~objects_part.Box`.\n\n.. image:: assets/general_ex1.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex1:\n Box(length, width, thickness)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n ex1 = Box(length, width, thickness)\n\n\n.. _ex 2:","api_names":"Box BuildPart","synonyms":""},"143":{"title":"10. Select Last and Hole","body":".. image:: assets/general_ex10.svg\n :align: center\n\n* **Builder mode**\n\n Using :class:`~build_enums.Select` ``.LAST`` you can select the most recently modified edges.\n It is used to perform a :meth:`~operations_generic.fillet` in this example. This example also\n makes use of :class:`~objects_part.Hole` which automatically cuts through the entire part.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex10:\n Box(length, width, thickness)\n Hole(radius=width / 4)\n fillet(ex10.edges(Select.LAST).group_by(Axis.Z)[-1], radius=2)\n\n* **Algebra mode**\n\n Using the pattern ``snapshot = obj.edges()`` before and ``last_edges = obj.edges() - snapshot`` after an\n operation allows to select the most recently modified edges (same for ``faces``, ``vertices``, ...).\n It is used to perform a :meth:`~operations_generic.fillet` in this example. This example also makes use\n of :class:`~objects_part.Hole`. Different to the *context mode*, you have to add the ``depth`` of the whole.\n\n .. code-block:: build123d\n\n ex10 = Part() + Box(length, width, thickness)\n \n snapshot = ex10.edges()\n ex10 -= Hole(radius=width / 4, depth=thickness)\n last_edges = ex10.edges() - snapshot\n ex10 = fillet(last_edges.group_by(Axis.Z)[-1], 2)\n\n\n.. _ex 11:","api_names":"Box BuildPart depth edges faces fillet group_by Hole last_edges Part Select snapshot vertices","synonyms":"bevel edge bore drill recessed fastener round edge"},"144":{"title":"11. Use a face as a plane for BuildSketch and introduce GridLocations","body":".. image:: assets/general_ex11.svg\n :align: center\n\n* **Builder mode**\n\n :class:`~build_sketch.BuildSketch` accepts a Plane or a Face, so in this case we locate the Sketch\n on the top of the part. Note that the face used as input to BuildSketch needs\n to be Planar or unpredictable behavior can result. Additionally :class:`~build_common.GridLocations`\n can be used to create a grid of points that are simultaneously used to place 4\n pentagons.\n\n Lastly, :meth:`~operations_part.extrude` can be used with a negative amount and ``Mode.SUBTRACT`` to\n cut these from the parent.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex11:\n Box(length, width, thickness)\n chamfer(ex11.edges().group_by(Axis.Z)[-1], length=4)\n fillet(ex11.edges().filter_by(Axis.Z), radius=5)\n Hole(radius=width / 4)\n fillet(ex11.edges(Select.LAST).sort_by(Axis.Z)[-1], radius=2)\n with BuildSketch(ex11.faces().sort_by(Axis.Z)[-1]) as ex11_sk:\n with GridLocations(length / 2, width / 2, 2, 2):\n RegularPolygon(radius=5, side_count=5)\n extrude(amount=-thickness, mode=Mode.SUBTRACT)\n\n* **Algebra mode**\n\n The pattern ``plane * obj`` can be used to locate an object on a plane. Furthermore, the pattern\n ``plane * location * obj`` first places the object on a plane and then moves it relative to plane\n according to ``location``.\n\n :class:`~build_common.GridLocations` creates a grid of points that can be used in loops or list\n comprehensions as described earlier.\n\n Lastly, :meth:`~operations_part.extrude` can be used with a negative amount and cut (``-``) from the\n parent.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n ex11 = Part() + Box(length, width, thickness)\n ex11 = chamfer(ex11.edges().group_by()[-1], 4)\n ex11 = fillet(ex11.edges().filter_by(Axis.Z), 5)\n last = ex11.edges()\n ex11 -= Hole(radius=width / 4, depth=thickness)\n ex11 = fillet((ex11.edges() - last).sort_by().last, 2)\n \n plane = Plane(ex11.faces().sort_by().last)\n polygons = Sketch() + [\n plane * loc * RegularPolygon(radius=5, side_count=5)\n for loc in GridLocations(length / 2, width / 2, 2, 2)\n ]\n ex11 -= extrude(polygons, -thickness)\n\nNote that the direction implied by positive or negative inputs to amount is relative to the\nnormal direction of the face or plane. As a result of this, unexpected behavior can occur\nif the extrude direction and mode/operation (ADD / ``+`` or SUBTRACT / ``-``) are not correctly set.\n\n.. _ex 12:","api_names":"Box BuildPart BuildSketch chamfer cut edges extrude faces fillet filter_by GridLocations group_by Hole location operation Part plane Plane RegularPolygon Sketch sort_by SUBTRACT","synonyms":"array bevel edge bore channel drill groove path cut pattern recessed fastener repeat round edge"},"145":{"title":"12. Defining an Edge with a Spline","body":"This example defines a side using a spline curve through a collection of points. Useful when you have an\nedge that needs a complex profile.\n\n.. image:: assets/general_ex12.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n pts = [\n (55, 30),\n (50, 35),\n (40, 30),\n (30, 20),\n (20, 25),\n (10, 20),\n (0, 20),\n ]\n \n with BuildPart() as ex12:\n with BuildSketch() as ex12_sk:\n with BuildLine() as ex12_ln:\n l1 = Spline(pts)\n l2 = Line((55, 30), (60, 0))\n l3 = Line((60, 0), (0, 0))\n l4 = Line((0, 0), (0, 20))\n make_face()\n extrude(amount=10)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n pts = [\n (55, 30),\n (50, 35),\n (40, 30),\n (30, 20),\n (20, 25),\n (10, 20),\n (0, 20),\n ]\n \n l1 = Spline(pts)\n l2 = Line(l1 @ 0, (60, 0))\n l3 = Line(l2 @ 1, (0, 0))\n l4 = Line(l3 @ 1, l1 @ 1)\n \n sk12 = make_face([l1, l2, l3, l4])\n ex12 = extrude(sk12, 10)\n\n\n.. _ex 13:","api_names":"BuildLine BuildPart BuildSketch extrude Line make_face Spline","synonyms":"control points interpolation smooth curve"},"146":{"title":"13. CounterBoreHoles, CounterSinkHoles, and PolarLocations","body":"Counter-sink and counter-bore holes are useful for creating recessed areas for fasteners.\n\n.. image:: assets/general_ex13.svg\n :align: center\n\n* **Builder mode**\n\n We use a face to establish a location for :class:`~build_common.Locations`.\n\n .. code-block:: build123d\n\n a, b = 40, 4\n with BuildPart() as ex13:\n Cylinder(radius=50, height=10)\n with Locations(ex13.faces().sort_by(Axis.Z)[-1]):\n with PolarLocations(radius=a, count=4):\n CounterSinkHole(radius=b, counter_sink_radius=2 * b)\n with PolarLocations(radius=a, count=4, start_angle=45, angular_range=360):\n CounterBoreHole(radius=b, counter_bore_radius=2 * b, counter_bore_depth=b)\n\n* **Algebra mode**\n\n We use a face to establish a plane that is used later in the code for locating objects\n onto this plane.\n\n .. code-block:: build123d\n\n a, b = 40, 4\n \n ex13 = Cylinder(radius=50, height=10)\n plane = Plane(ex13.faces().sort_by().last)\n \n ex13 -= (\n plane\n * PolarLocations(radius=a, count=4)\n * CounterSinkHole(radius=b, counter_sink_radius=2 * b, depth=10)\n )\n ex13 -= (\n plane\n * PolarLocations(radius=a, count=4, start_angle=45, angular_range=360)\n * CounterBoreHole(\n radius=b, counter_bore_radius=2 * b, depth=10, counter_bore_depth=b\n )\n )\n\n:class:`~build_common.PolarLocations` creates a list of points that are radially distributed.\n\n.. _ex 14:","api_names":"BuildPart CounterBoreHole CounterSinkHole Cylinder faces Locations Plane PolarLocations sort_by","synonyms":"array bore drill pattern recessed fastener repeat"},"147":{"title":"14. Position on a line with '\\@', '\\%' and introduce Sweep","body":"build123d includes a feature for finding the position along a line segment. This\nis normalized between 0 and 1 and can be accessed using the :meth:`~topology.Mixin1D.position_at` (`@`) operator.\nSimilarly the :meth:`~topology.Mixin1D.tangent_at` (`%`) operator returns the line direction at a given point.\n\nThese two features are very powerful for chaining line segments together without\nhaving to repeat dimensions again and again, which is error prone, time\nconsuming, and more difficult to maintain. The pending faces must lie on the\npath, please see example 37 for a way to make this placement easier.\n\n\n.. image:: assets/general_ex14.svg\n :align: center\n\n* **Builder mode**\n\n The :meth:`~operations_generic.sweep` method takes any pending faces and sweeps them through the provided\n path (in this case the path is taken from the pending edges from ``ex14_ln``).\n :meth:`~operations_part.revolve` requires a single connected wire.\n\n .. code-block:: build123d\n\n a, b = 40, 20\n \n with BuildPart() as ex14:\n with BuildLine() as ex14_ln:\n l1 = JernArc(start=(0, 0), tangent=(0, 1), radius=a, arc_size=180)\n l2 = JernArc(start=l1 @ 1, tangent=l1 % 1, radius=a, arc_size=-90)\n l3 = Line(l2 @ 1, l2 @ 1 + (-a, a))\n with BuildSketch(Plane.XZ) as ex14_sk:\n Rectangle(b, b)\n sweep()\n\n* **Algebra mode**\n\n The :meth:`~operations_generic.sweep` method takes any faces and sweeps them through the provided\n path (in this case the path is taken from ``ex14_ln``).\n\n .. code-block:: build123d\n\n a, b = 40, 20\n \n l1 = JernArc(start=(0, 0), tangent=(0, 1), radius=a, arc_size=180)\n l2 = JernArc(start=l1 @ 1, tangent=l1 % 1, radius=a, arc_size=-90)\n l3 = Line(l2 @ 1, l2 @ 1 + (-a, a))\n ex14_ln = l1 + l2 + l3\n \n sk14 = Plane.XZ * Rectangle(b, b)\n ex14 = sweep(sk14, path=ex14_ln)\n\nIt is also possible to use tuple or :class:`~geometry.Vector` addition (and other vector math operations)\nas seen in the ``l3`` variable.\n\n.. _ex 15:","api_names":"addition BuildLine BuildPart BuildSketch ex14_ln JernArc l3 Line path position_at Rectangle revolve sweep tangent_at Vector","synonyms":"axisymmetric channel groove lathe path cut turned"},"148":{"title":"15. Mirroring Symmetric Geometry","body":"Here mirror is used on the BuildLine to create a symmetric shape with fewer line segment commands.\nAdditionally the '@' operator is used to simplify the line segment commands.\n\n``(l4 @ 1).Y`` is used to extract the y-component of the ``l4 @ 1`` vector.\n\n.. image:: assets/general_ex15.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n a, b, c = 80, 40, 20\n \n with BuildPart() as ex15:\n with BuildSketch() as ex15_sk:\n with BuildLine() as ex15_ln:\n l1 = Line((0, 0), (a, 0))\n l2 = Line(l1 @ 1, l1 @ 1 + (0, b))\n l3 = Line(l2 @ 1, l2 @ 1 + (-c, 0))\n l4 = Line(l3 @ 1, l3 @ 1 + (0, -c))\n l5 = Line(l4 @ 1, (0, (l4 @ 1).Y))\n mirror(ex15_ln.line, about=Plane.YZ)\n make_face()\n extrude(amount=c)\n\n* **Algebra mode**\n\n Combine lines via the pattern ``Curve() + [l1, l2, l3, l4, l5]``\n\n .. code-block:: build123d\n\n a, b, c = 80, 40, 20\n \n l1 = Line((0, 0), (a, 0))\n l2 = Line(l1 @ 1, l1 @ 1 + (0, b))\n l3 = Line(l2 @ 1, l2 @ 1 + (-c, 0))\n l4 = Line(l3 @ 1, l3 @ 1 + (0, -c))\n l5 = Line(l4 @ 1, (0, (l4 @ 1).Y))\n ln = Curve() + [l1, l2, l3, l4, l5]\n ln += mirror(ln, Plane.YZ)\n \n sk15 = make_face(ln)\n ex15 = extrude(sk15, c)\n\n.. _ex 16:","api_names":"BuildLine BuildPart BuildSketch Curve extrude l4 Line make_face mirror","synonyms":"reflect symmetry"},"149":{"title":"16. Mirroring 3D Objects","body":"Mirror can also be used with BuildPart (and BuildSketch) to mirror 3D objects.\nThe ``Plane.offset()`` method shifts the plane in the normal direction (positive or negative).\n\n.. image:: assets/general_ex16.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex16_single:\n with BuildSketch(Plane.XZ) as ex16_sk:\n Rectangle(length, width)\n fillet(ex16_sk.vertices(), radius=length / 10)\n with GridLocations(x_spacing=length / 4, y_spacing=0, x_count=3, y_count=1):\n Circle(length / 12, mode=Mode.SUBTRACT)\n Rectangle(length, width, align=(Align.MIN, Align.MIN), mode=Mode.SUBTRACT)\n extrude(amount=length)\n \n with BuildPart() as ex16:\n add(ex16_single.part)\n mirror(ex16_single.part, about=Plane.XY.offset(width))\n mirror(ex16_single.part, about=Plane.YX.offset(width))\n mirror(ex16_single.part, about=Plane.YZ.offset(width))\n mirror(ex16_single.part, about=Plane.YZ.offset(-width))\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n sk16 = Rectangle(length, width)\n sk16 = fillet(sk16.vertices(), length / 10)\n \n circles = [loc * Circle(length / 12) for loc in GridLocations(length / 4, 0, 3, 1)]\n \n sk16 = sk16 - circles - Rectangle(length, width, align=(Align.MIN, Align.MIN))\n ex16_single = extrude(Plane.XZ * sk16, length)\n \n planes = [\n Plane.XY.offset(width),\n Plane.YX.offset(width),\n Plane.YZ.offset(width),\n Plane.YZ.offset(-width),\n ]\n objs = [mirror(ex16_single, plane) for plane in planes]\n ex16 = ex16_single + objs\n\n\n.. _ex 17:","api_names":"add BuildPart BuildSketch Circle direction extrude fillet GridLocations mirror offset Rectangle vertices","synonyms":"array bevel edge channel fit gap groove hollow path cut pattern reflect repeat round edge shell symmetry tolerance wall thickness"},"150":{"title":"17. Mirroring From Faces","body":"Here we select the farthest face in the Y-direction and turn it into a :class:`~geometry.Plane` using the\n``Plane()`` class.\n\n.. image:: assets/general_ex17.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n a, b = 30, 20\n \n with BuildPart() as ex17:\n with BuildSketch() as ex17_sk:\n RegularPolygon(radius=a, side_count=5)\n extrude(amount=b)\n mirror(ex17.part, about=Plane(ex17.faces().group_by(Axis.Y)[0][0]))\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n a, b = 30, 20\n \n sk17 = RegularPolygon(radius=a, side_count=5)\n ex17 = extrude(sk17, amount=b)\n ex17 += mirror(ex17, Plane(ex17.faces().sort_by(Axis.Y).first))\n\n\n.. _ex 18:","api_names":"BuildPart BuildSketch extrude faces group_by mirror Plane RegularPolygon sort_by","synonyms":"reflect symmetry"},"151":{"title":"18. Creating Workplanes on Faces","body":"Here we start with an earlier example, select the top face, draw a rectangle and then use Extrude\nwith a negative distance.\n\n.. image:: assets/general_ex18.svg\n :align: center\n\n* **Builder mode**\n\n We then use ``Mode.SUBTRACT`` to cut it out from the main body.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n a, b = 4, 5\n \n with BuildPart() as ex18:\n Box(length, width, thickness)\n chamfer(ex18.edges().group_by(Axis.Z)[-1], length=a)\n fillet(ex18.edges().filter_by(Axis.Z), radius=b)\n with BuildSketch(ex18.faces().sort_by(Axis.Z)[-1]):\n Rectangle(2 * b, 2 * b)\n extrude(amount=-thickness, mode=Mode.SUBTRACT)\n\n* **Algebra mode**\n\n We then use ``-=`` to cut it out from the main body.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n a, b = 4, 5\n \n ex18 = Part() + Box(length, width, thickness)\n ex18 = chamfer(ex18.edges().group_by()[-1], a)\n ex18 = fillet(ex18.edges().filter_by(Axis.Z), b)\n \n sk18 = Plane(ex18.faces().sort_by().first) * Rectangle(2 * b, 2 * b)\n ex18 -= extrude(sk18, -thickness)\n\n\n.. _ex 19:","api_names":"Box BuildPart BuildSketch chamfer edges extrude faces fillet filter_by group_by Part Plane Rectangle sort_by SUBTRACT","synonyms":"bevel edge channel groove path cut round edge"},"152":{"title":"19. Locating a workplane on a vertex","body":"Here a face is selected and two different strategies are used to select vertices.\nFirstly ``vtx`` uses :meth:`~topology.ShapeList.group_by` and ``Axis.X`` to select a particular vertex. The second strategy uses a custom\ndefined Axis ``vtx2Axis`` that is pointing roughly in the direction of a vertex to select, and then :meth:`~topology.ShapeList.sort_by`\nthis custom Axis.\n\n.. image:: assets/general_ex19.svg\n :align: center\n\n* **Builder mode**\n\n Then the X and Y positions of these vertices are selected and passed to :class:`~build_common.Locations`\n as center points for two circles that cut through the main part. Note that if you passed the variable ``vtx`` directly to\n :class:`~build_common.Locations` then the part would be offset from the workplane by the vertex z-position.\n\n .. code-block:: build123d\n\n length, thickness = 80.0, 10.0\n \n with BuildPart() as ex19:\n with BuildSketch() as ex19_sk:\n RegularPolygon(radius=length / 2, side_count=7)\n extrude(amount=thickness)\n topf = ex19.faces().sort_by(Axis.Z)[-1]\n vtx = topf.vertices().group_by(Axis.X)[-1][0]\n vtx2Axis = Axis((0, 0, 0), (-1, -0.5, 0))\n vtx2 = topf.vertices().sort_by(vtx2Axis)[-1]\n with BuildSketch(topf) as ex19_sk2:\n with Locations((vtx.X, vtx.Y), (vtx2.X, vtx2.Y)):\n Circle(radius=length / 8)\n extrude(amount=-thickness, mode=Mode.SUBTRACT)\n\n* **Algebra mode**\n\n Then the X and Y positions of these vertices are selected and used to move two circles\n that cut through the main part. Note that if you passed the variable ``vtx`` directly to\n :class:`~geometry.Pos` then the part would be offset from the workplane by the vertex z-position.\n\n .. code-block:: build123d\n\n length, thickness = 80.0, 10.0\n \n ex19_sk = RegularPolygon(radius=length / 2, side_count=7)\n ex19 = extrude(ex19_sk, thickness)\n \n topf = ex19.faces().sort_by().last\n \n vtx = topf.vertices().group_by(Axis.X)[-1][0]\n \n vtx2Axis = Axis((0, 0, 0), (-1, -0.5, 0))\n vtx2 = topf.vertices().sort_by(vtx2Axis)[-1]\n \n ex19_sk2 = Circle(radius=length / 8)\n ex19_sk2 = Pos(vtx.X, vtx.Y) * ex19_sk2 + Pos(vtx2.X, vtx2.Y) * ex19_sk2\n \n ex19 -= extrude(ex19_sk2, thickness)\n\n\n.. _ex 20:","api_names":"Axis BuildPart BuildSketch Circle extrude faces group_by Locations Pos RegularPolygon sort_by vertices vtx vtx2Axis X","synonyms":"array channel fit gap groove hollow path cut pattern repeat shell tolerance wall thickness"},"153":{"title":"2. Plate with Hole","body":"A rectangular box, but with a hole added.\n\n.. image:: assets/general_ex2.svg\n :align: center\n\n* **Builder mode**\n\n In this case we are using\n :class:`~build_enums.Mode` ``.SUBTRACT`` to cut the :class:`~objects_part.Cylinder`\n from the :class:`~objects_part.Box`.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n center_hole_dia = 22.0\n \n with BuildPart() as ex2:\n Box(length, width, thickness)\n Cylinder(radius=center_hole_dia / 2, height=thickness, mode=Mode.SUBTRACT)\n\n* **Algebra mode**\n\n In this case we are using\n the subtract operator ``-`` to cut the :class:`~objects_part.Cylinder`\n from the :class:`~objects_part.Box`.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n center_hole_dia = 22.0\n \n ex2 = Box(length, width, thickness)\n ex2 -= Cylinder(center_hole_dia / 2, height=thickness)\n\n\n.. _ex 3:","api_names":"Box BuildPart Cylinder Mode","synonyms":"bore channel drill groove path cut recessed fastener"},"154":{"title":"20. Offset Sketch Workplane","body":"The ``plane`` variable is set to be coincident with the farthest face in the\nnegative x-direction. The resulting Plane is offset from the original position.\n\n.. image:: assets/general_ex20.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex20:\n Box(length, width, thickness)\n plane = Plane(ex20.faces().group_by(Axis.X)[0][0])\n with BuildSketch(plane.offset(2 * thickness)):\n Circle(width / 3)\n extrude(amount=width)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n ex20 = Box(length, width, thickness)\n plane = Plane(ex20.faces().sort_by(Axis.X).first).offset(2 * thickness)\n \n sk20 = plane * Circle(width / 3)\n ex20 += extrude(sk20, width)\n\n\n.. _ex 21:","api_names":"Box BuildPart BuildSketch Circle extrude faces group_by offset plane Plane sort_by","synonyms":"fit gap hollow shell tolerance wall thickness"},"155":{"title":"21. Create a Workplanes in the center of another shape","body":"One cylinder is created, and then the origin and z_dir of that part are used to create a new Plane for\npositioning another cylinder perpendicular and halfway along the first.\n\n.. image:: assets/general_ex21.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n width, length = 10.0, 60.0\n \n with BuildPart() as ex21:\n with BuildSketch() as ex21_sk:\n Circle(width / 2)\n extrude(amount=length)\n with BuildSketch(Plane(origin=ex21.part.center(), z_dir=(-1, 0, 0))):\n Circle(width / 2)\n extrude(amount=length)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n width, length = 10.0, 60.0\n \n ex21 = extrude(Circle(width / 2), length)\n plane = Plane(origin=ex21.center(), z_dir=(-1, 0, 0))\n ex21 += plane * extrude(Circle(width / 2), length)\n\n\n.. _ex 22:","api_names":"BuildPart BuildSketch center Circle extrude Plane","synonyms":""},"156":{"title":"22. Rotated Workplanes","body":"It is also possible to create a rotated workplane, building upon some of the concepts in an earlier\nexample.\n\n.. image:: assets/general_ex22.svg\n :align: center\n\n* **Builder mode**\n\n Use the :meth:`~geometry.Plane.rotated` method to rotate the workplane.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex22:\n Box(length, width, thickness)\n pln = Plane(ex22.faces().group_by(Axis.Z)[0][0]).rotated((0, -50, 0))\n with BuildSketch(pln) as ex22_sk:\n with GridLocations(length / 4, width / 4, 2, 2):\n Circle(thickness / 4)\n extrude(amount=-100, both=True, mode=Mode.SUBTRACT)\n\n* **Algebra mode**\n\n Use the operator ``*`` to relocate the plane (post-multiplication!).\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n ex22 = Box(length, width, thickness)\n plane = Plane((ex22.faces().group_by(Axis.Z)[0])[0]) * Rot(0, 50, 0)\n \n holes = Sketch() + [\n plane * loc * Circle(thickness / 4)\n for loc in GridLocations(length / 4, width / 4, 2, 2)\n ]\n ex22 -= extrude(holes, -100, both=True)\n\n:class:`~build_common.GridLocations` places 4 Circles on 4 points on this rotated workplane, and then the Circles are\nextruded in the \"both\" (positive and negative) normal direction.\n\n\n.. _ex 23:","api_names":"Box BuildPart BuildSketch Circle extrude faces GridLocations group_by plane Plane Rot rotated Sketch","synonyms":"array bore channel drill groove path cut pattern recessed fastener repeat"},"157":{"title":"23. Revolve","body":"Here we build a sketch with a :class:`~objects_curve.Polyline`,\n:class:`~objects_curve.Line`, and a :class:`~objects_sketch.Circle`. It is\nabsolutely critical that the sketch is only on one side of the axis of rotation\nbefore Revolve is called. To that end, ``split`` is used with ``Plane.ZY`` to keep\nonly one side of the Sketch.\n\nIt is highly recommended to view your sketch before you attempt to call revolve.\n\n.. image:: assets/general_ex23.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n pts = [\n (-25, 35),\n (-25, 0),\n (-20, 0),\n (-20, 5),\n (-15, 10),\n (-15, 35),\n ]\n \n with BuildPart() as ex23:\n with BuildSketch(Plane.XZ) as ex23_sk:\n with BuildLine() as ex23_ln:\n l1 = Polyline(pts)\n l2 = Line(l1 @ 1, l1 @ 0)\n make_face()\n with Locations((0, 35)):\n Circle(25)\n split(bisect_by=Plane.ZY)\n revolve(axis=Axis.Z)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n pts = [\n (-25, 35),\n (-25, 0),\n (-20, 0),\n (-20, 5),\n (-15, 10),\n (-15, 35),\n ]\n \n l1 = Polyline(pts)\n l2 = Line(l1 @ 1, l1 @ 0)\n sk23 = make_face([l1, l2])\n \n sk23 += Pos(0, 35) * Circle(25)\n sk23 = Plane.XZ * split(sk23, bisect_by=Plane.ZY)\n \n ex23 = revolve(sk23, Axis.Z)\n\n\n.. _ex 24:","api_names":"BuildLine BuildPart BuildSketch Circle Line Locations make_face Polyline Pos revolve split ZY","synonyms":"array axisymmetric cut in half lathe pattern repeat slice trim turned"},"158":{"title":"24. Loft","body":"Loft is a very powerful tool that can be used to join dissimilar shapes. In this case we make a\nconical-like shape from a circle and a rectangle that is offset vertically. In this case\n:meth:`~operations_part.loft` automatically takes the pending faces that were added by the two BuildSketches.\nLoft can behave unexpectedly when the input faces are not parallel to each other.\n\n.. image:: assets/general_ex24.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex24:\n Box(length, length, thickness)\n with BuildSketch(ex24.faces().group_by(Axis.Z)[0][0]) as ex24_sk:\n Circle(length / 3)\n with BuildSketch(ex24_sk.faces()[0].offset(length / 2)) as ex24_sk2:\n Rectangle(length / 6, width / 6)\n loft()\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n ex24 = Box(length, length, thickness)\n plane = Plane(ex24.faces().sort_by().last)\n \n faces = Sketch() + [\n plane * Circle(length / 3),\n plane.offset(length / 2) * Rectangle(length / 6, width / 6),\n ]\n \n ex24 += loft(faces)\n\n\n.. _ex 25:","api_names":"Box BuildPart BuildSketch Circle faces group_by loft offset Plane Rectangle Sketch sort_by","synonyms":"blend profiles cross sections fit gap hollow shell tolerance transition wall thickness"},"159":{"title":"25. Offset Sketch","body":".. image:: assets/general_ex25.svg\n :align: center\n\n* **Builder mode**\n\n BuildSketch faces can be transformed with a 2D :meth:`~operations_generic.offset`.\n\n .. code-block:: build123d\n\n rad, offs = 50, 10\n \n with BuildPart() as ex25:\n with BuildSketch() as ex25_sk1:\n RegularPolygon(radius=rad, side_count=5)\n with BuildSketch(Plane.XY.offset(15)) as ex25_sk2:\n RegularPolygon(radius=rad, side_count=5)\n offset(amount=offs)\n with BuildSketch(Plane.XY.offset(30)) as ex25_sk3:\n RegularPolygon(radius=rad, side_count=5)\n offset(amount=offs, kind=Kind.INTERSECTION)\n extrude(amount=1)\n\n* **Algebra mode**\n\n Sketch faces can be transformed with a 2D :meth:`~operations_generic.offset`.\n\n .. code-block:: build123d\n\n rad, offs = 50, 10\n \n sk25_1 = RegularPolygon(radius=rad, side_count=5)\n sk25_2 = Plane.XY.offset(15) * RegularPolygon(radius=rad, side_count=5)\n sk25_2 = offset(sk25_2, offs)\n sk25_3 = Plane.XY.offset(30) * RegularPolygon(radius=rad, side_count=5)\n sk25_3 = offset(sk25_3, offs, kind=Kind.INTERSECTION)\n \n sk25 = Sketch() + [sk25_1, sk25_2, sk25_3]\n ex25 = extrude(sk25, 1)\n\nThey can be offset inwards or outwards, and with different techniques for extending the\ncorners (see :class:`~build_enums.Kind` in the Offset docs).\n\n\n.. _ex 26:","api_names":"BuildPart BuildSketch corners extrude Kind offset RegularPolygon Sketch","synonyms":"fit gap hollow shell tolerance wall thickness"},"160":{"title":"26. Offset Part To Create Thin features","body":"Parts can also be transformed using an offset, but in this case with\na 3D :meth:`~operations_generic.offset`. Also commonly known as a shell, this allows creating thin walls\nusing very few operations. This can also be offset inwards or outwards. Faces can be selected to be\n\"deleted\" using the ``openings`` parameter of :meth:`~operations_generic.offset`.\n\nNote that self intersecting edges and/or faces can break both 2D and 3D offsets.\n\n.. image:: assets/general_ex26.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n length, width, thickness, wall = 80.0, 60.0, 10.0, 2.0\n \n with BuildPart() as ex26:\n Box(length, width, thickness)\n topf = ex26.faces().sort_by(Axis.Z)[-1]\n offset(amount=-wall, openings=topf)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n length, width, thickness, wall = 80.0, 60.0, 10.0, 2.0\n \n ex26 = Box(length, width, thickness)\n topf = ex26.faces().sort_by().last\n ex26 = offset(ex26, amount=-wall, openings=topf)\n\n\n.. _ex 27:","api_names":"Box BuildPart faces offset openings sort_by","synonyms":"fit gap hollow shell tolerance wall thickness"},"161":{"title":"27. Splitting an Object","body":"You can split an object using a plane, and retain either or both halves. In this case we select\na face and offset half the width of the box.\n\n.. image:: assets/general_ex27.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex27:\n Box(length, width, thickness)\n with BuildSketch(ex27.faces().sort_by(Axis.Z)[0]) as ex27_sk:\n Circle(width / 4)\n extrude(amount=-thickness, mode=Mode.SUBTRACT)\n split(bisect_by=Plane(ex27.faces().sort_by(Axis.Y)[-1]).offset(-width / 2))\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n ex27 = Box(length, width, thickness)\n sk27 = Plane(ex27.faces().sort_by().first) * Circle(width / 4)\n ex27 -= extrude(sk27, -thickness)\n ex27 = split(ex27, Plane(ex27.faces().sort_by(Axis.Y).last).offset(-width / 2))\n\n\n.. _ex 28:","api_names":"Box BuildPart BuildSketch Circle extrude faces offset Plane sort_by split","synonyms":"channel cut in half fit gap groove hollow path cut shell slice tolerance trim wall thickness"},"162":{"title":"28. Locating features based on Faces","body":".. image:: assets/general_ex28.svg\n :align: center\n\n* **Builder mode**\n\n We create a triangular prism with :class:`~build_enums.Mode` ``.PRIVATE`` and then later\n use the faces of this object to cut holes in a sphere.\n\n .. code-block:: build123d\n\n width, thickness = 80.0, 10.0\n \n with BuildPart() as ex28:\n with BuildSketch() as ex28_sk:\n RegularPolygon(radius=width / 4, side_count=3)\n ex28_ex = extrude(amount=thickness, mode=Mode.PRIVATE)\n midfaces = ex28_ex.faces().group_by(Axis.Z)[1]\n Sphere(radius=width / 2)\n for face in midfaces:\n with Locations(face):\n Hole(thickness / 2)\n\n* **Algebra mode**\n\n We create a triangular prism and then later use the faces of this object to cut holes in a sphere.\n\n .. code-block:: build123d\n\n width, thickness = 80.0, 10.0\n \n sk28 = RegularPolygon(radius=width / 4, side_count=3)\n tmp28 = extrude(sk28, thickness)\n ex28 = Sphere(radius=width / 2)\n for p in [Plane(face) for face in tmp28.faces().group_by(Axis.Z)[1]]:\n ex28 -= p * Hole(thickness / 2, depth=width)\n\nWe are able to create multiple workplanes by looping over the list of faces.\n\n\n.. _ex 29:","api_names":"BuildPart BuildSketch extrude faces group_by Hole Locations Mode Plane RegularPolygon Sphere","synonyms":"array bore drill pattern recessed fastener repeat"},"163":{"title":"29. The Classic OCC Bottle","body":"build123d is based on the OpenCascade.org (OCC) modeling Kernel. Those who are familiar with OCC\nknow about the famous ‘bottle’ example. We use a 3D Offset and the openings parameter to create\nthe bottle opening.\n\n.. image:: assets/general_ex29.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n L, w, t, b, h, n = 60.0, 18.0, 9.0, 0.9, 90.0, 6.0\n \n with BuildPart() as ex29:\n with BuildSketch(Plane.XY.offset(-b)) as ex29_ow_sk:\n with BuildLine() as ex29_ow_ln:\n l1 = Line((0, 0), (0, w / 2))\n l2 = ThreePointArc(l1 @ 1, (L / 2.0, w / 2.0 + t), (L, w / 2.0))\n l3 = Line(l2 @ 1, ((l2 @ 1).X, 0, 0))\n mirror(ex29_ow_ln.line)\n make_face()\n extrude(amount=h + b)\n fillet(ex29.edges(), radius=w / 6)\n with BuildSketch(ex29.faces().sort_by(Axis.Z)[-1]):\n Circle(t)\n extrude(amount=n)\n necktopf = ex29.faces().sort_by(Axis.Z)[-1]\n offset(ex29.solids()[0], amount=-b, openings=necktopf)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n L, w, t, b, h, n = 60.0, 18.0, 9.0, 0.9, 90.0, 8.0\n \n l1 = Line((0, 0), (0, w / 2))\n l2 = ThreePointArc(l1 @ 1, (L / 2.0, w / 2.0 + t), (L, w / 2.0))\n l3 = Line(l2 @ 1, ((l2 @ 1).X, 0, 0))\n ln29 = l1 + l2 + l3\n ln29 += mirror(ln29)\n sk29 = make_face(ln29)\n ex29 = extrude(sk29, -(h + b))\n ex29 = fillet(ex29.edges(), radius=w / 6)\n \n neck = Plane(ex29.faces().sort_by().last) * Circle(t)\n ex29 += extrude(neck, n)\n necktopf = ex29.faces().sort_by().last\n ex29 = offset(ex29, -b, openings=necktopf)\n\n\n.. _ex 30:","api_names":"BuildLine BuildPart BuildSketch Circle edges extrude faces fillet Line make_face mirror offset org Plane solids sort_by ThreePointArc","synonyms":"bevel edge fit gap hollow reflect round edge shell symmetry tolerance wall thickness"},"164":{"title":"3. An extruded prismatic solid","body":"Build a prismatic solid using extrusion.\n\n.. image:: assets/general_ex3.svg\n :align: center\n\n* **Builder mode**\n\n This time we can first create a 2D :class:`~build_sketch.BuildSketch` adding a\n :class:`~objects_sketch.Circle` and a subtracted :class:`~objects_sketch.Rectangle`\n and then use :class:`~build_part.BuildPart`'s :meth:`~operations_part.extrude` feature.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex3:\n with BuildSketch() as ex3_sk:\n Circle(width)\n Rectangle(length / 2, width / 2, mode=Mode.SUBTRACT)\n extrude(amount=2 * thickness)\n\n* **Algebra mode**\n\n This time we can first create a 2D :class:`~objects_sketch.Circle` with a subtracted\n :class:`~objects_sketch.Rectangle`` and then use the :meth:`~operations_part.extrude` operation for parts.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n sk3 = Circle(width) - Rectangle(length / 2, width / 2)\n ex3 = extrude(sk3, amount=2 * thickness)\n\n\n.. _ex 4:","api_names":"BuildPart BuildSketch Circle extrude Rectangle","synonyms":"channel groove path cut"},"165":{"title":"30. Bezier Curve","body":"Here ``pts`` is used as an input to both :class:`~objects_curve.Polyline` and\n:class:`~objects_curve.Bezier` and ``wts`` to Bezier alone. These two together\ncreate a closed line that is made into a face and extruded.\n\n.. image:: assets/general_ex30.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n pts = [\n (0, 0),\n (20, 20),\n (40, 0),\n (0, -40),\n (-60, 0),\n (0, 100),\n (100, 0),\n ]\n \n wts = [\n 1.0,\n 1.0,\n 2.0,\n 3.0,\n 4.0,\n 2.0,\n 1.0,\n ]\n \n with BuildPart() as ex30:\n with BuildSketch() as ex30_sk:\n with BuildLine() as ex30_ln:\n l0 = Polyline(pts)\n l1 = Bezier(pts, weights=wts)\n make_face()\n extrude(amount=10)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n pts = [\n (0, 0),\n (20, 20),\n (40, 0),\n (0, -40),\n (-60, 0),\n (0, 100),\n (100, 0),\n ]\n \n wts = [\n 1.0,\n 1.0,\n 2.0,\n 3.0,\n 4.0,\n 2.0,\n 1.0,\n ]\n \n ex30_ln = Polyline(pts) + Bezier(pts, weights=wts)\n ex30_sk = make_face(ex30_ln)\n ex30 = extrude(ex30_sk, -10)\n\n\n.. _ex 31:","api_names":"Bezier BuildLine BuildPart BuildSketch extrude make_face Polyline pts wts","synonyms":""},"166":{"title":"31. Nesting Locations","body":"Locations contexts can be nested to create groups of shapes. Here 24 triangles, 6 squares, and\n1 hexagon are created and then extruded. Notably :class:`~build_common.PolarLocations`\nrotates any \"children\" groups by default.\n\n.. image:: assets/general_ex31.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n a, b, c = 80.0, 5.0, 3.0\n \n with BuildPart() as ex31:\n with BuildSketch() as ex31_sk:\n with PolarLocations(a / 2, 6):\n with GridLocations(3 * b, 3 * b, 2, 2):\n RegularPolygon(b, 3)\n RegularPolygon(b, 4)\n RegularPolygon(3 * b, 6, rotation=30)\n extrude(amount=c)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n a, b, c = 80.0, 5.0, 3.0\n \n ex31 = Rot(Z=30) * RegularPolygon(3 * b, 6)\n ex31 += PolarLocations(a / 2, 6) * (\n RegularPolygon(b, 4) + GridLocations(3 * b, 3 * b, 2, 2) * RegularPolygon(b, 3)\n )\n ex31 = extrude(ex31, 3)\n\n\n.. _ex 32:","api_names":"BuildPart BuildSketch extrude GridLocations PolarLocations RegularPolygon Rot","synonyms":"array pattern repeat"},"167":{"title":"32. Python For-Loop","body":"In this example, a standard python for-loop is used along with a list of faces extracted from a sketch\nto progressively modify the extrusion amount. There are 7 faces in the sketch, so this results in 7\nseparate calls to :meth:`~operations_part.extrude`.\n\n.. image:: assets/general_ex32.svg\n :align: center\n\n* **Builder mode**\n\n :class:`~build_enums.Mode` ``.PRIVATE`` is used in :class:`~build_sketch.BuildSketch` to avoid\n adding these faces until the for-loop.\n\n .. code-block:: build123d\n\n a, b, c = 80.0, 10.0, 1.0\n \n with BuildPart() as ex32:\n with BuildSketch(mode=Mode.PRIVATE) as ex32_sk:\n RegularPolygon(2 * b, 6, rotation=30)\n with PolarLocations(a / 2, 6):\n RegularPolygon(b, 4)\n for idx, obj in enumerate(ex32_sk.sketch.faces()):\n add(obj)\n extrude(amount=c + 3 * idx)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n a, b, c = 80.0, 10.0, 1.0\n \n ex32_sk = RegularPolygon(2 * b, 6, rotation=30)\n ex32_sk += PolarLocations(a / 2, 6) * RegularPolygon(b, 4)\n ex32 = Part() + [extrude(obj, c + 3 * idx) for idx, obj in enumerate(ex32_sk.faces())]\n\n\n.. _ex 33:","api_names":"add BuildPart BuildSketch extrude faces Mode Part PolarLocations RegularPolygon","synonyms":"array pattern repeat"},"168":{"title":"33. Python Function and For-Loop","body":"Building on the previous example, a standard python function is used to return\na sketch as a function of several inputs to\nprogressively modify the size of each square.\n\n.. image:: assets/general_ex33.svg\n :align: center\n\n* **Builder mode**\n\n The function returns a :class:`~build_sketch.BuildSketch`.\n\n .. code-block:: build123d\n\n a, b, c = 80.0, 5.0, 1.0\n \n \n def square(rad, loc):\n with BuildSketch() as sk:\n with Locations(loc):\n RegularPolygon(rad, 4)\n return sk.sketch\n \n \n with BuildPart() as ex33:\n with BuildSketch(mode=Mode.PRIVATE) as ex33_sk:\n locs = PolarLocations(a / 2, 6)\n for i, j in enumerate(locs):\n add(square(b + 2 * i, j))\n for idx, obj in enumerate(ex33_sk.sketch.faces()):\n add(obj)\n extrude(amount=c + 2 * idx)\n\n* **Algebra mode**\n\n The function returns a ``Sketch`` object.\n\n .. code-block:: build123d\n\n a, b, c = 80.0, 5.0, 1.0\n \n \n def square(rad, loc):\n return loc * RegularPolygon(rad, 4)\n \n \n ex33 = Part() + [\n extrude(square(b + 2 * i, loc), c + 2 * i)\n for i, loc in enumerate(PolarLocations(a / 2, 6))\n ]\n\n\n.. _ex 34:","api_names":"add BuildPart BuildSketch extrude faces Locations Part PolarLocations RegularPolygon Sketch square","synonyms":"array pattern repeat"},"169":{"title":"34. Embossed and Debossed Text","body":".. image:: assets/general_ex34.svg\n :align: center\n\n* **Builder mode**\n\n The text \"Hello\" is placed on top of a rectangle and embossed (raised) by placing a BuildSketch on the\n top face (``topf``). Note that :class:`~build_enums.Align` is used to control the text placement. We re-use\n the ``topf`` variable to select the same face and deboss (indented) the text \"World\". Note that if we simply\n ran ``BuildSketch(ex34.faces().sort_by(Axis.Z)[-1])`` for both ``ex34_sk1 & 2`` it would incorrectly locate\n the 2nd \"World\" text on the top of the \"Hello\" text.\n\n .. code-block:: build123d\n\n length, width, thickness, fontsz, fontht = 80.0, 60.0, 10.0, 25.0, 4.0\n \n with BuildPart() as ex34:\n Box(length, width, thickness)\n topf = ex34.faces().sort_by(Axis.Z)[-1]\n with BuildSketch(topf) as ex34_sk:\n Text(\"Hello\", font_size=fontsz, align=(Align.CENTER, Align.MIN))\n extrude(amount=fontht)\n with BuildSketch(topf) as ex34_sk2:\n Text(\"World\", font_size=fontsz, align=(Align.CENTER, Align.MAX))\n extrude(amount=-fontht, mode=Mode.SUBTRACT)\n\n* **Algebra mode**\n\n The text \"Hello\" is placed on top of a rectangle and embossed (raised) by placing a sketch on the\n top face (``topf``). Note that :class:`~build_enums.Align` is used to control the text placement. We re-use\n the ``topf`` variable to select the same face and deboss (indented) the text \"World\".\n\n .. code-block:: build123d\n\n length, width, thickness, fontsz, fontht = 80.0, 60.0, 10.0, 25.0, 4.0\n \n ex34 = Box(length, width, thickness)\n plane = Plane(ex34.faces().sort_by().last)\n ex34_sk = plane * Text(\"Hello\", font_size=fontsz, align=(Align.CENTER, Align.MIN))\n ex34 += extrude(ex34_sk, amount=fontht)\n ex34_sk2 = plane * Text(\"World\", font_size=fontsz, align=(Align.CENTER, Align.MAX))\n ex34 -= extrude(ex34_sk2, amount=-fontht)\n\n\n.. _ex 35:","api_names":"Align Box BuildPart BuildSketch deboss embossed ex34_sk1 extrude face faces Plane sort_by Text topf","synonyms":"channel groove path cut"},"170":{"title":"35. Slots","body":".. image:: assets/general_ex35.svg\n :align: center\n\n* **Builder mode**\n\n Here we create a :class:`~objects_sketch.SlotCenterToCenter` and then use a\n :class:`~build_line.BuildLine` and :class:`~objects_curve.RadiusArc` to create an\n arc for two instances of :class:`~objects_sketch.SlotArc`.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex35:\n Box(length, length, thickness)\n topf = ex35.faces().sort_by(Axis.Z)[-1]\n with BuildSketch(topf) as ex35_sk:\n SlotCenterToCenter(width / 2, 10)\n with BuildLine(mode=Mode.PRIVATE) as ex35_ln:\n RadiusArc((-width / 2, 0), (0, width / 2), radius=width / 2)\n SlotArc(arc=ex35_ln.edges()[0], height=thickness, rotation=0)\n with BuildLine(mode=Mode.PRIVATE) as ex35_ln2:\n RadiusArc((0, -width / 2), (width / 2, 0), radius=-width / 2)\n SlotArc(arc=ex35_ln2.edges()[0], height=thickness, rotation=0)\n extrude(amount=-thickness, mode=Mode.SUBTRACT)\n\n* **Algebra mode**\n\n Here we create a :class:`~objects_sketch.SlotCenterToCenter` and then use\n a :class:`~objects_curve.RadiusArc` to create an arc for two instances of :class:`~operations_sketch.SlotArc`.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n ex35 = Box(length, length, thickness)\n plane = Plane(ex35.faces().sort_by().last)\n ex35_sk = SlotCenterToCenter(width / 2, 10)\n ex35_ln = RadiusArc((-width / 2, 0), (0, width / 2), radius=width / 2)\n ex35_sk += SlotArc(arc=ex35_ln.edges()[0], height=thickness)\n ex35_ln2 = RadiusArc((0, -width / 2), (width / 2, 0), radius=-width / 2)\n ex35_sk += SlotArc(arc=ex35_ln2.edges()[0], height=thickness)\n ex35 -= extrude(plane * ex35_sk, -thickness)\n\n\n.. _ex 36:","api_names":"Box BuildLine BuildPart BuildSketch edges extrude faces Plane RadiusArc SlotArc SlotCenterToCenter sort_by","synonyms":"channel groove path cut"},"171":{"title":"36. Extrude Until","body":"Sometimes you will want to extrude until a given face that could be non planar or\nwhere you might not know easily the distance you have to extrude to. In such\ncases you can use :meth:`~operations_part.extrude` :class:`~build_enums.Until`\nwith ``Until.NEXT`` or ``Until.LAST``.\n\n.. image:: assets/general_ex36.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n rad, rev = 6, 50\n \n with BuildPart() as ex36:\n with BuildSketch() as ex36_sk:\n with Locations((0, rev)):\n Circle(rad)\n revolve(axis=Axis.X, revolution_arc=180)\n with BuildSketch() as ex36_sk2:\n Rectangle(rad, rev)\n extrude(until=Until.NEXT)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n rad, rev = 6, 50\n \n ex36_sk = Pos(0, rev) * Circle(rad)\n ex36 = revolve(axis=Axis.X, profiles=ex36_sk, revolution_arc=180)\n ex36_sk2 = Rectangle(rad, rev)\n ex36 += extrude(ex36_sk2, until=Until.NEXT, target=ex36)","api_names":"BuildPart BuildSketch Circle extrude LAST Locations NEXT Pos Rectangle revolve Until","synonyms":"array axisymmetric lathe pattern repeat turned"},"172":{"title":"4. Building Profiles using lines and arcs","body":"Sometimes you need to build complex profiles using lines and arcs. This example\nbuilds a prismatic solid from 2D operations. It is not necessary to create\nvariables for the line segments, but it will be useful in a later example.\n\n.. image:: assets/general_ex4.svg\n :align: center\n\n* **Builder mode**\n\n :class:`~build_sketch.BuildSketch` operates on closed Faces, and the operation\n :meth:`~operations_sketch.make_face` is used to convert the pending line segments\n from :class:`~build_line.BuildLine` into a closed Face.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex4:\n with BuildSketch() as ex4_sk:\n with BuildLine() as ex4_ln:\n l1 = Line((0, 0), (length, 0))\n l2 = Line((length, 0), (length, width))\n l3 = ThreePointArc((length, width), (width, width * 1.5), (0.0, width))\n l4 = Line((0.0, width), (0, 0))\n make_face()\n extrude(amount=thickness)\n\n* **Algebra mode**\n\n We start with an empty :class:`~topology.Curve` and add lines to it (note that\n ``Curve() + [line1, line2, line3]`` is much more efficient than ``line1 + line2 + line3``,\n see :ref:`algebra_performance`).\n The operation :meth:`~operations_sketch.make_face` is used to convert the line\n segments into a Face.\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n lines = Curve() + [\n Line((0, 0), (length, 0)),\n Line((length, 0), (length, width)),\n ThreePointArc((length, width), (width, width * 1.5), (0.0, width)),\n Line((0.0, width), (0, 0)),\n ]\n sk4 = make_face(lines)\n ex4 = extrude(sk4, thickness)\n\nNote that to build a closed face it requires line segments that form a closed shape.\n\n.. _ex 5:","api_names":"BuildLine BuildPart BuildSketch Curve extrude it Line line1 make_face ThreePointArc","synonyms":""},"173":{"title":"5. Moving the current working point","body":".. image:: assets/general_ex5.svg\n :align: center\n\n* **Builder mode**\n\n Using :class:`~build_common.Locations` we can place one (or multiple) objects\n at one (or multiple) places.\n\n .. code-block:: build123d\n\n a, b, c, d = 90, 45, 15, 7.5\n \n with BuildPart() as ex5:\n with BuildSketch() as ex5_sk:\n Circle(a)\n with Locations((b, 0.0)):\n Rectangle(c, c, mode=Mode.SUBTRACT)\n with Locations((0, b)):\n Circle(d, mode=Mode.SUBTRACT)\n extrude(amount=c)\n\n* **Algebra mode**\n\n Using the pattern ``Pos(x, y, z=0) * obj`` (with :class:`geometry.Pos`) we can move an\n object to the provided position. Using ``Rot(x_angle, y_angle, z_angle) * obj``\n (with :class:`geometry.Rot`) would rotate the object.\n\n .. code-block:: build123d\n\n a, b, c, d = 90, 45, 15, 7.5\n \n sk5 = Circle(a) - Pos(b, 0.0) * Rectangle(c, c) - Pos(0.0, b) * Circle(d)\n ex5 = extrude(sk5, c)\n\n\n.. _ex 6:","api_names":"BuildPart BuildSketch Circle extrude Locations one Pos Rectangle Rot","synonyms":"array channel groove path cut pattern repeat"},"174":{"title":"6. Using Point Lists","body":"Sometimes you need to create a number of features at various\n:class:`~build_common.Locations`.\n\n.. image:: assets/general_ex6.svg\n :align: center\n\n* **Builder mode**\n\n You can use a list of points to construct multiple objects at once.\n\n .. code-block:: build123d\n\n a, b, c = 80, 60, 10\n \n with BuildPart() as ex6:\n with BuildSketch() as ex6_sk:\n Circle(a)\n with Locations((b, 0), (0, b), (-b, 0), (0, -b)):\n Circle(c, mode=Mode.SUBTRACT)\n extrude(amount=c)\n\n* **Algebra mode**\n\n You can use loops to iterate over these Locations\n or list comprehensions as in the example.\n\n The algebra operations are vectorized, which means ``obj - [obj1, obj2, obj3]``\n is short for ``obj - obj1 - obj2 - ob3`` (and more efficient, see :ref:`algebra_performance`).\n\n .. code-block:: build123d\n\n a, b, c = 80, 60, 10\n \n sk6 = [loc * Circle(c) for loc in Locations((b, 0), (0, b), (-b, 0), (0, -b))]\n ex6 = extrude(Circle(a) - sk6, c)\n\n\n.. _ex 7:","api_names":"BuildPart BuildSketch Circle extrude Locations obj","synonyms":"array channel groove path cut pattern repeat"},"175":{"title":"7. Polygons","body":".. image:: assets/general_ex7.svg\n :align: center\n\n* **Builder mode**\n\n You can create :class:`~objects_sketch.RegularPolygon` for each stack point if\n you would like.\n\n .. code-block:: build123d\n\n a, b, c = 60, 80, 5\n \n with BuildPart() as ex7:\n with BuildSketch() as ex7_sk:\n Rectangle(a, b)\n with Locations((0, 3 * c), (0, -3 * c)):\n RegularPolygon(radius=2 * c, side_count=6, mode=Mode.SUBTRACT)\n extrude(amount=c)\n\n* **Algebra mode**\n\n You can apply locations to :class:`~objects_sketch.RegularPolygon` instances\n for each location via loops or list comprehensions.\n\n .. code-block:: build123d\n\n a, b, c = 60, 80, 5\n \n polygons = [\n loc * RegularPolygon(radius=2 * c, side_count=6)\n for loc in Locations((0, 3 * c), (0, -3 * c))\n ]\n sk7 = Rectangle(a, b) - polygons\n ex7 = extrude(sk7, amount=c)\n\n\n.. _ex 8:","api_names":"BuildPart BuildSketch extrude Locations Rectangle RegularPolygon","synonyms":"array channel groove path cut pattern repeat"},"176":{"title":"8. Polylines","body":":class:`~objects_curve.Polyline` allows creating a shape from a large number\nof chained points connected by lines. This example uses a polyline to create\none half of an i-beam shape, which is :meth:`~operations_generic.mirror` ed to\ncreate the final profile.\n\n.. image:: assets/general_ex8.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n (L, H, W, t) = (100.0, 20.0, 20.0, 1.0)\n pts = [\n (0, H / 2.0),\n (W / 2.0, H / 2.0),\n (W / 2.0, (H / 2.0 - t)),\n (t / 2.0, (H / 2.0 - t)),\n (t / 2.0, (t - H / 2.0)),\n (W / 2.0, (t - H / 2.0)),\n (W / 2.0, H / -2.0),\n (0, H / -2.0),\n ]\n \n with BuildPart() as ex8:\n with BuildSketch(Plane.YZ) as ex8_sk:\n with BuildLine() as ex8_ln:\n Polyline(pts)\n mirror(ex8_ln.line, about=Plane.YZ)\n make_face()\n extrude(amount=L)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n (L, H, W, t) = (100.0, 20.0, 20.0, 1.0)\n pts = [\n (0, H / 2.0),\n (W / 2.0, H / 2.0),\n (W / 2.0, (H / 2.0 - t)),\n (t / 2.0, (H / 2.0 - t)),\n (t / 2.0, (t - H / 2.0)),\n (W / 2.0, (t - H / 2.0)),\n (W / 2.0, H / -2.0),\n (0, H / -2.0),\n ]\n \n ln = Polyline(pts)\n ln += mirror(ln, Plane.YZ)\n \n sk8 = make_face(Plane.YZ * ln)\n ex8 = extrude(sk8, -L).clean()\n\n\n.. _ex 9:","api_names":"build123d BuildLine BuildPart BuildSketch clean extrude make_face mirror Polyline","synonyms":"reflect symmetry"},"177":{"title":"9. Selectors, Fillets, and Chamfers","body":"This example introduces multiple useful and important concepts. Firstly :meth:`~operations_generic.chamfer`\nand :meth:`~operations_generic.fillet` can be used to \"bevel\" and \"round\" edges respectively. Secondly,\nthese two methods require an edge or a list of edges to operate on. To select all\nedges, you could simply pass in ``ex9.edges()``.\n\n.. image:: assets/general_ex9.svg\n :align: center\n\n* **Builder mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n with BuildPart() as ex9:\n Box(length, width, thickness)\n chamfer(ex9.edges().group_by(Axis.Z)[-1], length=4)\n fillet(ex9.edges().filter_by(Axis.Z), radius=5)\n\n* **Algebra mode**\n\n .. code-block:: build123d\n\n length, width, thickness = 80.0, 60.0, 10.0\n \n ex9 = Part() + Box(length, width, thickness)\n ex9 = chamfer(ex9.edges().group_by(Axis.Z)[-1], length=4)\n ex9 = fillet(ex9.edges().filter_by(Axis.Z), radius=5)\n\nNote that :meth:`~topology.ShapeList.group_by` ``(Axis.Z)`` returns a list of lists of edges that is grouped by\ntheir z-position. In this case we want to use the ``[-1]`` group which, by convention, will\nbe the highest z-dimension group.\n\n\n.. _ex 10:","api_names":"Box BuildPart chamfer edges fillet filter_by group_by Part","synonyms":"bevel edge round edge"},"178":{"title":"Introductory Examples","body":"The examples on this page can help you learn how to build objects with build123d, and are intended as a general overview of build123d.\n\nThey are organized from simple to complex, so working through them in order is the best way to absorb them.\n\n.. note::\n\n Some important lines are omitted below to save space, so you will most likely need to add 1 & 2 to the provided code below for them to work:\n\n 1. ``from build123d import *``\n 2. If you are using build123d *builder mode* or *algebra mode*,\n\n - in *ocp_vscode* simply use e.g. ``show(ex15)`` to the end of your design to view parts, sketches and curves. ``show_all()`` can be used to automatically show all objects with their variable names as labels.\n - in *CQ-editor* add e.g. ``show_object(ex15.part)``, ``show_object(ex15.sketch)`` or ``show_object(ex15.line)`` to the end of your design to view parts, sketches or lines.\n\n 3. If you want to save your resulting object as an STL from *builder mode*, you can use e.g. ``export_stl(ex15.part, \"file.stl\")``.\n 4. If you want to save your resulting object as an STL from *algebra mode*, you can use e.g. ``export_stl(ex15, \"file.stl\")``\n 5. build123d also supports exporting to multiple other file formats including STEP, see here for further information: `Import/Export Formats `_\n\n.. contents:: List of Examples\n :backlinks: entry\n\n.. _ex 1:","api_names":"export_stl from show show_all show_object","synonyms":""},"179":{"title":"Ball Joint","body":"A component rotates around all 3 axes using a gimbal system (3 nested rotations). A :class:`~joints.BallJoint`\nis found within a rod end as shown here:\n\n.. image:: assets/rod_end.png\n\n.. code-block:: build123d\n\n from build123d import *\n from bd_warehouse.thread import IsoThread\n from ocp_vscode import *\n \n # Create the thread so the min radius is available below\n thread = IsoThread(major_diameter=6, pitch=1, length=20, end_finishes=(\"fade\", \"raw\"))\n inner_radius = 15.89 / 2\n inner_gap = 0.2\n \n with BuildPart() as rod_end:\n # Create the outer shape\n with BuildSketch():\n Circle(22.25 / 2)\n with Locations((0, -12)):\n Rectangle(8, 1)\n make_hull()\n split(bisect_by=Plane.YZ)\n revolve(axis=Axis.Y)\n # Refine the shape\n with BuildSketch(Plane.YZ) as s2:\n Rectangle(25, 8, align=(Align.MIN, Align.CENTER))\n Rectangle(9, 10, align=(Align.MIN, Align.CENTER))\n chamfer(s2.vertices(), 0.5)\n revolve(axis=Axis.Z, mode=Mode.INTERSECT)\n # Add the screw shaft\n Cylinder(\n thread.min_radius,\n 30,\n rotation=(90, 0, 0),\n align=(Align.CENTER, Align.CENTER, Align.MIN),\n )\n # Cutout the ball socket\n Sphere(inner_radius, mode=Mode.SUBTRACT)\n # Add thread\n with Locations((0, -30, 0)):\n add(thread, rotation=(-90, 0, 0))\n # Create the ball joint\n BallJoint(\n \"socket\",\n joint_location=Location(),\n angular_range=((-14, 14), (-14, 14), (0, 360)),\n )\n \n with BuildPart() as ball:\n Sphere(inner_radius - inner_gap)\n Box(50, 50, 13, mode=Mode.INTERSECT)\n Hole(4)\n ball.part.color = Color(\"aliceblue\")\n RigidJoint(\"ball\", joint_location=Location())\n \n rod_end.part.joints[\"socket\"].connect_to(ball.part.joints[\"ball\"], angles=(5, 10, 0))\n \n show(rod_end.part, ball.part, s2)\n \n\nNote how limits are defined during the instantiation of the ball joint when ensures that the pin or bolt\nwithin the rod end does not interfere with the rod end itself. The ``connect_to`` sets the three angles\n(only two are significant in this example).\n\n.. autoclass:: BallJoint\n\n..\n :exclude-members: connect_to\n\n .. method:: connect_to(other: RigidJoint, *, angles: RotationLike = None)\n\n Connect a ``BallJoint`` to a ``RigidJoint``","api_names":"add angles BallJoint Box BuildPart BuildSketch chamfer Circle Color connect_to Cylinder Hole IsoThread Location Locations make_hull Rectangle revolve RigidJoint show Sphere split system vertices","synonyms":"array axisymmetric bevel edge bore channel cut in half drill groove lathe path cut pattern recessed fastener repeat round edge slice trim turned"},"180":{"title":"Cylindrical Joint","body":"A :class:`~joints.CylindricalJoint` allows a component to rotate around and moves along a single axis\nlike a screw combining the functionality of a :class:`~joints.LinearJoint` and a\n:class:`~joints.RevoluteJoint` joint. The ``connect_to`` for these joints have both ``position`` and\n``angle`` parameters as shown below extracted from the joint tutorial.\n\n\n.. code-block::python\n\n hinge_outer.joints[\"hole2\"].connect_to(m6_joint, position=5 * MM, angle=30)\n\n.. autoclass:: CylindricalJoint\n\n..\n :exclude-members: connect_to\n\n .. method:: connect_to(other: RigidJoint, *, position: float = None, angle: float = None)\n\n Connect the ``CylindricalJoint`` to a ``RigidJoint``","api_names":"angle connect_to CylindricalJoint LinearJoint position RevoluteJoint RigidJoint","synonyms":"bore drill recessed fastener"},"181":{"title":"Joints","body":":class:`~topology.Joint`'s enable Solid and Compound objects to be arranged\nrelative to each other in an intuitive manner - with the same degree of motion\nthat is found with the equivalent physical joints. :class:`~topology.Joint`'s always work\nin pairs - a :class:`~topology.Joint` can only be connected to another :class:`~topology.Joint` as follows:\n\n+---------------------------------------+---------------------------------------------------------------------+--------------------+\n| :class:`~topology.Joint` | connect_to | Example |\n+=======================================+=====================================================================+====================+\n| :class:`~joints.BallJoint` | :class:`~joints.RigidJoint` | Gimbal |\n+---------------------------------------+---------------------------------------------------------------------+--------------------+\n| :class:`~joints.CylindricalJoint` | :class:`~joints.RigidJoint` | Screw |\n+---------------------------------------+---------------------------------------------------------------------+--------------------+\n| :class:`~joints.LinearJoint` | :class:`~joints.RigidJoint`, :class:`~joints.RevoluteJoint` | Slider or Pin Slot |\n+---------------------------------------+---------------------------------------------------------------------+--------------------+\n| :class:`~joints.RevoluteJoint` | :class:`~joints.RigidJoint` | Hinge |\n+---------------------------------------+---------------------------------------------------------------------+--------------------+\n| :class:`~joints.RigidJoint` | :class:`~joints.RigidJoint` | Fixed |\n+---------------------------------------+---------------------------------------------------------------------+--------------------+\n\nObjects may have many joints bound to them each with an identifying label. All :class:`~topology.Joint`\nobjects have a ``symbol`` property that can be displayed to help visualize\ntheir position and orientation (the `ocp-vscode `_ viewer\nhas built-in support for displaying joints).\n\n.. note::\n If joints are created within the scope of a :class:`~build_part.BuildPart` builder, the ``to_part``\n parameter need not be specified as the builder will, on exit, automatically transfer the joints created in its\n scope to the part created.\n\nThe following sections provide more detail on the available joints and describes how they are used.\n\n.. py:module:: joints","api_names":"BallJoint BuildPart CylindricalJoint Joint LinearJoint orientation RevoluteJoint RigidJoint symbol to_part","synonyms":""},"182":{"title":"Linear Joint","body":"Component moves along a single axis as with a sliding latch shown here:\n\n.. image:: assets/joint-latch-slide.png\n\nThe code to generate these components follows:\n\n.. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import *\n \n with BuildPart() as latch:\n # Basic box shape to start with filleted corners\n Box(70, 30, 14)\n end = latch.faces().sort_by(Axis.X)[-1] # save the end with the hole\n fillet(latch.edges().filter_by(Axis.Z), 2)\n fillet(latch.edges().sort_by(Axis.Z)[-1], 1)\n # Make screw tabs\n with BuildSketch(latch.faces().sort_by(Axis.Z)[0]) as l4:\n with Locations((-30, 0), (30, 0)):\n SlotOverall(50, 10, rotation=90)\n Rectangle(50, 30)\n fillet(l4.vertices(Select.LAST), radius=2)\n extrude(amount=-2)\n with GridLocations(60, 40, 2, 2):\n Hole(2)\n # Create the hole from the end saved previously\n with BuildSketch(end) as slide_hole:\n add(end)\n offset(amount=-2)\n fillet(slide_hole.vertices(), 1)\n extrude(amount=-68, mode=Mode.SUBTRACT)\n # Slot for the handle to slide in\n with BuildSketch(latch.faces().sort_by(Axis.Z)[-1]):\n SlotOverall(32, 8)\n extrude(amount=-2, mode=Mode.SUBTRACT)\n # The slider will move align the x axis 12mm in each direction\n LinearJoint(\"latch\", axis=Axis.X, linear_range=(-12, 12))\n \n with BuildPart() as slide:\n # The slide will be a little smaller than the hole\n with BuildSketch() as s1:\n add(slide_hole.sketch)\n offset(amount=-0.25)\n # The extrusions aren't symmetric\n extrude(amount=46)\n extrude(slide.faces().sort_by(Axis.Z)[0], amount=20)\n # Round off the ends\n fillet(slide.edges().group_by(Axis.Z)[0], 1)\n fillet(slide.edges().group_by(Axis.Z)[-1], 1)\n # Create the knob\n with BuildSketch() as s2:\n with Locations((12, 0)):\n SlotOverall(15, 4, rotation=90)\n Rectangle(12, 7, align=(Align.MIN, Align.CENTER))\n fillet(s2.vertices(Select.LAST), 1)\n split(bisect_by=Plane.XZ)\n revolve(axis=Axis.X)\n # Align the joint to Plane.ZY flipped\n RigidJoint(\"slide\", joint_location=Location(-Plane.ZY))\n \n # Position the slide in the latch: -12 >= position <= 12\n latch.part.joints[\"latch\"].connect_to(slide.part.joints[\"slide\"], position=12)\n \n # show(latch.part, render_joints=True)\n # show(slide.part, render_joints=True)\n show(latch.part, slide.part, render_joints=True)\n \n\n.. image:: assets/joint-latch.png\n :width: 65 %\n.. image:: assets/joint-slide.png\n :width: 27.5 %\n\nNote how the slide is constructed in a different orientation than the direction of motion. The\nthree highlighted lines of code show how the joints are created and connected together:\n\n* The :class:`~joints.LinearJoint` has an axis and limits of movement\n* The :class:`~joints.RigidJoint` has a single location, orientated such that the knob will ultimately be \"up\"\n* The ``connect_to`` specifies a position that must be within the predefined limits.\n\nThe slider can be moved back and forth by just changing the ``position`` value. Values outside\nof the limits will raise an exception.\n\n.. autoclass:: LinearJoint\n\n..\n :exclude-members: connect_to\n\n .. method:: connect_to(other: RevoluteJoint, *, position: float = None, angle: float = None)\n .. method:: connect_to(other: RigidJoint, *, position: float = None)\n :noindex:\n\n Connect the ``LinearJoint`` to either a ``RevoluteJoint`` or ``RigidJoint``","api_names":"add Box BuildPart BuildSketch connect_to edges extrude faces fillet filter_by GridLocations group_by Hole LinearJoint Location Locations offset position Rectangle RevoluteJoint revolve RigidJoint show SlotOverall sort_by split vertices","synonyms":"array axisymmetric bevel edge bore channel cut in half drill fit gap groove hollow lathe path cut pattern recessed fastener repeat round edge shell slice tolerance trim turned wall thickness"},"183":{"title":"Revolute Joint","body":"Component rotates around axis like a hinge. The :ref:`joint_tutorial` covers Revolute Joints in detail.\n\nDuring instantiation of a :class:`~joints.RevoluteJoint` there are three parameters not present with\nRigid Joints: ``axis``, ``angle_reference``, and ``range`` that allow the circular motion to be fully\ndefined.\n\nWhen :meth:`~topology.Joint.connect_to` with a Revolute Joint, an extra ``angle`` parameter is present\nwhich allows one to change the relative position of joined parts by changing a single value.\n\n.. autoclass:: RevoluteJoint\n\n..\n :exclude-members: connect_to\n\n .. method:: connect_to(other: RigidJoint, *, angle: float = None)\n\n Connect the ``RevoluteJoint`` to a ``RigidJoint``","api_names":"angle angle_reference axis connect_to RevoluteJoint RigidJoint","synonyms":""},"184":{"title":"Rigid Joint","body":"A rigid joint positions two components relative to each another with no freedom of movement. When a\n:class:`~joints.RigidJoint` is instantiated it's assigned a ``label``, a part to bind to (``to_part``),\nand a ``joint_location`` which defines both the position and orientation of the joint (see\n:class:`~geometry.Location`) - as follows:\n\n.. code-block:: build123d\n\n RigidJoint(label=\"outlet\", to_part=pipe, joint_location=path.location_at(1))\n\nOnce a joint is bound to a part this way, the :meth:`~topology.Joint.connect_to` method can be used to\nrepositioning another part relative to ``self`` which stay fixed - as follows:\n\n.. code-block:: build123d\n\n pipe.joints[\"outlet\"].connect_to(flange_outlet.joints[\"pipe\"])\n\n.. note::\n Within a part all of the joint labels must be unique.\n\nThe :meth:`~topology.Joint.connect_to` method only does a one time re-position of a part and does not\nbind them in any way; however, putting them into an :ref:`assembly` will maintain there relative locations\nas will combining parts with boolean operations or within a :class:`~build_part.BuildPart` context.\n\nAs a example of creating parts with joints and connecting them together, consider the following code where\nflanges are attached to the ends of a curved pipe:\n\n.. image:: assets/rigid_joints_pipe.png\n\n.. code-block:: build123d\n\n import copy\n from build123d import *\n from bd_warehouse.flange import WeldNeckFlange\n from bd_warehouse.pipe import PipeSection\n from ocp_vscode import *\n \n flange_inlet = WeldNeckFlange(nps=\"10\", flange_class=300)\n flange_outlet = copy.copy(flange_inlet)\n \n with BuildPart() as pipe_builder:\n # Create the pipe\n with BuildLine():\n path = TangentArc((0, 0, 0), (2 * FT, 0, 1 * FT), tangent=(1, 0, 0))\n with BuildSketch(Plane(origin=path @ 0, z_dir=path % 0)):\n PipeSection(\"10\", material=\"stainless\", identifier=\"40S\")\n sweep()\n \n # Add the joints\n RigidJoint(label=\"inlet\", joint_location=-path.location_at(0))\n RigidJoint(label=\"outlet\", joint_location=path.location_at(1))\n \n # Place the flanges at the ends of the pipe\n pipe_builder.part.joints[\"inlet\"].connect_to(flange_inlet.joints[\"pipe\"])\n pipe_builder.part.joints[\"outlet\"].connect_to(flange_outlet.joints[\"pipe\"])\n \n show(pipe_builder, flange_inlet, flange_outlet, render_joints=True)\n \n\nNote how the locations of the joints are determined by the :meth:`~topology.Mixin1D.location_at` method\nand how the ``-`` negate operator is used to reverse the direction of the location without changing its\nposition. Also note that the ``WeldNeckFlange`` class predefines two joints, one at the pipe end and\none at the face end - both of which are shown in the above image (generated by ocp-vscode with the\n``render_joints=True`` flag set in the ``show`` function).\n\n\n.. autoclass:: RigidJoint\n\n..\n :exclude-members: connect_to\n\n .. method:: connect_to(other: BallJoint, *, angles: RotationLike = None)\n .. method:: connect_to(other: CylindricalJoint, *, position: float = None, angle: float = None)\n :noindex:\n .. method:: connect_to(other: LinearJoint, *, position: float = None)\n :noindex:\n .. method:: connect_to(other: RevoluteJoint, *, angle: float = None)\n :noindex:\n .. method:: connect_to(other: RigidJoint)\n :noindex:\n\n Connect the ``RigidJoint`` to another Joint.\n..","api_names":"BuildLine BuildPart BuildSketch connect_to copy image joint joint_location label Location location_at PipeSection Plane render_joints RigidJoint self show sweep TangentArc to to_part WeldNeckFlange","synonyms":"array channel groove path cut pattern repeat"},"185":{"title":"Combing both concepts","body":"**Object arithmetic** and **Placement at locations** can be combined:\n\n .. code-block:: build123d\n\n b = Plane.XZ * Rot(X=30) * Box(1, 2, 3) + Plane.YZ * Pos(X=-1) * Cylinder(0.2, 5)\n\n**Note:** In Python ``*`` binds stronger then ``+``, ``-``, ``&``, hence brackets are not needed.","api_names":"Box Cylinder Pos Rot","synonyms":"array pattern repeat"},"186":{"title":"Key Concepts (algebra mode)","body":"Build123d's algebra mode works on objects of the classes ``Shape``, ``Part``, ``Sketch`` and ``Curve`` and is based on two concepts:\n\n1. **Object arithmetic**\n2. **Placement arithmetic**","api_names":"Concepts Curve Part Shape Sketch","synonyms":""},"187":{"title":"Object arithmetic","body":"- Creating a box and a cylinder centered at ``(0, 0, 0)``\n\n .. code-block:: build123d\n\n b = Box(1, 2, 3)\n c = Cylinder(0.2, 5)\n\n- Fusing a box and a cylinder\n\n .. code-block:: build123d\n\n r = Box(1, 2, 3) + Cylinder(0.2, 5)\n\n- Cutting a cylinder from a box\n\n .. code-block:: build123d\n\n r = Box(1, 2, 3) - Cylinder(0.2, 5)\n\n- Intersecting a box and a cylinder\n\n .. code-block:: build123d\n\n r = Box(1, 2, 3) & Cylinder(0.2, 5)\n\n**Notes:**\n\n* `b`, `c` and `r` are instances of class ``Compound`` and can be viewed with every viewer that can show ``build123d.Compound`` objects.\n* A discussion around performance can be found in :ref:`algebra_performance`.\n* A mathematically formal definition of the algebra can be found in :ref:`algebra_definition`.","api_names":"Box Compound Cylinder","synonyms":""},"188":{"title":"Placement arithmetic","body":"A ``Part``, ``Sketch`` or ``Curve`` does not have any location or rotation parameter.\nThe rationale is that an object defines its topology (shape, sizes and its center), but does not know \nwhere in space it will be located. Instead, it will be relocated with the ``*`` operator onto a plane \nand to location relative to the plane (similar ``moved``). \n\nThe generic forms of object placement are:\n\n1. Placement on ``plane`` or at ``location`` relative to XY plane:\n\n .. code-block:: build123d\n\n plane * alg_compound\n location * alg_compound\n\n2. Placement on the ``plane`` and then moved relative to the ``plane`` by ``location`` \n(the location is relative to the local coordinate system of the plane).\n\n .. code-block:: build123d\n\n plane * location * alg_compound\n\n\nDetails can be found in :ref:`location_arithmetics`.\n\nExamples:\n\n- Box on the ``XY`` plane, centered at `(0, 0, 0)` (both forms are equivalent):\n\n .. code-block:: build123d\n\n Plane.XY * Box(1, 2, 3)\n\n Box(1, 2, 3)\n\n Note: On the ``XY`` plane no placement is needed (mathematically ``Plane.XY *`` will not change the \n location of an object).\n\n- Box on the ``XY`` plane centered at `(0, 1, 0)` (all three are equivalent):\n\n .. code-block:: build123d\n\n Plane.XY * Pos(0, 1, 0) * Box(1, 2, 3)\n\n Pos(0, 1, 0) * Box(1, 2, 3) \n\n Pos(Y=1) * Box(1, 2, 3)\n\n Note: Again, ``Plane.XY`` can be omitted.\n\n- Box on plane ``Plane.XZ``:\n\n .. code-block:: build123d\n\n Plane.XZ * Box(1, 2, 3)\n\n- Box on plane ``Plane.XZ`` with a location ``(X=1, Y=2, Z=3)`` relative to the ``XZ`` plane, i.e., \n using the x-, y- and z-axis of the ``XZ`` plane:\n\n .. code-block:: build123d\n\n Plane.XZ * Pos(1, 2, 3) * Box(1, 2, 3)\n\n- Box on plane ``Plane.XZ`` moved to ``(X=1, Y=2, Z=3)`` relative to this plane and rotated there \n by the angles `(X=0, Y=100, Z=45)` around ``Plane.XZ`` axes:\n\n .. code-block:: build123d\n\n Plane.XZ * Pos(1, 2, 3) * Rot(0, 100, 45) * Box(1, 2, 3)\n\n Location((1, 2, 3), (0, 100, 45)) * Box(1, 2, 3)\n\n Note: ``Pos * Rot`` is the same as using ``Location`` directly\n\n- Box on plane ``Plane.XZ`` rotated on this plane by the angles ``(X=0, Y=100, Z=45)`` (using the \n x-, y- and z-axis of the ``XZ`` plane) and then moved to ``(X=1, Y=2, Z=3)`` relative to the ``XZ`` plane:\n\n .. code-block:: build123d\n\n Plane.XZ * Rot(0, 100, 45) * Pos(0,1,2) * Box(1, 2, 3)","api_names":"Box Curve location Location moved needed Part plane Pos Rot Sketch topology XY XZ","synonyms":""},"189":{"title":"Analogy: Adding Numbers on Paper","body":"Think of the Builder as a running tally when adding numbers on a piece of paper:\n\n- Each number represents an operation or object.\n- The ``+`` or ``-`` sign corresponds to the **ADD** or **SUBTRACT** mode.\n- At the end, the total is the sum of all operations, which you can retrieve by referencing \n the Builder’s output.\n\nBy adopting this approach, build123d ensures a natural, intuitive workflow for constructing \n2D and 3D models.\n\n.. note::\n **Why modifying objects directly doesn't work in Builder mode**\n\n A common mistake in Builder mode is attempting to modify an object after it is created:\n\n .. code-block:: build123d\n\n with BuildPart() as invalid:\n Cylinder(1, 2).moved(Location((1, 2, 3)))\n\n Builder mode works by having objects add themselves to the active builder immediately when \n they are created. In the example above:\n\n ``Cylinder(1, 2)`` creates the cylinder.\n\n The cylinder immediately adds itself to the ``BuildPart`` builder.\n\n ``.moved(...)`` is then applied to the temporary Python object returned by ``Cylinder``.\n\n Because the cylinder was already added to the builder, the move operation has no effect on \n the model being built.\n\n Placement must therefore be specified before the object is created, which is why Builder \n mode provides the ``Locations`` context (see below):\n\n .. code-block:: build123d\n\n with BuildPart() as valid:\n with Locations((1, 2, 3)):\n Cylinder(1, 2)\n\n Here the builder knows the location before the cylinder is created, so the part is placed \n correctly.\n\n A similar situation in normal Python\n\n .. code-block:: python\n\n with open(\"test.txt\", \"w\") as f:\n f.write(\"text\").to_bytes(1, \"big\")\n\n ``f.write(\"text\")`` writes \"text\" to the file and returns 4.\n ``.to_bytes(1, \"big\")`` is then called on that integer, producing b\"\\x04\".\n\n The file still contains only \"text\" because the additional operation happens after the \n write and its result is discarded.\n\n Builder mode behaves similarly: once an object has been added to the builder, modifying \n the returned Python object does not change what was already added.","api_names":"BuildPart context Cylinder Location Locations moved open to_bytes write","synonyms":"array pattern repeat"},"190":{"title":"Builder's Pending Objects","body":"When a builder exits, it will push the object created back to its parent if\nthere was one. Here is an example:\n\n.. code-block:: build123d\n\n height, width, thickness, f_rad = 60, 80, 20, 10\n\n with BuildPart() as pillow_block:\n with BuildSketch() as plan:\n Rectangle(width, height)\n fillet(plan.vertices(), radius=f_rad)\n extrude(amount=thickness)\n\n``BuildSketch`` exits after the ``fillet`` operation and when doing so it transfers\nthe sketch to the ``pillow_block`` instance of ``BuildPart`` as the internal instance variable\n``pending_faces``. This allows the ``extrude`` operation to be immediately invoked as it\nextrudes these pending faces into ``Solid`` objects. Likewise, ``loft`` would take all of the\n``pending_faces`` and attempt to create a single ``Solid`` object from them.\n\nNormally the user will not need to interact directly with pending objects; however,\none can see pending Edges and Faces with ``.pending_edges`` and \n``.pending_faces`` attributes. In the above example, by adding a \n``print(pillow_block.pending_faces)`` prior to the ``extrude(amount=thickness)`` the\npending ``Face`` from the ``BuildSketch`` will be displayed.","api_names":"BuildPart BuildSketch extrude Face fillet loft pending_faces pillow_block Rectangle Solid vertices","synonyms":"bevel edge blend profiles cross sections round edge transition"},"191":{"title":"Builders","body":"The three builders, ``BuildLine``, ``BuildSketch``, and ``BuildPart`` are tools to create\nnew objects - not the objects themselves. Each of the objects and operations applicable\nto these builders create objects of the standard CadQuery Direct API, most commonly\n``Compound`` objects. This is opposed to CadQuery's Fluent API which creates objects\nof the ``Workplane`` class which frequently needed to be converted back to base\nclass for further processing.\n\nOne can access the objects created by these builders by referencing the appropriate\ninstance variable. For example:\n\n.. code-block:: build123d\n\n with BuildPart() as my_part:\n ...\n\n show_object(my_part.part)\n\n.. code-block:: build123d\n\n with BuildSketch() as my_sketch:\n ...\n\n show_object(my_sketch.sketch)\n\n.. code-block:: build123d\n\n with BuildLine() as my_line:\n ...\n\n show_object(my_line.line)","api_names":"BuildLine BuildPart BuildSketch Compound show_object Workplane","synonyms":""},"192":{"title":"Combination Modes","body":"Almost all objects or operations have a ``mode`` parameter which is defined by the\n``Mode`` Enum class as follows:\n\n.. code-block:: build123d\n\n class Mode(Enum):\n ADD = auto()\n SUBTRACT = auto()\n INTERSECT = auto()\n REPLACE = auto()\n PRIVATE = auto()\n\nThe ``mode`` parameter describes how the user would like the object or operation to\ninteract with the object within the builder. For example, ``Mode.ADD`` will\nintegrate a new object(s) in with an existing ``part``. Note that a part doesn't\nnecessarily have to be a single object so multiple distinct objects could be added\nresulting is multiple objects stored as a ``Compound`` object. As one might expect\n``Mode.SUBTRACT``, ``Mode.INTERSECT``, and ``Mode.REPLACE`` subtract, intersect, or replace\n(from) the builder's object. ``Mode.PRIVATE`` instructs the builder that this object\nshould not be combined with the builder's object in any way.\n\nMost commonly, the default ``mode`` is ``Mode.ADD`` but this isn't always true.\nFor example, the ``Hole`` classes use a default ``Mode.SUBTRACT`` as they remove\na volume from the part under normal circumstances. However, the ``mode`` used in\nthe ``Hole`` classes can be specified as ``Mode.ADD`` or ``Mode.INTERSECT`` to\nhelp in inspection or debugging.","api_names":"ADD auto Compound Hole INTERSECT mode Mode object part PRIVATE replace REPLACE SUBTRACT","synonyms":"bore channel drill groove path cut recessed fastener"},"193":{"title":"Example Workflow","body":"Here is an example of using a Builder to create a simple part:\n\n.. code-block:: build123d\n\n from build123d import *\n\n # Using BuildPart to create a 3D model\n with BuildPart() as example_part:\n with BuildSketch() as base_sketch:\n Rectangle(20, 20)\n extrude(amount=10) # Create a base block\n with BuildSketch(Plane(example_part.faces().sort_by(Axis.Z).last)) as cut_sketch:\n Circle(5)\n extrude(amount=-5, mode=Mode.SUBTRACT) # Subtract a cylinder\n\n # Access the final part\n result_part = example_part.part","api_names":"BuildPart BuildSketch Circle extrude faces Plane Rectangle sort_by","synonyms":"channel groove path cut"},"194":{"title":"How the Builder Works","body":"When using a Builder (such as **BuildLine**, **BuildSketch**, or **BuildPart**), the \nfollowing principles apply:\n\n1. **Running Total**:\n - The Builder maintains an internal \"total,\" which represents the current state of \n the object being built. \n - Each operation updates this total by combining the new object with the existing one.\n\n2. **Combination Modes**:\n - Just as numbers in a column may have a `+` or `-` sign to indicate addition or \n subtraction, Builders use **modes** to control how each object is combined with \n the current total.\n - Common modes include:\n\n - **ADD**: Adds the new object to the current total.\n - **SUBTRACT**: Removes the new object from the current total.\n - **INTERSECT**: Keeps only the overlapping regions of the new object and the current total.\n - **REPLACE**: Entirely replace the running total.\n - **PRIVATE**: Don't change the running total at all. \n\n - The mode can be set dynamically for each operation, allowing for flexible and precise modeling.\n\n3. **Extracting the Result**:\n - At the end of the building process, the final object is accessed through the \n Builder's attributes, such as ``.line``, ``.sketch``, or ``.part``, depending on \n the Builder type.\n - For example:\n \n - **BuildLine**: Use ``.line`` to retrieve the final wireframe geometry.\n - **BuildSketch**: Use ``.sketch`` to extract the completed 2D profile.\n - **BuildPart**: Use ``.part`` to obtain the 3D solid.","api_names":"Builder","synonyms":""},"195":{"title":"Implicit Builder Instance Variables","body":"One might expect to have to reference a builder's instance variable when using\nobjects or operations that impact that builder like this:\n\n.. code-block:: build123d\n\n with BuildPart() as part_builder:\n Box(part_builder, 10,10,10)\n\nInstead, build123d determines from the scope of the object or operation which\nbuilder it applies to thus eliminating the need for the user to provide this\ninformation - as follows:\n\n.. code-block:: build123d\n\n with BuildPart() as part_builder:\n Box(10,10,10)\n with BuildSketch() as sketch_builder:\n Circle(2)\n\nIn this example, ``Box`` is in the scope of ``part_builder`` while ``Circle``\nis in the scope of ``sketch_builder``.","api_names":"Box BuildPart BuildSketch Circle part_builder sketch_builder","synonyms":""},"196":{"title":"Key Concepts","body":"- **Incremental Construction**:\n Builders allow you to build objects step-by-step, maintaining clarity and modularity.\n \n- **Dynamic Mode Switching**:\n The **mode** parameter gives you precise control over how each operation modifies \n the current total.\n\n- **Seamless Extraction**:\n The Builder paradigm simplifies the retrieval of the final object, ensuring that you \n always have access to the most up-to-date result.","api_names":"","synonyms":""},"197":{"title":"Key Concepts (builder mode)","body":"There are two primary APIs provided by build123d: builder and algebra. The builder\nAPI may be easier for new users as it provides some assistance and shortcuts; however,\nif you know what a Quaternion is you might prefer the algebra API which allows\nCAD objects to be created in the style of mathematical equations. Both API can\nbe mixed in the same model with the exception that the algebra API can't be used\nfrom within a builder context. As with music, there is no \"best\" genre or API,\nuse the one you prefer or both if you like.\n\nThe following key concepts will help new users understand build123d quickly.","api_names":"Concepts","synonyms":""},"198":{"title":"Locations Context","body":"When positioning objects or operations within a builder, Location Contexts are used. These\nfunction in a very similar way to the builders in that they create a context where one or\nmore locations are active within a scope. For example:\n\n.. code-block:: build123d\n\n with BuildPart():\n with Locations((0,10),(0,-10)):\n Box(1,1,1)\n with GridLocations(x_spacing=5, y_spacing=5, x_count=2, y_count=2):\n Sphere(1)\n Cylinder(1,1)\n\nIn this example ``Locations`` creates two positions on the current workplane at (0,10) and (0,-10).\nSince ``Box`` is within the scope of ``Locations``, two boxes are created at these locations. The\n``GridLocations`` context creates four positions which apply to the ``Sphere``. The ``Cylinder`` is\nout of the scope of ``GridLocations`` but in the scope of ``Locations`` so two cylinders are created.\n\nNote that these contexts are creating Location objects not just simple points. The difference\nisn't obvious until the ``PolarLocations`` context is used which can also rotate objects within\nits scope - much as the hour and minute indicator on an analogue clock.\n\nAlso note that the locations are local to the current location(s) - i.e. ``Locations`` can be\nnested. It's easy for a user to retrieve the global locations:\n\n.. code-block:: build123d\n\n with Locations(Plane.XY, Plane.XZ):\n locs = GridLocations(1, 1, 2, 2)\n for l in locs:\n print(l)\n\n.. code-block::\n\n Location(p=(-0.50,-0.50,0.00), o=(0.00,-0.00,0.00))\n Location(p=(-0.50,0.50,0.00), o=(0.00,-0.00,0.00))\n Location(p=(0.50,-0.50,0.00), o=(0.00,-0.00,0.00))\n Location(p=(0.50,0.50,0.00), o=(0.00,-0.00,0.00))\n Location(p=(-0.50,-0.00,-0.50), o=(90.00,-0.00,0.00))\n Location(p=(-0.50,0.00,0.50), o=(90.00,-0.00,0.00))\n Location(p=(0.50,0.00,-0.50), o=(90.00,-0.00,0.00))\n Location(p=(0.50,0.00,0.50), o=(90.00,-0.00,0.00))","api_names":"at Box BuildPart Cylinder GridLocations location Location Locations PolarLocations Sphere","synonyms":"array pattern repeat"},"199":{"title":"Operation Inputs","body":"When one is operating on an existing object, e.g. adding a fillet to a part,\nan iterable of objects is often required (often a ShapeList).\n\nHere is the definition of :meth:`~operations_generic.fillet` to help illustrate:\n\n.. code-block:: build123d\n\n def fillet(\n objects: Union[Union[Edge, Vertex], Iterable[Union[Edge, Vertex]]],\n radius: float,\n ):\n\nTo use this fillet operation, an edge or vertex or iterable of edges or \nvertices must be provided followed by a fillet radius with or without the keyword as follows:\n\n.. code-block:: build123d\n\n with BuildPart() as pipes:\n Box(10, 10, 10, rotation=(10, 20, 30))\n ...\n fillet(pipes.edges(Select.LAST), radius=0.2)\n\nHere the fillet accepts the iterable ShapeList of edges from the last operation of\nthe ``pipes`` builder and a radius is provided as a keyword argument.","api_names":"Box BuildPart edges fillet pipes required","synonyms":"bevel edge round edge"},"200":{"title":"Understanding the Builder Paradigm","body":"The **Builder** paradigm in build123d provides a powerful and intuitive way to construct \ncomplex geometric models. At its core, the Builder works like adding a column of numbers \non a piece of paper: a running \"total\" is maintained internally as each new object is \nadded or modified. This approach simplifies the process of constructing models by breaking \nit into smaller, incremental steps.","api_names":"","synonyms":""},"201":{"title":"Using Locations & Rotating Objects","body":"build123d stores points (to be specific ``Location`` (s)) internally to be used as\npositions for the placement of new objects. By default, a single location\nwill be created at the origin of the given workplane such that:\n\n.. code-block:: build123d\n\n with BuildPart() as pipes:\n Box(10, 10, 10, rotation=(10, 20, 30))\n\nwill create a single 10x10x10 box centered at (0,0,0) - by default objects are\ncentered. One can create multiple objects by pushing points prior to creating\nobjects as follows:\n\n.. code-block:: build123d\n\n with BuildPart() as pipes:\n with Locations((-10, -10, -10), (10, 10, 10)):\n Box(10, 10, 10, rotation=(10, 20, 30))\n\nwhich will create two boxes.\n\nTo orient a part, a ``rotation`` parameter is available on ``BuildSketch``` and\n``BuildPart`` APIs. When working in a sketch, the rotation is a single angle in\ndegrees so the parameter is a float. When working on a part, the rotation is\na three dimensional ``Rotation`` object of the form\n``Rotation(, , )`` although a simple three tuple of\nfloats can be used as input. As 3D rotations are not cumulative, one can\ncombine rotations with the `*` operator like this:\n``Rotation(10, 20, 30) * Rotation(0, 90, 0)`` to generate any desired rotation.\n\n.. hint::\n Experts Only\n\n ``Locations`` will accept ``Location`` objects for input which allows one\n to specify both the position and orientation. However, the orientation\n is often determined by the ``Plane`` that an object was created on.\n ``Rotation`` is a subclass of ``Location`` and therefore will also accept\n a position component.","api_names":"at Box BuildPart BuildSketch Location Locations Plane points rotation Rotation","synonyms":"array pattern repeat"},"202":{"title":"Workplanes","body":"As build123d is a 3D CAD package one must be able to position objects anywhere. As one\nfrequently will work in the same plane for a sequence of operations, the first parameter(s)\nof the builders is a (sequence of) workplane(s) which is (are) used\nto aid in the location of features. The default workplane in most cases is the ``Plane.XY``\nwhere a tuple of numbers represent positions on the x and y axes. However workplanes can\nbe generated on any plane which allows users to put a workplane where they are working\nand then work in local 2D coordinate space.\n\n\n.. code-block:: build123d\n\n with BuildPart(Plane.XY) as example:\n ... # a 3D-part\n with BuildSketch(example.faces().sort_by(sort_by=Axis.Z)[0]) as bottom:\n ...\n with BuildSketch(Plane.XZ) as vertical:\n ...\n with BuildSketch(example.faces().sort_by(sort_by=Axis.Z)[-1]) as top:\n ...\n\nWhen ``BuildPart`` is invoked it creates the workplane provided as a parameter (which has a\ndefault of the ``Plane.XY``). The ``bottom`` sketch is therefore created on the ``Plane.XY`` but with the\nnormal reversed to point down. Subsequently the user has created the ``vertical`` (``Plane.XZ``) sketch.\nAll objects or operations within the scope of a workplane will automatically be orientated with\nrespect to this plane so the user only has to work with local coordinates.\n\nAs shown above, workplanes can be created from faces as well. The ``top`` sketch is\npositioned on top of ``example`` by selecting its faces and finding the one with the greatest z value.\n\nOne is not limited to a single workplane at a time. In the following example all six\nfaces of the first box are used to define workplanes which are then used to position\nrotated boxes.\n\n.. code-block:: build123d\n\n import build123d as bd\n\n with bd.BuildPart() as bp:\n bd.Box(3, 3, 3)\n with bd.BuildSketch(*bp.faces()):\n bd.Rectangle(1, 2, rotation=45)\n bd.extrude(amount=0.1)\n\nThis is the result:\n\n.. image:: boxes_on_faces.svg\n :align: center\n\n.. _location_context_link:","api_names":"a bottom Box BuildPart BuildSketch example extrude faces is parameter Rectangle sort_by top vertical workplane XY XZ","synonyms":""},"203":{"title":"Key Concepts","body":"The following key concepts will help new users understand build123d quickly.\n\n.. _topology:","api_names":"","synonyms":""},"204":{"title":"Location","body":"A :class:`~geometry.Location` represents a combination of translation and rotation\napplied to a topological or geometric object. It encapsulates information\nabout the spatial orientation and position of a shape within its reference\ncoordinate system. This allows for efficient manipulation of shapes within\ncomplex assemblies or transformations. The location is typically used to\nposition shapes accurately within a 3D scene, enabling operations like\nassembly, and boolean operations. It's an essential component in build123d\nfor managing the spatial relationships of geometric entities, providing a\nfoundation for precise 3D modeling and engineering applications.\n\nThe topological classes (sub-classes of :class:`~topology.Shape`) and the geometric classes \n:class:`~geometry.Axis` and :class:`~geometry.Plane` all have a ``location`` property.\nThe :class:`~geometry.Location` class itself has ``position`` and ``orientation`` properties\nthat have setters and getters as shown below:\n\n\n.. doctest::\n\n >>> from build123d import *\n >>> # Create an object and extract its location\n >>> b = Box(1, 1, 1)\n >>> box_location = b.location\n >>> box_location\n (p=(0.00, 0.00, 0.00), o=(-0.00, 0.00, -0.00))\n >>> # Set position and orientation independently\n >>> box_location.position = (1, 2, 3)\n >>> box_location.orientation = (30, 40, 50)\n >>> box_location.position\n Vector: (1.0, 2.0, 3.0)\n >>> box_location.orientation\n Vector: (29.999999999999993, 40.00000000000002, 50.000000000000036)\n\nCombining the getter and setter enables relative changes as follows:\n\n.. doctest::\n\n >>> # Relative change\n >>> box_location.position += (3, 2, 1)\n >>> box_location.position\n Vector: (4.0, 4.0, 4.0)\n\nThere are also four methods that are used to change the location of objects:\n\n* :meth:`~topology.Shape.locate` - absolute change of this object\n* :meth:`~topology.Shape.located` - absolute change of copy of this object\n* :meth:`~topology.Shape.move` - relative change of this object\n* :meth:`~topology.Shape.moved` - relative change of copy of this object\n\nLocations can be combined with the ``*`` operator and have their direction flipped with\nthe ``-`` operator.","api_names":"Axis Box box_location classes locate located location Location move moved orientation Plane position Shape","synonyms":"array pattern repeat"},"205":{"title":"Selectors","body":".. include:: selectors.rst","api_names":"","synonyms":""},"206":{"title":"Topology","body":"Topology, in the context of 3D modeling and computational geometry, is the\nbranch of mathematics that deals with the properties and relationships of\ngeometric objects that are preserved under continuous deformations. In the\ncontext of CAD and modeling software like build123d, topology refers to the\nhierarchical structure of geometric elements (vertices, edges, faces, etc.) and\ntheir relationships in a 3D model. This structure defines how the components of\na model are connected, enabling operations like Boolean operations,\ntransformations, and analysis of complex shapes. Topology provides a formal\nframework for understanding and manipulating geometric data in a consistent and\nreliable manner.\n\nThe following are the topological objects that compose build123d objects:\n\n:class:`~topology.Vertex`\n A Vertex is a data structure representing a 0D topological element. It\n defines a precise point in 3D space, often at the endpoints or intersections of\n edges in a 3D model. These vertices are part of the topological structure used\n to represent complex shapes in build123d.\n\n:class:`~topology.Edge`\n\tAn Edge in build123d is a fundamental geometric entity representing a 1D\n\telement in a 3D model. It defines the shape and position of a 1D curve within\n\tthe model. Edges play a crucial role in defining the boundaries of faces and in\n\tconstructing complex 3D shapes.\n\n:class:`~topology.Wire`\n\tA Wire in build123d is a topological construct that represents a connected\n\tsequence of Edges, forming a 1D closed or open loop within a 3D model. Wires\n\tdefine the boundaries of faces and can be used to create complex shapes, making\n\tthem essential for modeling in build123d.\n\n:class:`~topology.Face`\n\tA Face in build123d represents a 2D surface in a 3D model. It defines the\n\tboundary of a region and can have associated geometric and topological data.\n\tFaces are vital for shaping solids, providing surfaces where other elements like\n\tedges and wires are connected to form complex structures.\n\n:class:`~topology.Shell`\n\tA Shell in build123d represents a collection of Faces, defining a closed,\n\tconnected volume in 3D space. It acts as a container for organizing and grouping\n\tfaces into a single shell, essential for defining complex 3D shapes like solids\n\tor assemblies within the build123d modeling framework.\n\n:class:`~topology.Solid`\n\tA Solid in build123d is a 3D geometric entity that represents a bounded\n\tvolume with well-defined interior and exterior surfaces. It encapsulates a\n\tclosed and watertight shape, making it suitable for modeling solid objects and\n\tenabling various Boolean operations such as union, intersection, and\n\tsubtraction.\n\n:class:`~topology.Compound`\n\tA Compound in build123d is a container for grouping multiple geometric\n\tshapes. It can hold various types of entities, such as vertices, edges, wires,\n\tfaces, shells, or solids, into a single structure. This makes it a versatile\n\ttool for managing and organizing complex assemblies or collections of shapes\n\twithin a single container.\n\n:class:`~topology.Shape`\n\tA Shape in build123d represents a fundamental building block in 3D\n\tmodeling. It encompasses various topological elements like vertices, edges,\n\twires, faces, shells, solids, and compounds. The Shape class is the base class\n\tfor all of the above topological classes.\n\nOne can use the :meth:`~topology.Shape.show_topology` method to display the\ntopology of a shape as shown here for a unit cube:\n\n.. code::\n\t\n\tSolid at 0x7f94c55430f0, Center(0.5, 0.5, 0.5)\n\t└── Shell at 0x7f94b95835f0, Center(0.5, 0.5, 0.5)\n\t ├── Face at 0x7f94b95836b0, Center(0.0, 0.5, 0.5)\n\t │ └── Wire at 0x7f94b9583730, Center(0.0, 0.5, 0.5)\n\t │ ├── Edge at 0x7f94b95838b0, Center(0.0, 0.0, 0.5)\n\t │ │ ├── Vertex at 0x7f94b9583470, Center(0.0, 0.0, 1.0)\n\t │ │ └── Vertex at 0x7f94b9583bb0, Center(0.0, 0.0, 0.0)\n\t │ ├── Edge at 0x7f94b9583a30, Center(0.0, 0.5, 1.0)\n\t │ │ ├── Vertex at 0x7f94b9583030, Center(0.0, 1.0, 1.0)\n\t │ │ └── Vertex at 0x7f94b9583e70, Center(0.0, 0.0, 1.0)\n\t │ ├── Edge at 0x7f94b9583770, Center(0.0, 1.0, 0.5)\n\t │ │ ├── Vertex at 0x7f94b9583bb0, Center(0.0, 1.0, 1.0)\n\t │ │ └── Vertex at 0x7f94b9583e70, Center(0.0, 1.0, 0.0)\n\t │ └── Edge at 0x7f94b9583db0, Center(0.0, 0.5, 0.0)\n\t │ ├── Vertex at 0x7f94b9583e70, Center(0.0, 1.0, 0.0)\n\t │ └── Vertex at 0x7f94b95862f0, Center(0.0, 0.0, 0.0)\n\t...\n\t └── Face at 0x7f94b958d3b0, Center(0.5, 0.5, 1.0)\n\t └── Wire at 0x7f94b958d670, Center(0.5, 0.5, 1.0)\n\t ├── Edge at 0x7f94b958e130, Center(0.0, 0.5, 1.0)\n\t │ ├── Vertex at 0x7f94b958e330, Center(0.0, 1.0, 1.0)\n\t │ └── Vertex at 0x7f94b958e770, Center(0.0, 0.0, 1.0)\n\t ├── Edge at 0x7f94b958e630, Center(0.5, 1.0, 1.0)\n\t │ ├── Vertex at 0x7f94b958e8b0, Center(1.0, 1.0, 1.0)\n\t │ └── Vertex at 0x7f94b958ea70, Center(0.0, 1.0, 1.0)\n\t ├── Edge at 0x7f94b958e7b0, Center(1.0, 0.5, 1.0)\n\t │ ├── Vertex at 0x7f94b958ebb0, Center(1.0, 1.0, 1.0)\n\t │ └── Vertex at 0x7f94b958ed70, Center(1.0, 0.0, 1.0)\n\t └── Edge at 0x7f94b958eab0, Center(0.5, 0.0, 1.0)\n\t ├── Vertex at 0x7f94b958eeb0, Center(1.0, 0.0, 1.0)\n\t └── Vertex at 0x7f94b9592170, Center(0.0, 0.0, 1.0)\n\t\nUsers of build123d will often reference topological objects as part of the\nprocess of creating the object as described below.","api_names":"Center Compound Edge elements Face Shape Shell show_topology Solid Vertex Wire","synonyms":""},"207":{"title":"Location arithmetic for algebra mode","body":"","api_names":"","synonyms":""},"208":{"title":"Position a shape relative to the XY plane","body":"For the following use the helper function:\n\n.. code-block:: build123d\n\n def location_symbol(location: Location, scale: float = 1) -> Compound:\n return Compound.make_triad(axes_scale=scale).locate(location)\n\n def plane_symbol(plane: Plane, scale: float = 1) -> Compound:\n triad = Compound.make_triad(axes_scale=scale)\n circle = Circle(scale * .8).edge()\n return (triad + circle).locate(plane.location)\n\n1. **Positioning at a location**\n\n .. code-block:: build123d\n\n loc = Location((0.1, 0.2, 0.3), (10, 20, 30))\n\n face = loc * Rectangle(1, 2)\n\n show_object(face, name=\"face\")\n show_object(location_symbol(loc), name=\"location\")\n\n.. image:: assets/location-example-01.png\n\n2) **Positioning on a plane**\n\n .. code-block:: build123d\n\n plane = Plane.XZ\n\n face = plane * Rectangle(1, 2)\n\n show_object(face, name=\"face\")\n show_object(plane_symbol(plane), name=\"plane\")\n\n.. image:: assets/location-example-07.png\n\nNote: The ``x``-axis and the ``y``-axis of the plane are on the ``x``-axis and the ``z``-axis of the world coordinate system (red and blue axis).","api_names":"Circle edge locate Location location_symbol make_triad plane_symbol Rectangle return show_object system x y z","synonyms":""},"209":{"title":"Relative positioning to a plane","body":"1. **Position an object on a plane relative to the plane**\n\n .. code-block:: build123d\n\n loc = Location((0.1, 0.2, 0.3), (10, 20, 30))\n\n face = loc * Rectangle(1,2)\n\n box = Plane(loc) * Pos(0.2, 0.4, 0.1) * Box(0.2, 0.2, 0.2)\n # box = Plane(face.location) * Pos(0.2, 0.4, 0.1) * Box(0.2, 0.2, 0.2)\n # box = loc * Pos(0.2, 0.4, 0.1) * Box(0.2, 0.2, 0.2)\n\n show_object(face, name=\"face\")\n show_object(location_symbol(loc), name=\"location\")\n show_object(box, name=\"box\")\n\n.. image:: assets/location-example-02.png\n\nThe ``X``, ``Y``, ``Z`` components of ``Pos(0.2, 0.4, 0.1)`` are relative to the ``x``-axis, ``y``-axis or\n``z``-axis of the underlying location ``loc``.\n\nNote: ``Plane(loc) *``, ``Plane(face.location) *`` and ``loc *`` are equivalent in this example.\n\n2. **Rotate an object on a plane relative to the plane**\n\n .. code-block:: build123d\n\n loc = Location((0.1, 0.2, 0.3), (10, 20, 30))\n\n face = loc * Rectangle(1,2)\n\n box = Plane(loc) * Rot(Z=80) * Box(0.2, 0.2, 0.2)\n\n show_object(face, name=\"face\")\n show_object(location_symbol(loc), name=\"location\")\n show_object(box, name=\"box\")\n\n.. image:: assets/location-example-03.png\n\nThe box is rotated via ``Rot(Z=80)`` around the ``z``-axis of the underlying location\n(and not of the z-axis of the world).\n\nMore general:\n\n .. code-block:: build123d\n\n loc = Location((0.1, 0.2, 0.3), (10, 20, 30))\n\n face = loc * Rectangle(1,2)\n\n box = loc * Rot(20, 40, 80) * Box(0.2, 0.2, 0.2)\n\n show_object(face, name=\"face\")\n show_object(location_symbol(loc), name=\"location\")\n show_object(box, name=\"box\")\n\n.. image:: assets/location-example-04.png\n\nThe box is rotated via ``Rot(20, 40, 80)`` around all three axes relative to the plane.\n\n3. **Rotate and position an object relative to a location**\n\n .. code-block:: build123d\n\n loc = Location((0.1, 0.2, 0.3), (10, 20, 30))\n\n face = loc * Rectangle(1,2)\n\n box = loc * Rot(20, 40, 80) * Pos(0.2, 0.4, 0.1) * Box(0.2, 0.2, 0.2)\n\n show_object(face, name=\"face\")\n show_object(location_symbol(loc), name=\"location\")\n show_object(box, name=\"box\")\n show_object(location_symbol(loc * Rot(20, 40, 80), 0.5), options={\"color\":(0, 255, 255)}, name=\"local_location\")\n\n.. image:: assets/location-example-05.png\n\nThe box is positioned via ``Pos(0.2, 0.4, 0.1)`` relative to the location ``loc * Rot(20, 40, 80)``\n\n4. **Position and rotate an object relative to a location**\n\n .. code-block:: build123d\n\n loc = Location((0.1, 0.2, 0.3), (10, 20, 30))\n\n face = loc * Rectangle(1,2)\n\n box = loc * Pos(0.2, 0.4, 0.1) * Rot(20, 40, 80) * Box(0.2, 0.2, 0.2)\n\n show_object(face, name=\"face\")\n show_object(location_symbol(loc), name=\"location\")\n show_object(box, name=\"box\")\n show_object(location_symbol(loc * Pos(0.2, 0.4, 0.1), 0.5), options={\"color\":(0, 255, 255)}, name=\"local_location\")\n\n.. image:: assets/location-example-06.png\n\nNote: This is the same as ``box = loc * Location((0.2, 0.4, 0.1), (20, 40, 80)) * Box(0.2, 0.2, 0.2)``","api_names":"box Box loc location Location location_symbol Plane Pos Rectangle Rot show_object x X y Y z Z","synonyms":""},"210":{"title":"Algebra Mode","body":"In algebra mode, object movement is expressed using algebraic operations. The \n:class:`~geometry.Pos` function, short for Position, represents a location, which can be combined \nwith objects or planes to define placement.\n\n1. ``Pos() * shape``: Applies a position to a shape.\n2. ``Plane() * Pos() * shape``: Combines a plane with a position and applies it to a shape.\n\nRotation is an important concept in this mode. A :class:`~geometry.Rotation` represents a location \nwith orientation values set, which can be used to define a new location or modify \nan existing one.\n\nExample:\n\n.. code-block:: build123d\n\n rotated_box = Rotation(45, 0, 0) * box","api_names":"Plane Pos Rotation","synonyms":""},"211":{"title":"Builder Mode","body":"In builder mode, object locations are defined before the objects themselves are \ncreated. This approach ensures that objects are positioned correctly during the \nconstruction process. The following tools are commonly used to specify locations:\n\n1. :class:`~build_common.Locations` Use this to define a specific location for the objects within the `with` block.\n2. :class:`~build_common.GridLocations` Arrange objects in a grid pattern.\n3. :class:`~build_common.PolarLocations` Position objects in a circular pattern.\n4. :class:`~build_common.HexLocations` Arrange objects in a hexagonal grid.\n\n.. note::\n The location(s) of an object must be defined prior to its creation when using builder mode.\n\nExample:\n\n.. code-block:: build123d\n\n with Locations((10, 20, 30)):\n Box(5, 5, 5)","api_names":"Box GridLocations HexLocations location Locations PolarLocations","synonyms":"array pattern repeat"},"212":{"title":"Direct Manipulation Methods","body":"The following methods allow for direct manipulation of a shape's location and orientation \nafter it has been created. These methods offer a mix of absolute and relative transformations.","api_names":"","synonyms":""},"213":{"title":"Movement Methods","body":"- **Relative Move:**\n\n.. code-block:: build123d\n\n shape.move(Location)\n \n- **Relative Move of Copy:**\n\n.. code-block:: build123d\n\n relocated_shape = shape.moved(Location)\n \n- **Absolute Move:**\n\n.. code-block:: build123d\n\n shape.locate(Location)\n \n- **Absolute Move of Copy:**\n\n.. code-block:: build123d\n\n relocated_shape = shape.located(Location)","api_names":"locate located move moved","synonyms":""},"214":{"title":"Moving Objects","body":"In build123d, there are several methods to move objects. These methods vary \nbased on the mode of operation and provide flexibility for object placement \nand orientation. Below, we outline the three main approaches to moving objects: \nbuilder mode, algebra mode, and direct manipulation methods.","api_names":"","synonyms":""},"215":{"title":"Orientation","body":"- **Absolute Orientation:** Set the orientation directly.\n\n.. code-block:: build123d\n\n shape.orientation = (X, Y, Z)\n\n- **Relative Orientation:** Adjust the orientation incrementally.\n\n.. code-block:: build123d\n\n shape.orientation += (X, Y, Z)\n shape.orientation -= (X, Y, Z)","api_names":"","synonyms":""},"216":{"title":"Position","body":"- **Absolute Position:** Set the position directly.\n \n.. code-block:: build123d\n\n shape.position = (x, y, z)\n \n- **Relative Position:** Adjust the position incrementally.\n\n.. code-block:: build123d\n\n shape.position += (x, y, z)\n shape.position -= (x, y, z)","api_names":"","synonyms":""},"217":{"title":"Transformation a.k.a. Translation and Rotation","body":".. note::\n These methods have an optional ``transform`` parameter which allows the user to transform the base \n object itself which is quite slow and potentially problematic as opposed to just changing the \n object's internal :class:`~geometry.Location`. \n\n- **Translation:** Move a shape relative to its current position.\n\n.. code-block:: build123d\n\n relocated_shape = shape.translate((x, y, z))\n \n- **Rotation:** Rotate a shape around a specified axis by a given angle.\n\n.. code-block:: build123d\n\n rotated_shape = shape.rotate(Axis, angle_in_degrees)","api_names":"Location rotate transform translate","synonyms":""},"218":{"title":"1D Objects","body":"The following objects all can be used in BuildLine contexts. Note that\n1D objects are not affected by ``Locations`` in Builder mode.\n\n.. grid:: 3\n\n .. grid-item-card:: :class:`~objects_curve.Airfoil`\n\n .. image:: assets/example_airfoil.svg\n\n +++\n Airfoil described by 4 digit NACA profile\n\n .. grid-item-card:: :class:`~objects_curve.Bezier`\n\n .. image:: assets/bezier_curve_example.svg\n\n +++\n Curve defined by control points and weights\n\n .. grid-item-card:: :class:`~objects_curve.BlendCurve`\n\n .. image:: assets/example_blend_curve.svg\n\n +++\n Curve blending curvature of two curves\n\n .. grid-item-card:: :class:`~objects_curve.BSpline`\n\n .. image:: assets/example_bspline.svg\n\n +++\n B-spline from control points and knot data\n\n .. grid-item-card:: :class:`~objects_curve.CenterArc`\n\n .. image:: assets/center_arc_example.svg\n\n +++\n Arc defined by center, radius, & angles\n\n\n .. grid-item-card:: :class:`~objects_curve.ConstrainedArcs`\n\n .. image:: assets/constrained_arcs_example.svg\n\n +++\n Arc(s) constrained by other geometric objects\n\n\n .. grid-item-card:: :class:`~objects_curve.ConstrainedLines`\n\n .. image:: assets/constrained_lines_example.svg\n\n +++\n Line(s) constrained by other geometric objects\n\n .. grid-item-card:: :class:`~objects_curve.DoubleTangentArc`\n\n .. image:: assets/double_tangent_line_example.svg\n\n +++\n Arc defined by point/tangent pair & other curve\n\n .. grid-item-card:: :class:`~objects_curve.EllipticalCenterArc`\n\n .. image:: assets/elliptical_center_arc_example.svg\n\n +++\n Elliptical arc defined by center, radii & angles\n\n .. grid-item-card:: :class:`~objects_curve.EllipticalStartArc`\n\n .. image:: assets/elliptical_start_arc_example.svg\n\n +++\n Elliptical arc defined by start, tangent, radii & angles\n\n .. grid-item-card:: :class:`~objects_curve.ParabolicCenterArc`\n\n .. image:: assets/parabolic_center_arc_example.svg\n\n +++\n Parabolic arc defined by vertex, focal length & angles\n\n .. grid-item-card:: :class:`~objects_curve.HyperbolicCenterArc`\n\n .. image:: assets/hyperbolic_center_arc_example.svg\n\n +++\n Hyperbolic arc defined by center, radii & angles\n\n .. grid-item-card:: :class:`~objects_curve.FilletPolyline`\n\n .. image:: assets/filletpolyline_example.svg\n\n +++\n Polyline with filleted corners defined by pts and radius\n\n .. grid-item-card:: :class:`~objects_curve.Helix`\n\n .. image:: assets/helix_example.svg\n\n +++\n Helix defined pitch, radius and height\n\n .. grid-item-card:: :class:`~objects_curve.IntersectingLine`\n\n .. image:: assets/intersecting_line_example.svg\n\n +++\n Intersecting line defined by start, direction & other line\n\n .. grid-item-card:: :class:`~objects_curve.JernArc`\n\n .. image:: assets/jern_arc_example.svg\n\n +++\n Arc define by start point, tangent, radius and angle\n\n .. grid-item-card:: :class:`~objects_curve.Line`\n\n .. image:: assets/line_example.svg\n\n +++\n Line defined by end points\n\n .. grid-item-card:: :class:`~objects_curve.PolarLine`\n\n .. image:: assets/polar_line_example.svg\n\n +++\n Line defined by start, angle and length\n\n .. grid-item-card:: :class:`~objects_curve.Polyline`\n\n .. image:: assets/polyline_example.svg\n\n +++\n Multiple line segments defined by points\n\n .. grid-item-card:: :class:`~objects_curve.RadiusArc`\n\n .. image:: assets/radius_arc_example.svg\n\n +++\n Arc defined by two points and a radius\n\n .. grid-item-card:: :class:`~objects_curve.SagittaArc`\n\n .. image:: assets/sagitta_arc_example.svg\n\n +++\n Arc defined by two points and a sagitta\n\n .. grid-item-card:: :class:`~objects_curve.Spline`\n\n .. image:: assets/spline_example.svg\n\n +++\n Curve define by points\n\n .. grid-item-card:: :class:`~objects_curve.TangentArc`\n\n .. image:: assets/tangent_arc_example.svg\n\n +++\n Arc defined by two points and a tangent\n\n .. grid-item-card:: :class:`~objects_curve.ThreePointArc`\n\n .. image:: assets/three_point_arc_example.svg\n\n +++\n Arc defined by three points\n\n .. grid-item-card:: :class:`~objects_curve.ArcArcTangentLine`\n\n .. image:: assets/example_arc_arc_tangent_line.svg\n\n +++\n Line tangent defined by two arcs\n\n .. grid-item-card:: :class:`~objects_curve.ArcArcTangentArc`\n\n .. image:: assets/example_arc_arc_tangent_arc.svg\n\n +++\n Arc tangent defined by two arcs\n\n .. grid-item-card:: :class:`~objects_curve.PointArcTangentLine`\n\n .. image:: assets/example_point_arc_tangent_line.svg\n\n +++\n Line tangent defined by a point and arc\n\n .. grid-item-card:: :class:`~objects_curve.PointArcTangentArc`\n\n .. image:: assets/example_point_arc_tangent_arc.svg\n\n +++\n Arc tangent defined by a point, direction, and arc","api_names":"Airfoil Arc ArcArcTangentArc ArcArcTangentLine Bezier BlendCurve BSpline CenterArc ConstrainedArcs ConstrainedLines DoubleTangentArc EllipticalCenterArc EllipticalStartArc FilletPolyline Helix HyperbolicCenterArc IntersectingLine JernArc Line Locations ParabolicCenterArc PointArcTangentArc PointArcTangentLine PolarLine Polyline RadiusArc SagittaArc Spline TangentArc ThreePointArc","synonyms":"array bevel edge coil control points interpolation pattern repeat round edge smooth curve spiral thread path"},"219":{"title":"2D Objects","body":".. grid:: 3\n\n .. grid-item-card:: :class:`~drafting.Arrow`\n\n .. image:: assets/arrow.svg\n\n +++\n Arrow with head and path for shaft\n\n .. grid-item-card:: :class:`~drafting.ArrowHead`\n\n .. image:: assets/arrow_head.svg\n\n +++\n Arrow head with multiple types\n\n\n .. grid-item-card:: :class:`~objects_sketch.Circle`\n\n .. image:: assets/circle_example.svg\n\n +++\n Circle defined by radius\n\n .. grid-item-card:: :class:`~drafting.DimensionLine`\n\n .. image:: assets/d_line.svg\n\n +++\n Dimension line\n\n\n .. grid-item-card:: :class:`~objects_sketch.Ellipse`\n\n .. image:: assets/ellipse_example.svg\n\n +++\n Ellipse defined by major and minor radius\n\n .. grid-item-card:: :class:`~drafting.ExtensionLine`\n\n .. image:: assets/e_line.svg\n\n +++\n Extension lines for distance or angles\n\n .. grid-item-card:: :class:`~objects_sketch.Polygon`\n\n .. image:: assets/polygon_example.svg\n\n +++\n Polygon defined by points\n\n .. grid-item-card:: :class:`~objects_sketch.Rectangle`\n\n .. image:: assets/rectangle_example.svg\n\n +++\n Rectangle defined by width and height\n\n .. grid-item-card:: :class:`~objects_sketch.RectangleRounded`\n\n .. image:: assets/rectangle_rounded_example.svg\n\n +++\n Rectangle with rounded corners defined by width, height, and radius\n\n .. grid-item-card:: :class:`~objects_sketch.RegularPolygon`\n\n .. image:: assets/regular_polygon_example.svg\n\n +++\n RegularPolygon defined by radius and number of sides\n\n .. grid-item-card:: :class:`~objects_sketch.SlotArc`\n\n .. image:: assets/slot_arc_example.svg\n\n +++\n SlotArc defined by arc and height\n\n .. grid-item-card:: :class:`~objects_sketch.SlotCenterPoint`\n\n .. image:: assets/slot_center_point_example.svg\n\n +++\n SlotCenterPoint defined by two points and a height\n\n .. grid-item-card:: :class:`~objects_sketch.SlotCenterToCenter`\n\n .. image:: assets/slot_center_to_center_example.svg\n\n +++\n SlotCenterToCenter defined by center separation and height\n\n .. grid-item-card:: :class:`~objects_sketch.SlotOverall`\n\n .. image:: assets/slot_overall_example.svg\n\n +++\n SlotOverall defined by end-to-end length and height\n\n .. grid-item-card:: :class:`~drafting.TechnicalDrawing`\n\n .. image:: assets/tech_drawing.svg\n\n +++\n A technical drawing with descriptions\n\n .. grid-item-card:: :class:`~objects_sketch.Text`\n\n .. image:: assets/text_example.svg\n\n +++\n Text defined by string and font parameters\n\n .. grid-item-card:: :class:`~objects_sketch.Trapezoid`\n\n .. image:: assets/trapezoid_example.svg\n\n +++\n Trapezoid defined by width, height and interior angles\n\n .. grid-item-card:: :class:`~objects_sketch.Triangle`\n\n .. image:: assets/triangle_example.svg\n\n +++\n Triangle defined by one side & two other sides or interior angles","api_names":"Arrow ArrowHead Circle DimensionLine Ellipse ExtensionLine Polygon Rectangle RectangleRounded RegularPolygon SlotArc SlotCenterPoint SlotCenterToCenter SlotOverall TechnicalDrawing Text Trapezoid Triangle","synonyms":""},"220":{"title":"3D Objects","body":".. grid:: 3\n\n .. grid-item-card:: :class:`~objects_part.Box`\n\n .. image:: assets/box_example.svg\n\n +++\n Box defined by length, width, height\n\n .. grid-item-card:: :class:`~objects_part.Cone`\n\n .. image:: assets/cone_example.svg\n\n +++\n Cone defined by radii and height\n\n .. grid-item-card:: :class:`~objects_part.ConvexPolyhedron`\n\n .. image:: assets/convex_polyhedron_example.svg\n\n +++\n Convex Polyhedron defined by points\n\n .. grid-item-card:: :class:`~objects_part.CounterBoreHole`\n\n .. image:: assets/counter_bore_hole_example.svg\n\n +++\n Counter bore hole defined by radii and depths\n\n .. grid-item-card:: :class:`~objects_part.CounterSinkHole`\n\n .. image:: assets/counter_sink_hole_example.svg\n\n +++\n Counter sink hole defined by radii and depth and angle\n\n .. grid-item-card:: :class:`~objects_part.Cylinder`\n\n .. image:: assets/cylinder_example.svg\n\n +++\n Cylinder defined by radius and height\n\n .. grid-item-card:: :class:`~objects_part.Hole`\n\n .. image:: assets/hole_example.svg\n\n +++\n Hole defined by radius and depth\n\n .. grid-item-card:: :class:`~objects_part.Sphere`\n\n .. image:: assets/sphere_example.svg\n\n +++\n Sphere defined by radius and arc angles\n\n .. grid-item-card:: :class:`~objects_part.Torus`\n\n .. image:: assets/torus_example.svg\n\n +++\n Torus defined major and minor radii\n\n .. grid-item-card:: :class:`~objects_part.Wedge`\n\n .. image:: assets/wedge_example.svg\n\n +++\n Wedge defined by lengths along multiple Axes","api_names":"Box Cone ConvexPolyhedron CounterBoreHole CounterSinkHole Cylinder Hole Sphere Torus Wedge","synonyms":"bore drill recessed fastener"},"221":{"title":"Align","body":"2D/Sketch and 3D/Part objects can be aligned relative to themselves, either centered, or justified\nright or left of each Axis. The following diagram shows how this alignment works in 2D:\n\n.. image:: assets/align.svg\n :align: center\n\nFor example:\n\n.. code-block:: build123d\n\n with BuildSketch():\n Circle(1, align=(Align.MIN, Align.MIN))\n\ncreates a circle who's minimal X and Y values are on the X and Y axis and is located in the top right corner.\nThe ``Align`` enum has values: ``MIN``, ``CENTER`` and ``MAX``.\n\nIn 3D the ``align`` parameter also contains a Z align value but otherwise works in the same way.\n\nNote that the ``align`` will also accept a single ``Align`` value which will be used on all axes -\nas shown here:\n\n.. code-block:: build123d\n\n with BuildSketch():\n Circle(1, align=Align.MIN)","api_names":"align Align BuildSketch CENTER Circle MAX MIN","synonyms":""},"222":{"title":"Custom Objects","body":"All of the objects presented above were created using one of three base object classes:\n:class:`~objects_curve.BaseLineObject` , :class:`~objects_sketch.BaseSketchObject` , and\n:class:`~objects_part.BasePartObject` . Users can use these base object classes to\neasily create custom objects that have all the functionality of the core objects.\n\n.. image:: assets/card_box.svg\n :align: center\n\nHere is an example of a custom sketch object specially created as part of the design of\nthis playing card storage box (:download:`see the playing_cards.py example <../examples/playing_cards.py>`):\n\n.. code-block:: build123d\n\n class Club(BaseSketchObject):\n def __init__(\n self,\n height: float,\n rotation: float = 0,\n align: tuple[Align, Align] = (Align.CENTER, Align.CENTER),\n mode: Mode = Mode.ADD,\n ):\n with BuildSketch() as club:\n with BuildLine():\n l0 = Line((0, -188), (76, -188))\n b0 = Bezier(l0 @ 1, (61, -185), (33, -173), (17, -81))\n b1 = Bezier(b0 @ 1, (49, -128), (146, -145), (167, -67))\n b2 = Bezier(b1 @ 1, (187, 9), (94, 52), (32, 18))\n b3 = Bezier(b2 @ 1, (92, 57), (113, 188), (0, 188))\n mirror(about=Plane.YZ)\n make_face()\n scale(by=height / club.sketch.bounding_box().size.Y)\n super().__init__(obj=club.sketch, rotation=rotation, align=align, mode=mode)\n \n \n\nHere the new custom object class is called ``Club`` and it's a sub-class of\n:class:`~objects_sketch.BaseSketchObject` . The ``__init__`` method contains all\nof the parameters used to instantiate the custom object, specially a ``height``,\n``rotation``, ``align``, and ``mode`` - your objects may contain a sub or super set of\nthese parameters but should always contain a ``mode`` parameter such that it\ncan be combined with a builder's object.\n\nNext is the creation of the object itself, in this case a sketch of the club suit.\n\nThe final line calls the ``__init__`` method of the super class - i.e.\n:class:`~objects_sketch.BaseSketchObject` with its parameters.\n\nThat's it, now the ``Club`` object can be used anywhere a :class:`~objects_sketch.Circle`\nwould be used - with either the Algebra or Builder API.\n\n.. image:: assets/buildline_example_6.svg\n :align: center","api_names":"__init__ align BaseLineObject BasePartObject BaseSketchObject Bezier bounding_box box BuildLine BuildSketch Circle Club height Line make_face mirror mode rotation scale super","synonyms":"reflect symmetry"},"223":{"title":"Mode","body":"With the Builder API the ``mode`` parameter controls how objects are combined with lines, sketches, or parts\nunder construction. The ``Mode`` enum has values:\n\n* ``ADD``: fuse this object to the object under construction\n* ``SUBTRACT``: cut this object from the object under construction\n* ``INTERSECT``: intersect this object with the object under construction\n* ``REPLACE``: replace the object under construction with this object\n* ``PRIVATE``: don't interact with the object under construction at all\n\nThe Algebra API doesn't use the ``mode`` parameter - users combine objects with operators.","api_names":"ADD INTERSECT mode Mode PRIVATE REPLACE SUBTRACT","synonyms":""},"224":{"title":"Objects","body":"Objects are Python classes that take parameters as inputs and create 1D, 2D or 3D Shapes.\nFor example, a :class:`~objects_part.Torus` is defined by a major and minor radii. In\nBuilder mode, objects are positioned with ``Locations`` while in Algebra mode, objects\nare positioned with the ``*`` operator and shown in these examples:\n\n.. code-block:: build123d\n\n with BuildPart() as disk:\n with BuildSketch():\n Circle(a)\n with Locations((b, 0.0)):\n Rectangle(c, c, mode=Mode.SUBTRACT)\n with Locations((0, b)):\n Circle(d, mode=Mode.SUBTRACT)\n extrude(amount=c)\n\n.. code-block:: build123d\n\n sketch = Circle(a) - Pos(b, 0.0) * Rectangle(c, c) - Pos(0.0, b) * Circle(d)\n disk = extrude(sketch, c)\n\nThe following sections describe the 1D, 2D and 3D objects:","api_names":"BuildPart BuildSketch Circle extrude Locations Pos Rectangle Torus","synonyms":"array channel groove path cut pattern repeat"},"225":{"title":"Reference","body":".. py:module:: objects_curve\n\n.. autoclass:: BaseLineObject\n.. autoclass:: Airfoil\n.. autoclass:: Bezier\n.. autoclass:: BlendCurve\n.. autoclass:: BSpline\n.. autoclass:: CenterArc\n.. autoclass:: ConstrainedArcs\n.. autoclass:: ConstrainedLines\n.. autoclass:: DoubleTangentArc\n.. autoclass:: EllipticalCenterArc\n.. autoclass:: EllipticalStartArc\n.. autoclass:: ParabolicCenterArc\n.. autoclass:: HyperbolicCenterArc\n.. autoclass:: FilletPolyline\n.. autoclass:: Helix\n.. autoclass:: IntersectingLine\n.. autoclass:: JernArc\n.. autoclass:: Line\n.. autoclass:: PolarLine\n.. autoclass:: Polyline\n.. autoclass:: RadiusArc\n.. autoclass:: SagittaArc\n.. autoclass:: Spline\n.. autoclass:: TangentArc\n.. autoclass:: ThreePointArc\n.. autoclass:: ArcArcTangentLine\n.. autoclass:: ArcArcTangentArc\n.. image:: assets/objects/arcarctangentarc_keep_table.png\n :alt: ArcArcTangentArc keep table\n :align: center\n\n.. autoclass:: PointArcTangentLine\n.. autoclass:: PointArcTangentArc","api_names":"Airfoil ArcArcTangentArc ArcArcTangentLine BaseLineObject Bezier BlendCurve BSpline CenterArc ConstrainedArcs ConstrainedLines DoubleTangentArc EllipticalCenterArc EllipticalStartArc FilletPolyline Helix HyperbolicCenterArc IntersectingLine JernArc Line ParabolicCenterArc PointArcTangentArc PointArcTangentLine PolarLine Polyline RadiusArc SagittaArc Spline TangentArc ThreePointArc","synonyms":"bevel edge coil control points interpolation round edge smooth curve spiral thread path"},"226":{"title":"Reference","body":".. py:module:: objects_sketch\n\n.. autoclass:: BaseSketchObject\n.. autoclass:: drafting.Arrow\n.. autoclass:: drafting.ArrowHead\n.. autoclass:: Circle\n.. autoclass:: drafting.DimensionLine\n.. autoclass:: Ellipse\n.. autoclass:: drafting.ExtensionLine\n.. autoclass:: Polygon\n.. autoclass:: Rectangle\n.. autoclass:: RectangleRounded\n.. autoclass:: RegularPolygon\n.. autoclass:: SlotArc\n.. autoclass:: SlotCenterPoint\n.. autoclass:: SlotCenterToCenter\n.. autoclass:: SlotOverall\n.. autoclass:: drafting.TechnicalDrawing\n.. autoclass:: Text\n.. autoclass:: Trapezoid\n.. autoclass:: Triangle","api_names":"Arrow ArrowHead BaseSketchObject Circle DimensionLine Ellipse ExtensionLine Polygon Rectangle RectangleRounded RegularPolygon SlotArc SlotCenterPoint SlotCenterToCenter SlotOverall TechnicalDrawing Text Trapezoid Triangle","synonyms":""},"227":{"title":"Reference","body":".. py:module:: objects_part\n\n.. autoclass:: BasePartObject\n.. autoclass:: Box\n.. autoclass:: Cone\n.. autoclass:: ConvexPolyhedron\n.. autoclass:: CounterBoreHole\n.. autoclass:: CounterSinkHole\n.. autoclass:: Cylinder\n.. autoclass:: Hole\n.. autoclass:: Sphere\n.. autoclass:: Torus\n.. autoclass:: Wedge","api_names":"BasePartObject Box Cone ConvexPolyhedron CounterBoreHole CounterSinkHole Cylinder Hole Sphere Torus Wedge","synonyms":"bore drill recessed fastener"},"228":{"title":"Text","body":".. include:: objects/text.rst","api_names":"","synonyms":""},"229":{"title":"Conclusion","body":"While OpenSCAD and build123d share the goal of empowering users to create parametric 3D \nmodels, their approaches differ significantly. Embracing build123d’s workflow of building \nwith lower-dimensional objects and applying extrusion, lofting, sweeping, or revolution \nwill unlock its full potential and lead to better design outcomes.","api_names":"","synonyms":"blend profiles channel cross sections groove path cut transition"},"230":{"title":"Example Comparison","body":"To illustrate the advantages of this approach, compare a simple model in OpenSCAD and \nbuild123d of a piece of angle iron:\n\n**OpenSCAD Approach**\n\n.. code-block:: openscad\n\n $fn = 100; // Increase the resolution for smooth fillets\n\n // Dimensions\n length = 100; // 10 cm long\n width = 30; // 3 cm wide\n thickness = 4; // 4 mm thick\n fillet = 5; // 5 mm fillet radius\n delta = 0.001; // a small number\n\n // Create the angle iron\n difference() {\n // Outer shape\n cube([width, length, width], center = false);\n // Inner shape\n union() {\n translate([thickness+fillet,-delta,thickness+fillet])\n rotate([-90,0,0])\n cylinder(length+2*delta, fillet,fillet);\n translate([thickness,-delta,thickness+fillet])\n cube([width-thickness,length+2*delta,width-fillet],center=false);\n translate([thickness+fillet,-delta,thickness])\n cube([width-fillet,length+2*delta,width-thickness],center=false);\n \n }\n }\n\n**build123d Approach**\n\n.. code-block:: build123d\n\n # Builder mode\n with BuildPart() as angle_iron:\n with BuildSketch() as profile:\n Rectangle(3 * CM, 4 * MM, align=Align.MIN)\n Rectangle(4 * MM, 3 * CM, align=Align.MIN)\n extrude(amount=10 * CM)\n fillet(angle_iron.edges().filter_by(lambda e: e.is_interior), 5 * MM)\n\n\n.. code-block:: build123d\n\n # Algebra mode\n profile = Rectangle(3 * CM, 4 * MM, align=Align.MIN)\n profile += Rectangle(4 * MM, 3 * CM, align=Align.MIN)\n angle_iron = extrude(profile, 10 * CM)\n angle_iron = fillet(angle_iron.edges().filter_by(lambda e: e.is_interior), 5 * MM)\n\n.. image:: ./assets/AngleIron.png\n\nOpenSCAD and build123d offer distinct paradigms for creating 3D models, as demonstrated\nby the angle iron example. OpenSCAD relies on Constructive Solid Geometry (CSG) operations, \ncombining and subtracting 3D shapes like cubes and cylinders. Fillets are approximated by \nmanually adding high-resolution cylinders, making adjustments cumbersome and less precise. \nThis static approach can handle simple models but becomes challenging for complex or iterative designs.\n\nIn contrast, build123d emphasizes a profile-driven workflow. It starts with a 2D sketch, \ndefining the geometry’s outline, which is then extruded or otherwise transformed into a \n3D model. Features like fillets are applied dynamically by querying topological elements, \nsuch as edges, using intuitive filtering methods. This approach ensures precision and \nflexibility, making changes straightforward without the need for manual repositioning or realignment.\n\nThe build123d methodology is computationally efficient, leveraging mathematical precision \nfor features like fillets. By separating the design into manageable steps-sketching, extruding, \nand refining-it aligns with traditional CAD practices and enhances readability, modularity, \nand maintainability. Unlike OpenSCAD, build123d’s dynamic querying of topological features \nallows for easy updates and adjustments, making it better suited for modern, complex, and \niterative design workflows.\n\nIn summary, build123d’s sketch-based paradigm and topological querying capabilities provide \nsuperior precision, flexibility, and efficiency compared to OpenSCAD’s static, CSG-centric \napproach, making it a better choice for robust and adaptable CAD modeling.","api_names":"BuildPart BuildSketch cube cylinder difference edges extrude fillet filter_by Geometry Rectangle rotate translate union","synonyms":"bevel edge round edge"},"231":{"title":"Moving Beyond Constructive Solid Geometry (CSG)","body":"OpenSCAD's modeling paradigm heavily relies on Constructive Solid Geometry (CSG) to build \nmodels by combining and subtracting 3D solids. While build123d supports similar operations, \nits design philosophy encourages a fundamentally different, often more efficient approach: \nstarting with lower-dimensional entities like faces and edges and then transforming them \ninto solids.","api_names":"Geometry","synonyms":""},"232":{"title":"Refining the Model","body":"After creating the initial 3D shape, you can refine the model by adding details or making \nmodifications using build123d's advanced features, such as:\n\n- **Fillets and Chamfers**: Smooth or bevel edges to enhance the design.\n- **Boolean Operations**: Combine, subtract, or intersect 3D shapes to achieve the desired \n geometry.","api_names":"","synonyms":"bevel edge round edge"},"233":{"title":"Tips for Transitioning","body":"- **Think in Lower Dimensions**: Begin with 1D curves or 2D sketches as the foundation \n and progressively build upwards into 3D shapes.\n\n- **Leverage Topological References**: Use build123d's powerful selector system to \n reference features of existing objects for creating new ones. For example, apply \n inside or outside fillets and chamfers to vertices and edges of an existing part \n with precision.\n\n- **Operational Equivalency and Beyond**: Build123d provides equivalents to almost all \n features available in OpenSCAD, with the exception of the 3D **minkowski** operation. \n However, a 2D equivalent, **make_hull**, is available in build123d. Beyond operational \n equivalency, build123d offers a wealth of additional functionality, including advanced \n features like topological queries, dynamic filtering, and robust tools for creating complex \n geometries. By exploring build123d's extensive operations, you can unlock new possibilities \n and take your designs far beyond the capabilities of OpenSCAD.\n\n- **Explore the Documentation**: Dive into build123d’s comprehensive API documentation \n to unlock its full potential and discover advanced features.\n \nBy shifting your design mindset from solid-based CSG to a profile-driven approach, you \ncan fully harness build123d's capabilities to create precise, efficient, and complex models. \nWelcome aboard, and happy designing!","api_names":"","synonyms":"bevel edge round edge"},"234":{"title":"Transitioning from OpenSCAD","body":"Welcome to build123d! If you're familiar with OpenSCAD, you'll notice key differences in \nhow models are constructed. This guide is designed to help you adapt your design approach \nand understand the fundamental differences in modeling philosophies. While OpenSCAD relies \nheavily on Constructive Solid Geometry (CSG) to combine primitive 3D shapes like cubes and \nspheres, build123d encourages a more flexible and efficient workflow based on building \nlower-dimensional objects.","api_names":"Geometry","synonyms":""},"235":{"title":"Using a More Traditional CAD Design Workflow","body":"Most industry-standard CAD packages recommend starting with a sketch (a 2D object) and \ntransforming it into a 3D model-a design philosophy that is central to build123d.\n\nIn build123d, the design process typically begins with defining the outline of an object. \nThis might involve creating a complex 1D object using **BuildLine**, which provides tools \nfor constructing intricate wireframe geometries. The next step involves converting these \n1D objects into 2D sketches using **BuildSketch**, which offers a wide range of 2D primitives \nand advanced capabilities, such as:\n\n- **make_face**: Converts a 1D **BuildLine** object into a planar 2D face.\n- **make_hull**: Generates a convex hull from a 1D **BuildLine** object.\n\nOnce a 2D profile is created, it can be transformed into 3D objects in a **BuildPart** context \nusing operations such as:\n\n- **Extrusion**: Extends a 2D profile along a straight path to create a 3D shape.\n- **Revolution**: Rotates a 2D profile around an axis to form a symmetrical 3D object.\n- **Lofting**: Connects multiple 2D profiles along a path to create smooth transitions \n between shapes.\n- **Sweeping**: Moves a 2D profile along a defined path to create a 3D form.","api_names":"sketch","synonyms":"blend profiles channel cross sections groove path cut transition"},"236":{"title":"Why Transition Away from CSG?","body":"CSG is a powerful method for creating 3D models, but it has limitations when dealing with \ncomplex designs. build123d’s approach offers several advantages:\n\n- **Simplified Complexity Management**: \n Working with 2D profiles and faces instead of directly manipulating 3D solids simplifies \n your workflow. In large models, the number of operations on solids can grow exponentially, \n making it difficult to manage and debug. Building with 2D profiles helps keep designs \n modular and organized.\n\n- **Improved Robustness**: \n Operations on 2D profiles are inherently less computationally intensive and \n less error-prone than equivalent operations on 3D solids. This robustness ensures smoother \n workflows and reduces the likelihood of failing operations in complex models.\n\n- **Enhanced Efficiency**: \n Constructing models from 2D profiles using operations like **extruding**, **lofting**, \n **sweeping**, or **revolving** is computationally faster. These methods also provide \n greater design flexibility, enabling you to create intricate forms with ease.\n\n- **Better Precision and Control**: \n Starting with 2D profiles allows for more precise geometric control. Constraints, dimensions, \n and relationships between entities can be established more effectively in 2D, ensuring a solid \n foundation for your 3D design.","api_names":"","synonyms":"blend profiles channel cross sections groove path cut transition"},"237":{"title":"Why Transition to build123d?","body":"Transitioning to build123d allows you to harness a modern and efficient approach to 3D modeling. \nBy starting with lower-dimensional objects and leveraging powerful transformation tools, you can \ncreate precise, complex designs with ease. This workflow emphasizes modularity and maintainability, \nenabling quick modifications and reducing computational complexity.","api_names":"","synonyms":""},"238":{"title":"Operations","body":"Operations are functions that take objects as inputs and transform them into new objects. For example, a 2D Sketch can be extruded to create a 3D Part. All operations are Python functions which can be applied using both the Algebra and Builder APIs. It's important to note that objects created by operations are not affected by ``Locations``, meaning their position is determined solely by the input objects used in the operation.\n\nHere are a couple ways to use :func:`~operations_part.extrude`, in Builder and Algebra mode:\n\n.. code-block:: build123d\n\n with BuildPart() as cylinder:\n with BuildSketch():\n Circle(radius)\n extrude(amount=height)\n\n.. code-block:: build123d\n\n cylinder = extrude(Circle(radius), amount=height)\n\nThe following table summarizes all of the available operations. Operations marked as 1D are\napplicable to BuildLine and Algebra Curve, 2D to BuildSketch and Algebra Sketch, 3D to\nBuildPart and Algebra Part.\n\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| Operation | Description | 0D | 1D | 2D | 3D | Example |\n+==============================================+====================================+====+====+====+====+===================================+\n| :func:`~operations_generic.add` | Add object to builder | | ✓ | ✓ | ✓ | :ref:`16 ` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_generic.bounding_box` | Add bounding box as Shape | | ✓ | ✓ | ✓ | |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_generic.chamfer` | Bevel Vertex or Edge | | | ✓ | ✓ | :ref:`9 ` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_part.draft` | Add a draft taper to a part | | | | ✓ | :ref:`examples-cast_bearing_unit` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_part.extrude` | Draw 2D Shape into 3D | | | | ✓ | :ref:`3 ` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_generic.fillet` | Radius Vertex or Edge | | | ✓ | ✓ | :ref:`9 ` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_sketch.full_round` | Round-off Face along given Edge | | | ✓ | | :ref:`ttt-24-spo-06` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_part.loft` | Create 3D Shape from sections | | | | ✓ | :ref:`24 ` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_part.make_brake_formed` | Create sheet metal parts | | | | ✓ | |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_sketch.make_face` | Create a Face from Edges | | | ✓ | | :ref:`4 ` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_sketch.make_hull` | Create Convex Hull from Edges | | | ✓ | | |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_generic.mirror` | Mirror about Plane | | ✓ | ✓ | ✓ | :ref:`15 ` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_generic.offset` | Inset or outset Shape | | ✓ | ✓ | ✓ | :ref:`25 ` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_generic.project` | Project points, lines or Faces | ✓ | ✓ | ✓ | | |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_part.project_workplane` | Create workplane for projection | | | | | |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_part.revolve` | Swing 2D Shape about Axis | | | | ✓ | :ref:`23 ` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_generic.scale` | Change size of Shape | | ✓ | ✓ | ✓ | |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_part.section` | Generate 2D slices from 3D Shape | | | | ✓ | |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_generic.split` | Divide object by Plane | | ✓ | ✓ | ✓ | :ref:`27 ` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_generic.sweep` | Extrude 1/2D section(s) along path | | | ✓ | ✓ | :ref:`14 ` |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_part.thicken` | Expand 2D section(s) | | | | ✓ | |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n| :func:`~operations_sketch.trace` | Convert lines to faces | | | ✓ | | |\n+----------------------------------------------+------------------------------------+----+----+----+----+-----------------------------------+\n\nThe following table summarizes all of the selectors that can be used within\nthe scope of a Builder. Note that they will extract objects from the builder that is\ncurrently within scope without it being explicitly referenced.\n\n+---------------------------------+--------------------------------------+----------------------+\n| | Builder | \n+---------------------------------+--------------------------------------+------+--------+------+\n| Selector | Description | Line | Sketch | Part |\n+=================================+======================================+======+========+======+\n| :func:`~build_common.edge` | Select edge from current builder | ✓ | ✓ | ✓ |\n+---------------------------------+--------------------------------------+------+--------+------+\n| :func:`~build_common.edges` | Select edges from current builder | ✓ | ✓ | ✓ |\n+---------------------------------+--------------------------------------+------+--------+------+\n| :func:`~build_common.face` | Select face from current builder | | ✓ | ✓ |\n+---------------------------------+--------------------------------------+------+--------+------+\n| :func:`~build_common.faces` | Select faces from current builder | | ✓ | ✓ |\n+---------------------------------+--------------------------------------+------+--------+------+\n| :func:`~build_common.solid` | Select solid from current builder | | | ✓ |\n+---------------------------------+--------------------------------------+------+--------+------+\n| :func:`~build_common.solids` | Select solids from current builder | | | ✓ |\n+---------------------------------+--------------------------------------+------+--------+------+\n| :func:`~build_common.vertex` | Select vertex from current builder | ✓ | ✓ | ✓ |\n+---------------------------------+--------------------------------------+------+--------+------+\n| :func:`~build_common.vertices` | Select vertices from current builder | ✓ | ✓ | ✓ |\n+---------------------------------+--------------------------------------+------+--------+------+\n| :func:`~build_common.wire` | Select wire from current builder | ✓ | ✓ | ✓ |\n+---------------------------------+--------------------------------------+------+--------+------+\n| :func:`~build_common.wires` | Select wires from current builder | ✓ | ✓ | ✓ |\n+---------------------------------+--------------------------------------+------+--------+------+","api_names":"add bounding_box BuildPart BuildSketch chamfer Circle draft edge edges extrude face faces fillet full_round Locations loft make_brake_formed make_face make_hull mirror offset project project_workplane revolve scale section solid solids split sweep thicken trace vertex vertices wire wires","synonyms":"array axisymmetric bevel edge blend profiles channel cross sections cut in half fit gap groove hollow lathe path cut pattern reflect repeat round edge shell slice symmetry tolerance transition trim turned wall thickness"},"239":{"title":"Reference","body":".. autofunction:: operations_generic.add\n.. autofunction:: operations_generic.bounding_box\n.. autofunction:: operations_generic.chamfer\n.. autofunction:: operations_part.draft\n.. autofunction:: operations_part.extrude\n.. autofunction:: operations_generic.fillet\n.. autofunction:: operations_sketch.full_round\n.. autofunction:: operations_part.loft\n.. autofunction:: operations_part.make_brake_formed\n.. autofunction:: operations_sketch.make_face\n.. autofunction:: operations_sketch.make_hull\n.. autofunction:: operations_generic.mirror\n.. autofunction:: operations_generic.offset\n.. autofunction:: operations_generic.project\n.. autofunction:: operations_part.project_workplane\n.. autofunction:: operations_part.revolve\n.. autofunction:: operations_generic.scale\n.. autofunction:: operations_part.section\n.. autofunction:: operations_generic.split\n.. autofunction:: operations_generic.sweep\n.. autofunction:: operations_part.thicken\n.. autofunction:: operations_sketch.trace\n\n.. autofunction:: build_common.edge\n.. autofunction:: build_common.edges\n.. autofunction:: build_common.face\n.. autofunction:: build_common.faces\n.. autofunction:: build_common.solid\n.. autofunction:: build_common.solids\n.. autofunction:: build_common.vertex\n.. autofunction:: build_common.vertices\n.. autofunction:: build_common.wire\n.. autofunction:: build_common.wires","api_names":"add bounding_box chamfer draft edge edges extrude face faces fillet full_round loft make_brake_formed make_face make_hull mirror offset project project_workplane revolve scale section solid solids split sweep thicken trace vertex vertices wire wires","synonyms":"axisymmetric bevel edge blend profiles channel cross sections cut in half fit gap groove hollow lathe path cut reflect round edge shell slice symmetry tolerance transition trim turned wall thickness"},"240":{"title":"Custom Sorting and Filtering","body":"It is important to note that standard list methods such as `sorted` or `filtered` can\nbe used to easily build complex selectors beyond what is available with the predefined\nsorts and filters. Here is an example of a custom filters:\n\n.. code-block:: build123d\n\n with BuildSketch() as din:\n ...\n outside_vertices = filter(\n lambda v: (v.Y == 0.0 or v.Y == height)\n and -overall_width / 2 < v.X < overall_width / 2,\n din.vertices(),\n )\n\nThe :meth:`~topology.ShapeList.filter_by` method can take lambda expressions as part of a\nfluent chain of operations which enables integration of custom filters into a larger change of\nselectors as shown in this example:\n\n.. code-block:: build123d\n\n obj = Box(1, 1, 1) - Cylinder(0.2, 1)\n faces_with_holes = obj.faces().filter_by(lambda f: f.inner_wires())\n\n.. image:: assets/custom_selector.png \n\nHere the two faces with \"inner_wires\" (i.e. holes) have been selected independent of orientation.","api_names":"Box BuildSketch Cylinder faces filter filter_by inner_wires vertices","synonyms":"bore drill recessed fastener"},"241":{"title":"Quick Reference","body":"The following tables describes the build123d selectors:\n\n+-------------+-----------------------------------+-------------------+-------------------+\n| Selector | Applicability | Description | Example |\n+=============+===================================+===================+===================+\n| vertices() | BuildLine, BuildSketch, BuildPart | Vertex extraction | `part.vertices()` |\n+-------------+-----------------------------------+-------------------+-------------------+\n| edges() | BuildLine, BuildSketch, BuildPart | Edge extraction | `part.edges()` |\n+-------------+-----------------------------------+-------------------+-------------------+\n| wires() | BuildLine, BuildSketch, BuildPart | Wire extraction | `part.wires()` |\n+-------------+-----------------------------------+-------------------+-------------------+\n| faces() | BuildSketch, BuildPart | Face extraction | `part.faces()` |\n+-------------+-----------------------------------+-------------------+-------------------+\n| solids() | BuildPart | Solid extraction | `part.solids()` |\n+-------------+-----------------------------------+-------------------+-------------------+\n\n.. _selector_operators:\n\n+----------+-----------------------+--------------------+-------------------------------------------------------+---------------------------------------------------------------------------+\n| Operator | Operand | Method | Description | Example |\n+==========+=======================+====================+=======================================================+===========================================================================+\n| > | SortBy, Axis | sort_by | Sort ShapeList by operand | `part.vertices() > Axis.Z` |\n+----------+-----------------------+--------------------+-------------------------------------------------------+---------------------------------------------------------------------------+\n| < | SortBy, Axis | sort_by | Reverse sort ShapeList by operand | `part.faces() < Axis.Z` |\n+----------+-----------------------+--------------------+-------------------------------------------------------+---------------------------------------------------------------------------+\n| >> | SortBy, Axis | group_by | Group ShapeList by operand and return last value | `part.solids() >> Axis.X` |\n+----------+-----------------------+--------------------+-------------------------------------------------------+---------------------------------------------------------------------------+\n| << | SortBy, Axis | group_by | Group ShapeList by operand and return first value | `part.faces() << Axis.Y` |\n+----------+-----------------------+--------------------+-------------------------------------------------------+---------------------------------------------------------------------------+\n| \\| | Axis, Plane, GeomType | filter_by | Filter and sort ShapeList by Axis, Plane, or GeomType | `part.faces() \\| Axis.Z` |\n+----------+-----------------------+--------------------+-------------------------------------------------------+---------------------------------------------------------------------------+\n| [] | | | Standard python list indexing and slicing | `part.faces()[-2:]` |\n+----------+-----------------------+--------------------+-------------------------------------------------------+---------------------------------------------------------------------------+\n| | Axis | filter_by_position | Filter ShapeList by Axis & mix / max values | `part.faces()..filter_by_position(Axis.Z, 1, 2, inclusive=(False, True))` |\n+----------+-----------------------+--------------------+-------------------------------------------------------+---------------------------------------------------------------------------+\n\nThe operand types are: Axis, Plane, SortBy, and GeomType. An Axis is a base object with an origin and a\ndirection with several predefined values such as ``Axis.X``, ``Axis.Y``, and ``Axis.Z``; however,\nany Axis could be used as an operand (e.g. ``Axis((1,2,3),(0.5,0,-0.5))`` is valid) - see\n:class:`~geometry.Axis` for a complete description.\nA Plane is a coordinate system defined by an origin, x_dir (X direction), y_dir (Y direction), and\nz_dir (Z direction). See :class:`~geometry.Plane` for a complete description.\nFiltering by a Plane will return faces/edges parallel to it.\nSortBy and GeomType are python\nEnum class described here:\n\n:class:`~build_enums.GeomType`\n BEZIER, BSPLINE, CIRCLE, CONE, CYLINDER, ELLIPSE, EXTRUSION, HYPERBOLA, LINE, OFFSET, OTHER,\n PARABOLA, PLANE, REVOLUTION, SPHERE, TORUS\n:class:`~build_enums.SortBy`\n LENGTH, RADIUS, AREA, VOLUME, DISTANCE","api_names":"Axis edges faces filter_by_position GeomType operand Plane solids SortBy vertices wires X x_dir Y y_dir Z z_dir","synonyms":"control points fit gap hollow interpolation shell smooth curve tolerance wall thickness"},"242":{"title":"ShapeList Class","body":"The builders include methods to extract Edges, Faces, Solids, Vertices, or Wires from the objects\nthey are building. All of these methods return objects of a subclass of `list`, a :class:`~topology.ShapeList` with\ncustom filtering and sorting methods and operations as follows.","api_names":"ShapeList","synonyms":""},"243":{"title":"Code","body":".. code-block:: build123d\n\n from datetime import date\n \n from bd_warehouse.open_builds import StepperMotor\n from build123d import *\n from ocp_vscode import show\n \n \n def project_to_2d(\n part: Part,\n viewport_origin: VectorLike,\n viewport_up: VectorLike,\n page_origin: VectorLike,\n scale_factor: float = 1.0,\n ) -> tuple[ShapeList[Edge], ShapeList[Edge]]:\n \"\"\"project_to_2d\n \n Helper function to generate 2d views translated on the 2d page.\n \n Args:\n part (Part): 3d object\n viewport_origin (VectorLike): location of viewport\n viewport_up (VectorLike): direction of the viewport Y axis\n page_origin (VectorLike): center of 2d object on page\n scale_factor (float, optional): part scalar. Defaults to 1.0.\n \n Returns:\n tuple[ShapeList[Edge], ShapeList[Edge]]: visible & hidden edges\n \"\"\"\n scaled_part = part if scale_factor == 1.0 else scale(part, scale_factor)\n visible, hidden = scaled_part.project_to_viewport(\n viewport_origin, viewport_up, look_at=(0, 0, 0)\n )\n visible = [Pos(*page_origin) * e for e in visible]\n hidden = [Pos(*page_origin) * e for e in hidden]\n \n return ShapeList(visible), ShapeList(hidden)\n \n \n # The object that appearing in the drawing\n stepper: Part = StepperMotor(\"Nema23\")\n \n # Create a standard technical drawing border on A4 paper\n border = TechnicalDrawing(\n designed_by=\"build123d\",\n design_date=date.fromisoformat(\"2025-05-23\"),\n page_size=PageSize.A4,\n title=\"Nema 23 Stepper\",\n sub_title=\"Units: mm\",\n drawing_number=\"BD-1\",\n sheet_number=1,\n drawing_scale=1,\n )\n page_size = border.bounding_box().size\n \n # Specify the drafting options for extension lines\n drafting_options = Draft(font_size=3.5, decimal_precision=1, display_units=False)\n \n # Lists used to store the 2d visible and hidden lines\n visible_lines, hidden_lines = [], []\n \n # Isometric Projection - A 3D view where the part is rotated to reveal three\n # dimensions equally.\n iso_v, iso_h = project_to_2d(\n stepper,\n (100, 100, 100),\n (0, 0, 1),\n page_size * 0.3,\n 0.75,\n )\n visible_lines.extend(iso_v)\n hidden_lines.extend(iso_h)\n \n # Plan View (Top) - The view from directly above the part (looking down along\n # the Z-axis).\n vis, _ = project_to_2d(\n stepper,\n (0, 0, 100),\n (0, 1, 0),\n (page_size.X * -0.3, page_size.Y * 0.25),\n )\n visible_lines.extend(vis)\n \n # Dimension the top of the stepper\n top_bbox = Curve(vis).bounding_box()\n perimeter = Pos(*top_bbox.center()) * Rectangle(top_bbox.size.X, top_bbox.size.Y)\n d1 = ExtensionLine(\n border=perimeter.edges().sort_by(Axis.X)[-1], offset=1 * CM, draft=drafting_options\n )\n d2 = ExtensionLine(\n border=perimeter.edges().sort_by(Axis.Y)[0], offset=1 * CM, draft=drafting_options\n )\n # Add a label\n l1 = Text(\"Plan View\", 6)\n l1.position = vis.sort_by(Axis.Y)[-1].center() + (0, 5 * MM)\n \n # Front Elevation - The primary view, typically looking along the Y-axis,\n # showing the height.\n vis, _ = project_to_2d(\n stepper,\n (0, -100, 0),\n (0, 0, 1),\n (page_size.X * -0.3, page_size.Y * -0.125),\n )\n visible_lines.extend(vis)\n d3 = ExtensionLine(\n border=vis.sort_by(Axis.Y)[-1], offset=-5 * MM, draft=drafting_options\n )\n l2 = Text(\"Front Elevation\", 6)\n l2.position = vis.group_by(Axis.Y)[0].sort_by(Edge.length)[-1].center() + (0, -5 * MM)\n \n # Side Elevation - Often refers to the Right Side View, looking along the X-axis.\n vis, _ = project_to_2d(\n stepper,\n (100, 0, 0),\n (0, 0, 1),\n (0, page_size.Y * 0.15),\n )\n visible_lines.extend(vis)\n side_bbox = Curve(vis).bounding_box()\n shaft_top_corner = vis.edges().sort_by(Axis.Y)[-1].vertices().sort_by(Axis.X)[-1]\n body_bottom_corner = (side_bbox.max.X, side_bbox.min.Y)\n d4 = ExtensionLine(\n border=(shaft_top_corner, body_bottom_corner),\n offset=-(side_bbox.max.X - shaft_top_corner.X) - 1 * CM, # offset to outside view.\n measurement_direction=(0, 1, 0),\n draft=drafting_options,\n )\n l3 = Text(\"Side Elevation\", 6)\n l3.position = vis.group_by(Axis.Y)[0].sort_by(Edge.length)[-1].center() + (0, -5 * MM)\n \n \n # Initialize the SVG exporter\n exporter = ExportSVG(unit=Unit.MM)\n # Define visible and hidden line layers\n exporter.add_layer(\"Visible\")\n exporter.add_layer(\"Hidden\", line_color=(99, 99, 99), line_type=LineType.ISO_DOT)\n # Add the objects to the appropriate layer\n exporter.add_shape(visible_lines, layer=\"Visible\")\n exporter.add_shape(hidden_lines, layer=\"Hidden\")\n exporter.add_shape(border, layer=\"Visible\")\n exporter.add_shape([d1, d2, d3, d4], layer=\"Visible\")\n exporter.add_shape([l1, l2, l3], layer=\"Visible\")\n # Write the file\n exporter.write(f\"assets/stepper_drawing.svg\")\n \n show(border, visible_lines, d1, d2, d3, d4, l1, l2, l3)","api_names":"add_layer add_shape bounding_box center Curve Draft edges ExportSVG extend ExtensionLine fromisoformat group_by page_origin part Pos project_to_2d project_to_viewport Rectangle scale scale_factor ShapeList show sort_by StepperMotor TechnicalDrawing Text vertices View viewport_origin viewport_up write","synonyms":"fit gap hollow shell tolerance wall thickness"},"244":{"title":"Dependencies","body":"This example depends on the following packages:\n\n- `build123d`\n- `bd_warehouse` (for the `StepperMotor` part)\n- `ocp_vscode` (for local preview)","api_names":"","synonyms":""},"245":{"title":"How It Works","body":"The script uses the `project_to_viewport` method to project the 3D part geometry into 2D.\nA helper function, `project_to_2d`, sets up the viewport (camera origin and up direction)\nand places the result onto a virtual drawing sheet.\n\nThe steps involved are:\n\n1. Load or construct a 3D part (in this case, a stepper motor).\n2. Define a `TechnicalDrawing` border and title block using A4 page size.\n3. Generate each of the standard views and apply transformations to place them.\n4. Add dimensions using `ExtensionLine` and labels using `Text`.\n5. Export the drawing using `ExportSVG`, separating visible and hidden edges by layer\n and style.","api_names":"part viewport","synonyms":""},"246":{"title":"Overview","body":"A technical drawing represents a 3D object in 2D using a series of standardized views.\nThese include:\n\n- **Plan (Top View)** – as seen from directly above (Z-axis down)\n- **Front Elevation** – looking at the object head-on (Y-axis forward)\n- **Side Elevation (Right Side)** – viewed from the right (X-axis)\n- **Isometric Projection** – a 3D perspective view to help visualize depth\n\nEach view is aligned to a position on the page and optionally scaled or annotated.","api_names":"above Elevation on Plan right","synonyms":""},"247":{"title":"Result","body":".. image:: /assets/stepper_drawing.svg\n :alt: Stepper motor technical drawing\n :class: align-center\n :width: 80%","api_names":"","synonyms":""},"248":{"title":"Technical Drawing Tutorial","body":"This example demonstrates how to generate a standard technical drawing of a 3D part\nusing `build123d`. It creates orthographic and isometric views of a Nema 23 stepper\nmotor and exports the result as an SVG file suitable for printing or inspection.","api_names":"","synonyms":""},"249":{"title":"Try It Yourself","body":"You can modify the script to:\n\n- Replace the part with your own `Part` model\n- Adjust camera angles and scale\n- Add other views (bottom, rear)\n- Enhance with more labels and dimensions","api_names":"views","synonyms":""},"250":{"title":"2D before 3D","body":"When creating complex 3D objects, it is generally best to start with 2D work before\nmoving on to 3D. This is because 3D structures are much more intricate, and 3D operations\ncan be slower and more prone to failure. For designers who come from a Constructive Solid\nGeometry (CSG) background, such as OpenSCAD, this approach may seem counterintuitive. On\nthe other hand, designers from a GUI BREP CAD background, like Fusion 360 or SolidWorks,\nmay find this approach more natural.\n\nIn practice, this means that 3D objects are often created by applying operations like\n:func:`~operations_part.extrude` or :func:`~operations_part.revolve` to 2D sketches, as shown below:\n\n.. code:: python\n\n with BuildPart() as my_part:\n with BuildSketch() as part_profile:\n ...\n extrude(amount=some_distance)\n ...\n\nWith this structure ``part_profile`` may have many objects that are combined and\nmodified by operations like :func:`~operations_generic.fillet` before being extruded\nto a 3D shape.","api_names":"BuildPart BuildSketch extrude fillet Geometry part_profile revolve","synonyms":"axisymmetric bevel edge lathe round edge turned"},"251":{"title":"Build123d - CadQuery Integration","body":"As both `CadQuery `_ and **build123d** use\na common OpenCascade Python wrapper (`OCP `_) it's possible to\ninterchange objects both from CadQuery to build123d and vice-versa by transferring the ``wrapped`` \nobjects as follows (first from CadQuery to build123d):\n\n.. code-block:: build123d\n\n import build123d as b3d\n b3d_solid = b3d.Solid.make_box(1,1,1)\n\n ... some cadquery stuff ...\n\n b3d_solid.wrapped = cq_solid.wrapped\n\nSecondly, from build123d to CadQuery as follows:\n\n.. code-block:: build123d\n\n import build123d as b3d\n import cadquery as cq\n\n with b3d.BuildPart() as b123d_box:\n b3d.Box(1,2,3)\n\n cq_solid = cq.Solid.makeBox(1,1,1)\n cq_solid.wrapped = b123d_box.part.solid().wrapped","api_names":"Box BuildPart follows make_box makeBox solid wrapped wrapper","synonyms":""},"252":{"title":"Can't Get There from Here","body":"Unfortunately, it's a reality that not all parts described using build123d can be\nsuccessfully constructed by the underlying CAD core. Designers may have to\nexplore different design approaches to get the OpenCascade CAD core to successfully\nbuild the target object. For instance, if a multi-section :func:`~operations_generic.sweep`\noperation fails, a :func:`~operations_part.loft` operation may be a viable alternative\nin certain situations. It's crucial to remember that CAD is a complex field and\npatience may be required to achieve the desired results.","api_names":"loft sweep","synonyms":"blend profiles channel cross sections groove path cut transition"},"253":{"title":"Delay Chamfers and Fillets","body":"Chamfers and fillets can add complexity to a design by transforming simple vertices\nor edges into arcs or non-planar faces. This can significantly increase the complexity\nof the design. To avoid unnecessary processing costs and potential errors caused by a\nneedlessly complicated design, it's recommended to perform these operations towards\nthe end of the object's design. This is especially true for 3D shapes, as it is\nsometimes necessary to fillet or chamfer in the 2D design phase. Luckily, these\n2D fillets and chamfers are less likely to fail than their 3D counterparts.","api_names":"","synonyms":"bevel edge round edge"},"254":{"title":"Don't Builders inherit workplane/coordinate systems when nested","body":"Some users expect that nested Builders will inherit the workplane or coordinate system from\ntheir parent Builder - this is not true. When a Builder is instantiated, a workplane is either\nprovided by the user or it defaults to ``Plane.XY``. Having Builders inherent coordinate systems\nfrom their parents could result in confusion when they are nested as well as change their\nbehaviour depending on which scope they are in. Inheriting coordinate systems isn't necessarily \nincorrect, it was considered for build123d but ultimately the simple static approach was taken.","api_names":"XY","synonyms":""},"255":{"title":"Isn’t ``from build123d import *`` bad practice?","body":"Glob imports like ``from build123d import *`` are generally frowned upon when writing software, and for\ngood reason. They pollute the global namespace, cause confusing collisions, and are not future-proof, as\nfuture changes to the library being imported could collide with other names. It would be much safer to do \nsomething like ``import build123d as bd`` and then reference every item with, for example, ``bd.BuildPart()``.\nIf your goal is to integrate build123d into a larger piece of software, which many people work on, or where\nlong-term maintainability is a priority, using this approach is definitely a good idea! Why then, are\nglob imports so often used in build123d code and official examples?\n\nbuild123d is most commonly used not as a library within a larger application, but as a `Domain-Specific Language `__\nwhich, together with something like the OCP CAD Viewer, acts as the user interface for a CAD application.\nWriting build123d often involves live coding in a REPL or typing in editors with limited space due to\nthe rest of the CAD GUI taking up screen space. Scripts are usually centred around build123d usage, with\nusage of other libraries being limited enough that naming conflicts are easily avoided. In this context,\nit’s entirely reasonable to prioritise developer ergonomics over “correctness” by making build123d’s primitives\navailable in the global namespace.","api_names":"BuildPart from import","synonyms":""},"256":{"title":"Object Selection","body":"When selecting features in a design it's sometimes easier to select an object from\nhigher up in the topology first, then select the object from there. For example let's\nconsider a plate with four chamfered holes like this:\n\n.. image:: assets/plate.svg\n :align: center\n\nWhen selecting edges to be chamfered one might first select the face that these edges\nbelong to then select the edges as shown here:\n\n.. code-block:: build123d\n\n from build123d import *\n\n svg_opts = {\"pixel_scale\": 5, \"show_axes\": False, \"show_hidden\": True}\n\n length, width, thickness = 80.0, 60.0, 10.0\n hole_dia = 6.0\n\n with BuildPart() as plate:\n Box(length, width, thickness)\n with GridLocations(length - 20, width - 20, 2, 2):\n Hole(radius=hole_dia / 2)\n top_face: Face = plate.faces().sort_by(Axis.Z)[-1]\n hole_edges = top_face.edges().filter_by(GeomType.CIRCLE)\n chamfer(hole_edges, length=1)","api_names":"Box BuildPart chamfer edges faces filter_by GridLocations Hole sort_by","synonyms":"array bevel edge bore drill pattern recessed fastener repeat round edge"},"257":{"title":"Packing Objects on a Plane","body":"When designing independent shapes it's common to place each at or near\nthe global origin, which can make it tricky to visualize many shapes at\nonce. :meth:`pack.pack` will translate the :class:`~topology.Shape`'s passed to it so\nthat they don't overlap, with an optional padding/spacing. Here's the\nresult of packing a bunch of overlapping boxes (left) using some\npadding (right):\n\n.. image:: assets/packed_boxes_input.svg\n :width: 200\n :align: left\n\n.. image:: assets/packed_boxes_output.svg\n :align: right\n\n\nBy default, the original Z value of all objects packed using the :meth:`pack.pack` function is preserved. \nIf you want to align all objects so that they are \"placed\" on the zero Z coordinate, the :meth:`pack` \nfunction has an `align_z` argument. When set to `True`, this will align all objects. \n\nThis can be useful, for example, when preparing print setups for 3D printing, giving you full control \nover this alignment so you don't have to leave it to the slicer.\n\n\n.. _are_glob_imports_bad_practice:","api_names":"boxes pack padding Shape","synonyms":""},"258":{"title":"Parameterize","body":"One of the most powerful features of build123d is the ability to design fully\nparameterized parts. While it may be faster to use a GUI CAD package for the\ninitial iteration of a part, subsequent iterations can prove frustratingly\ndifficult. By using variables for critical dimensions and deriving other dimensions\nfrom these key variables, not only can a single part be created, but a whole set\nof parts can be readily available. When inevitable change requests arise, a simple\nparameter adjustment may be all that's required to make necessary modifications.","api_names":"","synonyms":"bore drill recessed fastener"},"259":{"title":"Self Intersection","body":"Avoid creating objects that intersect themselves - even if at a single vertex - as these topologies\nwill almost certainly be invalid (even if :meth:`~topology.Shape.is_valid` reports a ``True`` value).\nAn example of where this may arise is with the thread of a screw (or any helical shape) where after\none complete revolution the part may contact itself. One is likely be more successful if the part\nis split into multiple sections - say 180° of a helix - which are then stored in an assembly.\n\n.. rst-class:: clearfix","api_names":"invalid is_valid screw True","synonyms":"coil cut in half slice spiral thread path trim"},"260":{"title":"Tips, Best Practices and FAQ","body":"Although there are countless ways to create objects with build123d, experience\nhas proven that certain techniques can assist designers in achieving their goals\nwith the greatest efficiency. The following is a description of these techniques.","api_names":"","synonyms":""},"261":{"title":"Use Shallow Copies","body":"As discussed in the Assembly section, a :ref:`shallow copy ` of parts that\nare repeated in your design can make a huge difference in performance and usability of\nyour end design. Objects like fasteners, bearings, chain links, etc. could be duplicated\ntens or even hundreds of times otherwise. Use shallow copies where possible but keep in\nmind that if one instance of the object changes all will change.","api_names":"","synonyms":""},"262":{"title":"Why doesn't BuildSketch(Plane.XZ) work?","body":"When creating a sketch not on the default ``Plane.XY`` users may expect that they are drawing directly\non the workplane / coordinate system provided. For example:\n\n.. code-block:: build123d\n\n with BuildSketch(Plane.XZ) as vertical_sketch:\n Rectangle(1, 1)\n with Locations(vertices().group_by(Axis.X)[-1].sort_by(Axis.Z)[-1]):\n Circle(0.2)\n\n.. image:: assets/vertical_sketch.png\n\nIn this case the circle is not positioned in the top right as one would expect; in-fact, the position\nof the circle randomly switches between the bottom and top corner.\n\nThis is because all sketches are created on a local ``Plane.XY`` independent of where they will be\nultimately placed; therefore, the ``sort_by(Axis.Z)`` is sorting two points that have a Z value of\nzero as they are located on ``Plane.XY`` and effectively return a random point.\n\nWhy does ``BuildSketch`` work this way? Consider an example where the user wants to work on a\nplane not aligned with any Axis, as follows (this is often done when creating a sketch on a ``Face``\nof a 3D part but is simulated here by rotating a ``Plane``):\n\n.. code-block:: build123d\n\n with BuildSketch(Plane.YZ.rotated((123, 45, 6))) as custom_plane:\n Rectangle(1, 1, align=Align.MIN)\n with Locations(vertices().group_by(Axis.X)[-1].sort_by(Axis.Y)[-1]):\n Circle(0.2)\n\n.. image:: assets/sketch_on_custom_plane.png\n\nHere one can see both ``sketch_local`` (with the light fill on ``Plane.XY``) and the ``sketch``\n(with the darker fill) placed on the user provided workplane. As the selectors work off global \ncoordinates, selection of the \"top right\" of this sketch would be quite challenging and would \nlikely change if the sketch was ever moved as could happen if the 3D part changed. For an \nexample of sketching on a 3D part, see :ref:`sketching_on_other_planes`.","api_names":"BuildSketch Circle Face follows group_by Locations Plane Rectangle rotated sketch sketch_local sort_by vertices XY","synonyms":"array pattern repeat"},"263":{"title":"Why is BuildLine not working as expected within the scope of BuildSketch?","body":"As described above, all sketching is done on a local ``Plane.XY``; however, the following\nis a common issue:\n\n.. code-block:: build123d\n\n with BuildSketch() as sketch:\n with BuildLine(Plane.XZ):\n Polyline(...)\n make_face()\n\nHere ``BuildLine`` is within the scope of ``BuildSketch``; therefore, all of the\ndrawing should be done on ``Plane.XY``; however, the user has specified ``Plane.XZ``\nwhen creating the ``BuildLine`` instance. Although this isn't absolutely incorrect\nit's almost certainly not what the user intended. Here the face created by ``make_face`` will\nbe reoriented to ``Plane.XY`` as all sketching must be done on that plane. This reorienting\nof objects to ``Plane.XY`` allows a user to ``add`` content from other sources to the\nsketch without having to manually re-orient the object. \n\nUnless there is a good reason and the user understands how the ``BuildLine`` object will be\nreoriented, all ``BuildLine`` instances within the scope of ``BuildSketch`` should be done\non the default ``Plane.XY``.","api_names":"add BuildLine BuildSketch make_face Polyline XY XZ","synonyms":""},"264":{"title":"Examples","body":".. toctree::\n :maxdepth: 2\n :hidden:\n\n topology_selection/sort_examples\n\n.. grid:: 3\n :gutter: 3\n\n .. grid-item-card:: SortBy\n :img-top: assets/topology_selection/thumb_sort_sortby.png\n :link: sort_sortby\n :link-type: ref\n\n .. grid-item-card:: Along Wire\n :img-top: assets/topology_selection/thumb_sort_along_wire.png\n :link: sort_along_wire\n :link-type: ref\n\n .. grid-item-card:: Axis\n :img-top: assets/topology_selection/thumb_sort_axis.png\n :link: sort_axis\n :link-type: ref\n\n .. grid-item-card:: Distance From\n :img-top: assets/topology_selection/thumb_sort_distance.png\n :link: sort_distance_from\n :link-type: ref","api_names":"","synonyms":""},"265":{"title":"Examples","body":".. toctree::\n :maxdepth: 2\n :hidden:\n\n topology_selection/group_examples\n\n.. grid:: 3\n :gutter: 3\n\n .. grid-item-card:: Axis and Length\n :img-top: assets/topology_selection/thumb_group_axis.png\n :link: group_axis\n :link-type: ref\n\n .. grid-item-card:: Hole Area\n :img-top: assets/topology_selection/thumb_group_hole_area.png\n :link: group_hole_area\n :link-type: ref\n\n .. grid-item-card:: Properties with Keys\n :img-top: assets/topology_selection/thumb_group_properties_with_keys.png\n :link: group_properties_with_keys\n :link-type: ref","api_names":"","synonyms":"bore drill recessed fastener"},"266":{"title":"Examples","body":".. toctree::\n :maxdepth: 2\n :hidden:\n\n topology_selection/filter_examples\n\n.. grid:: 3\n :gutter: 3\n\n .. grid-item-card:: GeomType\n :img-top: assets/topology_selection/thumb_filter_geomtype.png\n :link: filter_geomtype\n :link-type: ref\n\n .. grid-item-card:: All Edges Circle\n :img-top: assets/topology_selection/thumb_filter_all_edges_circle.png\n :link: filter_all_edges_circle\n :link-type: ref\n\n .. grid-item-card:: Axis and Plane\n :img-top: assets/topology_selection/thumb_filter_axisplane.png\n :link: filter_axis_plane\n :link-type: ref\n\n .. grid-item-card:: Inner Wire Count\n :img-top: assets/topology_selection/thumb_filter_inner_wire_count.png\n :link: filter_inner_wire_count\n :link-type: ref\n\n .. grid-item-card:: Nested Filters\n :img-top: assets/topology_selection/thumb_filter_nested.png\n :link: filter_nested\n :link-type: ref\n\n .. grid-item-card:: Shape Properties\n :img-top: assets/topology_selection/thumb_filter_shape_properties.png\n :link: filter_shape_properties\n :link-type: ref\n\n.. |vertices| replace:: :meth:`~topology.Shape.vertices`\n.. |edges| replace:: :meth:`~topology.Shape.edges`\n.. |wires| replace:: :meth:`~topology.Shape.wires`\n.. |faces| replace:: :meth:`~topology.Shape.faces`\n.. |solids| replace:: :meth:`~topology.Shape.solids`\n.. |sort_by| replace:: :meth:`~topology.ShapeList.sort_by`\n.. |sort_by_distance| replace:: :meth:`~topology.ShapeList.sort_by_distance`\n.. |group_by| replace:: :meth:`~topology.ShapeList.group_by`\n.. |topo_distance_to| replace:: :func:`~topology.topo_distance_to`\n.. |filter_by| replace:: :meth:`~topology.ShapeList.filter_by`\n.. |filter_by_position| replace:: :meth:`~topology.ShapeList.filter_by_position`\n.. |ShapeList| replace:: :class:`~topology.ShapeList`","api_names":"edges faces filter_by filter_by_position group_by ShapeList solids sort_by sort_by_distance topo_distance_to vertices wires","synonyms":""},"267":{"title":"Filter","body":"A ``ShapeList`` can be filtered with the |filter_by| and |filter_by_position| methods based\non a filtering criteria. Filters are flexible way to isolate (or exclude) features based\non known criteria.\n\nLets say we need all the faces with a normal in the ``+Z`` direction. One way to do this\nmight be with a list comprehension, however |filter_by| has the capability to take a\nlambda function as a filter condition on the entire list. In this case, the normal of\neach face can be checked against a vector direction and filtered accordingly.\n\n.. code-block:: build123d\n\n part.faces().filter_by(lambda f: f.normal_at() == Vector(0, 0, 1))\n\n.. figure:: assets/topology_selection/operators_filter_z_normal.png\n :align: center\n\n|","api_names":"faces filter_by isolate normal_at ShapeList Vector","synonyms":""},"268":{"title":"Group","body":"A ShapeList can be grouped and sorted with the |group_by| method based on a grouping\ncriteria. Grouping can be a great way to organize features without knowing the values of\nspecific feature properties. Rather than returning a ``ShapeList``, |group_by| returns\na ``GroupBy``, a list of ``ShapeList`` objects sorted by the grouping criteria.\n``GroupBy`` can be printed to view the members of each group, indexed like a list to\nretrieve a ``ShapeList``, and be accessed using a key with the ``group`` method. If the\ngroup keys are unknown they can be discovered with ``key_to_group_index``.\n\nIf we want only the edges from the smallest faces by area we can get the faces, then\ngroup by ``SortBy.AREA``. The ``ShapeList`` of smallest faces is available from the first\nlist index. Finally, a ``ShapeList`` has access to selectors, so calling |edges| will\nreturn a new list of all edges in the previous list.\n\n.. code-block:: build123d\n\n part.faces().group_by(SortBy.AREA)[0].edges())\n\n.. figure:: assets/topology_selection/operators_group_area.png\n :align: center\n\n|","api_names":"AREA edges faces group group_by GroupBy key_to_group_index ShapeList","synonyms":""},"269":{"title":"Operators","body":"Operators provide methods refine a ``ShapeList`` of features isolated by a *selector* to\nfurther specify feature(s). These methods can sort, group, or filter ``ShapeList``\nobjects and return a modified ``ShapeList``, or in the case of |group_by|, ``GroupBy``,\na list of ``ShapeList`` objects accessible by index or key.","api_names":"feature GroupBy ShapeList","synonyms":""},"270":{"title":"Overview","body":"+--------------+----------------+-----------------------------------------------+-----------------------+\n| Selector | Criteria | Applicability | Description |\n+==============+================+===============================================+=======================+\n| |vertices| | ALL, LAST | ``BuildLine``, ``BuildSketch``, ``BuildPart`` | ``Vertex`` extraction |\n+--------------+----------------+-----------------------------------------------+-----------------------+\n| |edges| | ALL, LAST, NEW | ``BuildLine``, ``BuildSketch``, ``BuildPart`` | ``Edge`` extraction |\n+--------------+----------------+-----------------------------------------------+-----------------------+\n| |wires| | ALL, LAST | ``BuildLine``, ``BuildSketch``, ``BuildPart`` | ``Wire`` extraction |\n+--------------+----------------+-----------------------------------------------+-----------------------+\n| |faces| | ALL, LAST | ``BuildSketch``, ``BuildPart`` | ``Face`` extraction |\n+--------------+----------------+-----------------------------------------------+-----------------------+\n| |solids| | ALL, LAST | ``BuildPart`` | ``Solid`` extraction |\n+--------------+----------------+-----------------------------------------------+-----------------------+\n\nBoth shape objects and builder objects have access to selector methods to select all of\na feature as long as they can contain the feature being selected.\n\n.. code-block:: build123d\n\n # In context\n with BuildSketch() as context:\n Rectangle(1, 1)\n context.edges()\n\n # Build context implicitly has access to the selector\n edges()\n\n # Taking the sketch out of context\n context.sketch.edges()\n\n # Create sketch out of context\n Rectangle(1, 1).edges()","api_names":"BuildLine BuildPart BuildSketch Edge edges Face Rectangle Solid Vertex Wire","synonyms":""},"271":{"title":"Overview","body":"+----------------------+------------------------------------------------------------------+-------------------------------------------------------+\n| Method | Criteria | Description |\n+======================+==================================================================+=======================================================+\n| |sort_by| | ``Axis``, ``Edge``, ``Wire``, ``SortBy``, callable, property | Sort ``ShapeList`` by criteria |\n+----------------------+------------------------------------------------------------------+-------------------------------------------------------+\n| |sort_by_distance| | ``Shape``, ``VectorLike`` | Sort ``ShapeList`` by distance from criteria |\n+----------------------+------------------------------------------------------------------+-------------------------------------------------------+\n| |group_by| | ``Axis``, ``Edge``, ``Wire``, ``SortBy``, callable, property | Group ``ShapeList`` by criteria |\n+----------------------+------------------------------------------------------------------+-------------------------------------------------------+\n| |filter_by| | ``Axis``, ``Plane``, ``GeomType``, callable, property | Filter ``ShapeList`` by criteria |\n+----------------------+------------------------------------------------------------------+-------------------------------------------------------+\n| |filter_by_position| | ``Axis`` | Filter ``ShapeList`` by ``Axis`` & mix / max values |\n+----------------------+------------------------------------------------------------------+-------------------------------------------------------+\n\nOperator methods take criteria to refine ``ShapeList``. Broadly speaking, the criteria\nfall into the following categories, though not all operators take all criteria:\n\n- Geometric objects: ``Axis``, ``Plane``\n- Topological objects: ``Edge``, ``Wire``\n- Enums: :class:`~build_enums.SortBy`, :class:`~build_enums.GeomType`\n- Properties, eg: ``Face.area``, ``Edge.length``\n- Callable, eg: ``lambda e: e.is_interior == 1``, ``lambda f: len(f.edges()) >= 3``,\n ``Vertex().distance``, |topo_distance_to|","api_names":"area Axis Edge edges GeomType lambda length Plane Shape ShapeList SortBy VectorLike Vertex Wire","synonyms":""},"272":{"title":"Select In Build Context","body":"Build contexts track the last operation and their selector methods can take\n:class:`~build_enums.Select` as criteria to specify a subset of\nfeatures to extract. By default, a selector will select ``ALL`` of a feature, while\n``LAST`` selects features created or altered by the most recent operation. |edges| can\nuniquely specify ``NEW`` to only select edges created in the last operation which neither\nexisted in the referenced object before the last operation, nor the modifying object.\n\n.. important::\n\n :class:`~build_enums.Select` as selector criteria is only valid for builder objects!\n\n .. code-block:: build123d\n\n # In context\n with BuildPart() as context:\n Box(2, 2, 1)\n Cylinder(1, 2)\n context.edges(Select.LAST)\n\n # Does not work out of context!\n context.part.edges(Select.LAST)\n (Box(2, 2, 1) + Cylinder(1, 2)).edges(Select.LAST)\n\nCreate a simple part to demonstrate selectors. Select using the default criteria\n``Select.ALL``. Specifying ``Select.ALL`` for the selector is not required.\n\n.. code-block:: build123d\n\n with BuildPart() as part:\n Box(5, 5, 1)\n Cylinder(1, 5)\n\n part.vertices()\n part.edges()\n part.faces()\n\n # Is the same as\n part.vertices(Select.ALL)\n part.edges(Select.ALL)\n part.faces(Select.ALL)\n\n.. figure:: assets/topology_selection/selectors_select_all.png\n :align: center\n\n The default ``Select.ALL`` features\n\nSelect features changed in the last operation with criteria ``Select.LAST``.\n\n.. code-block:: build123d\n\n with BuildPart() as part:\n Box(5, 5, 1)\n Cylinder(1, 5)\n\n part.vertices(Select.LAST)\n part.edges(Select.LAST)\n part.faces(Select.LAST)\n\n.. figure:: assets/topology_selection/selectors_select_last.png\n :align: center\n\n ``Select.LAST`` features\n\nSelect only new edges from the last operation with ``Select.NEW``. This option is only\navailable for a ``ShapeList`` of edges!\n\n.. code-block:: build123d\n\n with BuildPart() as part:\n Box(5, 5, 1)\n Cylinder(1, 5)\n\n part.edges(Select.NEW)\n\n.. figure:: assets/topology_selection/selectors_select_new.png\n :align: center\n\n ``Select.NEW`` edges where box and cylinder intersect\n\nThis only returns new edges which are not reused from Box or Cylinder, in this case where\nthe objects `intersect`. But what happens if the objects don't intersect and all the\nedges are reused?\n\n.. code-block:: build123d\n\n with BuildPart() as part:\n Box(5, 5, 1, align=(Align.CENTER, Align.CENTER, Align.MAX))\n Cylinder(2, 2, align=(Align.CENTER, Align.CENTER, Align.MIN))\n\n part.edges(Select.NEW)\n\n.. figure:: assets/topology_selection/selectors_select_new_none.png\n :align: center\n\n ``Select.NEW`` edges when box and cylinder don't intersect\n\nNo edges are selected! Unlike the previous example, the Edge between the Box and Cylinder\nobjects is an edge reused from the Cylinder. Think of ``Select.NEW`` as a way to select\nonly completely new edges created by the operation.\n\n.. note::\n\n Chamfer and fillet modify the current object, but do not have new edges via\n ``Select.NEW``.\n\n .. code-block:: build123d\n\n with BuildPart() as part:\n Box(5, 5, 1)\n Cylinder(1, 5)\n edges = part.edges().filter_by(lambda a: a.length == 1)\n fillet(edges, 1)\n\n part.edges(Select.NEW)\n\n .. figure:: assets/topology_selection/selectors_select_new_fillet.png\n :align: center\n\n Left, ``Select.NEW`` returns no edges after fillet. Right, ``Select.LAST``","api_names":"ALL Box BuildPart Cylinder edges faces fillet filter_by LAST NEW Select ShapeList vertices","synonyms":"bevel edge round edge"},"273":{"title":"Select New Edges In Algebra Mode","body":"The utility method ``new_edges`` compares one or more shape objects to a\nanother \"combined\" shape object and returns the edges new to the combined shape.\n``new_edges`` is available both Algebra mode or Builder mode, but is necessary in\nAlgebra Mode where ``Select.NEW`` is unavailable\n\n.. code-block:: build123d\n\n box = Box(5, 5, 1)\n circle = Cylinder(2, 5)\n part = box + circle\n edges = new_edges(box, circle, combined=part)\n\n.. figure:: assets/topology_selection/selectors_new_edges.png\n :align: center\n\n``new_edges`` can also find edges created during a chamfer or fillet operation by\ncomparing the object before the operation to the \"combined\" object.\n\n.. code-block:: build123d\n\n box = Box(5, 5, 1)\n circle = Cylinder(2, 5)\n part_before = box + circle\n edges = part_before.edges().filter_by(lambda a: a.length == 1)\n part = fillet(edges, 1)\n edges = new_edges(part_before, combined=part)\n\n.. figure:: assets/topology_selection/operators_group_area.png\n :align: center\n\n.. _operators:","api_names":"Box Cylinder edges fillet filter_by NEW new_edges","synonyms":"bevel edge round edge"},"274":{"title":"Selectors","body":"Selectors provide methods to extract all or a subset of a feature type in the referenced\nobject. These methods select Edges, Faces, Solids, Vertices, or Wires in Builder objects\nor from Shape objects themselves. All of these methods return a |ShapeList|,\nwhich is a subclass of ``list`` and may be sorted, grouped, or filtered by\n:ref:`operators`.","api_names":"","synonyms":""},"275":{"title":"Sort","body":"A ``ShapeList`` can be sorted with the |sort_by| and |sort_by_distance|\nmethods based on a sorting criteria. Sorting is a critical step when isolating individual\nfeatures as a ``ShapeList`` from a selector is typically unordered.\n\nHere we want to capture some vertices from the object furthest along ``X``: All the\nvertices are first captured with the |vertices| selector, then sort by ``Axis.X``.\nFinally, the vertices can be captured with a list slice for the last 4 list items, as the\nitems are sorted from least to greatest ``X`` position. Remember, ``ShapeList`` is a\nsubclass of ``list``, so any list slice can be used.\n\n.. code-block:: build123d\n\n part.vertices().sort_by(Axis.X)[-4:]\n\n.. figure:: assets/topology_selection/operators_sort_x.png\n :align: center\n\n|","api_names":"ShapeList sort_by vertices X","synonyms":""},"276":{"title":"Topological Distance","body":"|topo_distance_to| creates a callable key that measures graph distance through\ntopology rather than geometric distance through space. It is useful when selecting\nfeatures by adjacency, for example faces connected to a reference face, or the next\nring of faces after that.\n\nDistances are measured within the shared ``topo_parent`` of the reference shape. The\nreference shape has distance ``0``, directly adjacent shapes have distance ``1``, and\nunreachable shapes have distance ``inf``.\n\n.. code-block:: build123d\n\n box = Box(1, 1, 1)\n faces = box.faces()\n top_face = faces.sort_by(Axis.Z)[-1]\n\n face_rings = faces.group_by(topo_distance_to(top_face))\n\n top = face_rings[0]\n sides = face_rings[1]\n bottom = face_rings[2]\n\nMultiple reference shapes can be provided. This is useful for selecting all features\nwithin a topological distance from any reference. In this example, a sphere is converted\nto a triangular mesh, faces near the middle of the mesh are used as references, and all\nmesh faces are grouped into topological rings expanding away from that starting band.\n\n.. code-block:: build123d\n\n from build123d import *\n from pathlib import Path\n from tempfile import TemporaryDirectory\n\n from ocp_vscode import ColorMap, show\n\n mesher = Mesher()\n mesher.add_shape(Sphere(1), linear_deflection=0.05, angular_deflection=1)\n\n with TemporaryDirectory() as tmp_dir:\n mesh_path = Path(tmp_dir) / \"sphere.stl\"\n mesher.write(mesh_path)\n mesh_sphere = Mesher().read(mesh_path)[0]\n\n sphere_faces = mesh_sphere.faces()\n\n vertical_groups = sphere_faces.group_by(Axis.Z)\n starting_ring = vertical_groups[len(vertical_groups) // 2]\n face_rings = sphere_faces.group_by(topo_distance_to(starting_ring))\n\n show(*face_rings, colors=ColorMap.listed(len(face_rings)))\n\n.. figure:: assets/topology_selection/topo_distance_to.png\n :align: center\n\nThe same approach can be used with edges or vertices. For example, a single edge on the\nmesh can be used as the starting point for edge-distance rings.\n\n.. code-block:: build123d\n\n sphere_edges = mesh_sphere.edges()\n reference_edge = choice(sphere_edges)\n edge_rings = sphere_edges.group_by(topo_distance_to(reference_edge))","api_names":"add_shape Box choice edges faces group_by inf listed Mesher Path read show sort_by Sphere TemporaryDirectory topo_distance_to topo_parent write","synonyms":""},"277":{"title":"Topology Selection and Exploration","body":":ref:`topology` is the structure of build123d geometric features and traversing the\ntopology of a part is often required to specify objects for an operation or to locate a\nCAD feature. :ref:`selectors` allow selection of topology objects into a |ShapeList|.\n:ref:`operators` are powerful methods further explore and refine a |ShapeList| for\nsubsequent operations.\n\n.. _selectors:","api_names":"","synonyms":""},"278":{"title":"23-02-02 SM Hanger","body":".. image:: assets/ttt/ttt-23-02-02-sm_hanger.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 1028g +/- 10g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Creation of a complex sheet metal part\n \n name: ttt_sm_hanger.py\n by: Gumyr\n date: July 17, 2023\n \n desc:\n This example implements the sheet metal part described in Too Tall Toby's\n sm_hanger CAD challenge.\n \n Notably, a BuildLine/Curve object is filleted by providing all the vertices\n and allowing the fillet operation filter out the end vertices. The\n make_brake_formed operation is used both in Algebra and Builder mode to\n create a sheet metal part from just an outline and some dimensions.\n license:\n \n Copyright 2023 Gumyr\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n \n \"\"\"\n \n from build123d import *\n from ocp_vscode import *\n \n sheet_thickness = 4 * MM\n \n # Create the main body from a side profile\n with BuildPart() as side:\n d = Vector(1, 0, 0).rotate(Axis.Y, 60)\n with BuildLine(Plane.XZ) as side_line:\n l1 = Line((0, 65), (170 / 2, 65))\n l2 = PolarLine(l1 @ 1, length=65, direction=d, length_mode=LengthMode.VERTICAL)\n l3 = Line(l2 @ 1, (170 / 2, 0))\n fillet(side_line.vertices(), 7)\n make_brake_formed(\n thickness=sheet_thickness,\n station_widths=[40, 40, 40, 112.52 / 2, 112.52 / 2, 112.52 / 2],\n side=Side.RIGHT,\n )\n fe = side.edges().filter_by(Axis.Z).group_by(Axis.Z)[0].sort_by(Axis.Y)[-1]\n fillet(fe, radius=7)\n \n # Create the \"wings\" at the top\n with BuildPart() as wing:\n with BuildLine(Plane.YZ) as wing_line:\n l1 = Line((0, 65), (80 / 2 + 1.526 * sheet_thickness, 65))\n PolarLine(l1 @ 1, 20.371288916, direction=Vector(0, 1, 0).rotate(Axis.X, -75))\n fillet(wing_line.vertices(), 7)\n make_brake_formed(\n thickness=sheet_thickness,\n station_widths=110 / 2,\n side=Side.RIGHT,\n )\n bottom_edge = wing.edges().group_by(Axis.X)[-1].sort_by(Axis.Z)[0]\n fillet(bottom_edge, radius=7)\n \n # Create the tab at the top in Algebra mode\n tab_line = Plane.XZ * Polyline(\n (20, 65 - sheet_thickness), (56 / 2, 65 - sheet_thickness), (56 / 2, 88)\n )\n tab_line = fillet(tab_line.vertices(), 7)\n tab = make_brake_formed(sheet_thickness, 8, tab_line, Side.RIGHT)\n tab = fillet(tab.edges().filter_by(Axis.X).group_by(Axis.Z)[-1].sort_by(Axis.Y)[-1], 5)\n tab -= Pos((0, 0, 80)) * Rot(0, 90, 0) * Hole(5, 100)\n \n # Combine the parts together\n with BuildPart() as sm_hanger:\n add([side.part, wing.part])\n mirror(about=Plane.XZ)\n with BuildSketch(Plane.XY.offset(65)) as h1:\n with Locations((20, 0)):\n Rectangle(30, 30, align=(Align.MIN, Align.CENTER))\n fillet(h1.vertices().group_by(Axis.X)[-1], 7)\n SlotCenterPoint((154, 0), (154 / 2, 0), 20)\n extrude(amount=-40, mode=Mode.SUBTRACT)\n with BuildSketch() as h2:\n SlotCenterPoint((206, 0), (206 / 2, 0), 20)\n extrude(amount=40, mode=Mode.SUBTRACT)\n add(tab)\n mirror(about=Plane.YZ)\n mirror(about=Plane.XZ)\n \n got_mass = sm_hanger.part.volume * 7800 * 1e-6\n want_mass = 1028\n tolerance = 10\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.1f} g\")\n # assert delta < tolerance, f\"{got_mass=}, {want_mass=}, {delta=}, {tolerance=}\"\n \n # assert abs(got_mass - 1028) < 10, f\"{got_mass=}, want=1028, tolerance=10\"\n \n show(sm_hanger)\n \n\n.. _ttt-23-t-24:","api_names":"abs add BuildLine BuildPart BuildSketch edges extrude fillet filter_by group_by Hole Line Locations make_brake_formed mirror offset PolarLine Polyline Pos Rectangle Rot rotate show SlotCenterPoint sort_by Vector vertices","synonyms":"array bevel edge bore channel drill fit gap groove hollow path cut pattern recessed fastener reflect repeat round edge shell symmetry tolerance wall thickness"},"279":{"title":"23-T-24 Curved Support","body":".. image:: assets/ttt/ttt-23-t-24-curved_support.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 1294 g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Too Tall Toby challenge 23-T-24 CURVED SUPPORT\n \"\"\"\n \n from math import sin, cos, tan, radians\n from build123d import *\n from ocp_vscode import *\n import sympy\n \n # This problem uses the sympy symbolic math solver\n \n # Define the symbols for the unknowns\n # - the center of the radius 30 arc (x30, y30)\n # - the center of the radius 66 arc (x66, y66)\n # - end of the 8° line (l8x, l8y)\n # - the point with the radius 30 and 66 arc meet i30_66\n # - the start of the horizontal line lh\n y30, x66, xl8, yl8 = sympy.symbols(\"y30 x66 xl8 yl8\")\n x30 = 77 - 55 / 2\n y66 = 66 + 32\n \n # There are 4 unknowns so we need 4 equations\n equations = [\n (x66 - x30) ** 2 + (y66 - y30) ** 2 - (66 + 30) ** 2, # distance between centers\n xl8 - (x30 + 30 * sin(radians(8))), # 8 degree slope\n yl8 - (y30 + 30 * cos(radians(8))), # 8 degree slope\n (yl8 - 50) / (55 / 2 - xl8) - tan(radians(8)), # 8 degree slope\n ]\n # There are two solutions but we want the 2nd one\n solution = {k: float(v) for k,v in sympy.solve(equations, dict=True)[1].items()}\n \n # Create the critical points\n c30 = Vector(x30, solution[y30])\n c66 = Vector(solution[x66], y66)\n l8 = Vector(solution[xl8], solution[yl8])\n i30_66 = Line(c30, c66) @ (30 / (30 + 66))\n lh = Vector(c66.X, 32)\n \n with BuildLine() as profile:\n l1 = Line((55 / 2, 50), l8)\n l2 = RadiusArc(l1 @ 1, i30_66, 30)\n l3 = RadiusArc(l2 @ 1, lh, -66)\n l4 = Polyline(l3 @ 1, (125, 32), (125, 0), (0, 0), (0, (l1 @ 0).Y), l1 @ 0)\n \n with BuildPart() as curved_support:\n with BuildSketch() as base_plan:\n c_8_degrees = Circle(55 / 2)\n with Locations((0, 125)):\n Circle(30 / 2)\n base_hull = make_hull(mode=Mode.PRIVATE)\n extrude(amount=32)\n extrude(c_8_degrees, amount=60)\n extrude(base_hull, amount=11)\n with BuildSketch(Plane.YZ) as bridge:\n make_face(profile.edges())\n extrude(amount=11 / 2, both=True)\n Hole(35 / 2)\n with Locations((0, 125)):\n Hole(20 / 2)\n \n got_mass = curved_support.part.volume * 7800e-6\n want_mass = 1294\n delta = abs(got_mass - want_mass)\n tolerance = 3\n print(f\"Mass: {got_mass:0.1f} g\")\n assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'\n \n show(curved_support)\n \n\n.. _ttt-24-spo-06:","api_names":"abs arc BuildLine BuildPart BuildSketch Circle cos edges extrude Hole items line Line Locations make_face make_hull Polyline radians RadiusArc show sin slope solve symbols tan Vector","synonyms":"array bore drill pattern recessed fastener repeat"},"280":{"title":"24-SPO-06 Buffer Stand","body":".. image:: assets/ttt/ttt-24-SPO-06-Buffer_Stand.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 3.92 lbs\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import show\n \n with BuildPart() as p:\n with BuildSketch() as xy:\n with BuildLine():\n l1 = ThreePointArc((5 / 2, -1.25), (5.5 / 2, 0), (5 / 2, 1.25))\n Polyline(l1 @ 0, (0, -1.25), (0, 1.25), l1 @ 1)\n make_face()\n extrude(amount=4)\n \n with BuildSketch(Plane.YZ) as yz:\n Trapezoid(2.5, 4, 90 - 6, align=(Align.CENTER, Align.MIN))\n full_round(yz.edges().sort_by(SortBy.LENGTH)[0])\n circle_edge = yz.edges().filter_by(GeomType.CIRCLE)[0]\n arc_center = circle_edge.arc_center\n arc_radius = circle_edge.radius\n extrude(amount=10, mode=Mode.INTERSECT)\n \n # To avoid OCCT problems, don't attempt to extend the top arc, remove instead\n with BuildPart(mode=Mode.SUBTRACT) as internals:\n y = p.edges().filter_by(Axis.X).sort_by(Axis.Z)[-1].center().Z\n \n with BuildSketch(Plane.YZ.offset(4.25 / 2)) as yz:\n Trapezoid(2.5, y, 90 - 6, align=(Align.CENTER, Align.MIN))\n with Locations(arc_center):\n Circle(arc_radius, mode=Mode.SUBTRACT)\n extrude(amount=-(4.25 - 3.5) / 2)\n \n with BuildSketch(Plane.YZ.offset(3.5 / 2)) as yz:\n Trapezoid(2.5, 4, 90 - 6, align=(Align.CENTER, Align.MIN))\n extrude(amount=-3.5 / 2)\n \n with BuildSketch(Plane.XZ.offset(-2)) as xz:\n with Locations((0, 4)):\n RectangleRounded(4.25, 7.5, 0.5)\n extrude(amount=4, mode=Mode.INTERSECT)\n \n with Locations(p.faces(Select.LAST).filter_by(GeomType.PLANE).sort_by(Axis.Z)[-1]):\n CounterBoreHole(0.625 / 2, 1.25 / 2, 0.5)\n \n with BuildSketch(Plane.YZ) as rib:\n with Locations((0, 0.25)):\n Trapezoid(0.5, 1, 90 - 8, align=(Align.CENTER, Align.MIN))\n full_round(rib.edges().sort_by(SortBy.LENGTH)[0])\n extrude(amount=4.25 / 2)\n \n mirror(about=Plane.YZ)\n \n part = scale(p.part, IN)\n \n \n got_mass = part.volume * 7800e-6 / LB\n want_mass = 3.923\n tolerance = 0.02\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.1f} lbs\")\n assert delta < tolerance, f\"{got_mass=}, {want_mass=}, {delta=}, {tolerance=}\"\n \n show(p)","api_names":"abs BuildLine BuildPart BuildSketch center Circle CounterBoreHole edges extrude faces filter_by full_round Locations make_face mirror offset Polyline RectangleRounded scale show sort_by ThreePointArc Trapezoid","synonyms":"array bore channel drill fit gap groove hollow path cut pattern recessed fastener reflect repeat shell symmetry tolerance wall thickness"},"281":{"title":"Party Pack 01-01 Bearing Bracket","body":".. image:: assets/ttt/ttt-ppp0101.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 797.15 g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Too Tall Toby Party Pack 01-01 Bearing Bracket\n \"\"\"\n \n from build123d import *\n from ocp_vscode import *\n \n densa = 7800 / 1e6 # carbon steel density g/mm^3\n densb = 2700 / 1e6 # aluminum alloy\n densc = 1020 / 1e6 # ABS\n \n with BuildPart() as p:\n with BuildSketch() as s:\n Rectangle(115, 50)\n with Locations((5 / 2, 0)):\n SlotOverall(90, 12, mode=Mode.SUBTRACT)\n extrude(amount=15)\n \n with BuildSketch(Plane.XZ.offset(50 / 2)) as s3:\n with Locations((-115 / 2 + 26, 15)):\n SlotOverall(42 + 2 * 26 + 12, 2 * 26, rotation=90)\n zz = extrude(amount=-12)\n split(bisect_by=Plane.XY)\n edgs = p.part.edges().filter_by(Axis.Y).group_by(Axis.X)[-2]\n fillet(edgs, 9)\n \n with Locations(zz.faces().sort_by(Axis.Y)[0]):\n with Locations((42 / 2 + 6, 0)):\n CounterBoreHole(24 / 2, 34 / 2, 4)\n mirror(about=Plane.XZ)\n \n with BuildSketch() as s4:\n RectangleRounded(115, 50, 6)\n extrude(amount=80, mode=Mode.INTERSECT)\n # fillet does not work right, mode intersect is safer\n \n with BuildSketch(Plane.YZ) as s4:\n with BuildLine() as bl:\n l1 = Line((0, 0), (18 / 2, 0))\n l2 = PolarLine(l1 @ 1, 8, 60, length_mode=LengthMode.VERTICAL)\n l3 = Line(l2 @ 1, (0, 8))\n mirror(about=Plane.YZ)\n make_face()\n extrude(amount=115/2, both=True, mode=Mode.SUBTRACT)\n \n show_object(p)\n \n \n got_mass = p.part.volume*densa\n want_mass = 797.15\n tolerance = 1\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.2f} g\")\n assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'\n \n\n\n.. _ttt-ppp0102:","api_names":"abs BuildLine BuildPart BuildSketch CounterBoreHole edges extrude faces fillet filter_by group_by Line Locations make_face mirror offset PolarLine Rectangle RectangleRounded show_object SlotOverall sort_by split","synonyms":"array bevel edge bore channel cut in half drill fit gap groove hollow path cut pattern recessed fastener reflect repeat round edge shell slice symmetry tolerance trim wall thickness"},"282":{"title":"Party Pack 01-02 Post Cap","body":".. image:: assets/ttt/ttt-ppp0102.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 43.09 g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Too Tall Toby Party Pack 01-02 Post Cap\n \"\"\"\n \n from build123d import *\n from ocp_vscode import *\n \n densa = 7800 / 1e6 # carbon steel density g/mm^3\n densb = 2700 / 1e6 # aluminum alloy\n densc = 1020 / 1e6 # ABS\n \n \n # TTT Party Pack 01: PPP0102, mass(abs) = 43.09g\n with BuildPart() as p:\n with BuildSketch(Plane.XZ) as sk1:\n Rectangle(49, 48 - 8, align=(Align.CENTER, Align.MIN))\n Rectangle(9, 48, align=(Align.CENTER, Align.MIN))\n with Locations((9 / 2, 40)):\n Ellipse(20, 8)\n split(bisect_by=Plane.YZ)\n revolve(axis=Axis.Z)\n \n with BuildSketch(Plane.YZ.offset(-15)) as xc1:\n with Locations((0, 40 / 2 - 17)):\n Ellipse(10 / 2, 4 / 2)\n with BuildLine(Plane.XZ) as l1:\n CenterArc((-15, 40 / 2), 17, 90, 180)\n sweep(path=l1)\n \n fillet(p.edges().filter_by(GeomType.CIRCLE, reverse=True).group_by(Axis.X)[0], 1)\n \n with BuildLine(mode=Mode.PRIVATE) as lc1:\n PolarLine(\n (42 / 2, 0), 37, 94, length_mode=LengthMode.VERTICAL\n ) # construction line\n \n pts = [\n (0, 0),\n (42 / 2, 0),\n ((lc1.line @ 1).X, (lc1.line @ 1).Y),\n (0, (lc1.line @ 1).Y),\n ]\n with BuildSketch(Plane.XZ) as sk2:\n Polygon(*pts, align=None)\n fillet(sk2.vertices().group_by(Axis.X)[1], 3)\n revolve(axis=Axis.Z, mode=Mode.SUBTRACT)\n \n show(p)\n \n \n got_mass = p.part.volume*densc\n want_mass = 43.09\n tolerance = 1\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.2f} g\")\n assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'\n \n \n\n.. _ttt-ppp0103:","api_names":"abs BuildLine BuildPart BuildSketch CenterArc edges Ellipse fillet filter_by group_by Locations mass offset PolarLine Polygon Rectangle revolve show split sweep vertices","synonyms":"array axisymmetric bevel edge channel cut in half fit gap groove hollow lathe path cut pattern repeat round edge shell slice tolerance trim turned wall thickness"},"283":{"title":"Party Pack 01-03 C Clamp Base","body":".. image:: assets/ttt/ttt-ppp0103.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 96.13 g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Too Tall Toby Party Pack 01-03 C Clamp Base\n \"\"\"\n \n from build123d import *\n from ocp_vscode import *\n \n densa = 7800 / 1e6 # carbon steel density g/mm^3\n densb = 2700 / 1e6 # aluminum alloy\n densc = 1020 / 1e6 # ABS\n \n \n with BuildPart() as ppp0103:\n with BuildSketch() as sk1:\n RectangleRounded(34 * 2, 95, 18)\n with Locations((0, -2)):\n RectangleRounded((34 - 16) * 2, 95 - 18 - 14, 7, mode=Mode.SUBTRACT)\n with Locations((-34 / 2, 0)):\n Rectangle(34, 95, 0, mode=Mode.SUBTRACT)\n extrude(amount=16)\n with BuildSketch(Plane.XZ.offset(-95 / 2)) as cyl1:\n with Locations((0, 16 / 2)):\n Circle(16 / 2)\n extrude(amount=18)\n with BuildSketch(Plane.XZ.offset(95 / 2 - 14)) as cyl2:\n with Locations((0, 16 / 2)):\n Circle(16 / 2)\n extrude(amount=23)\n with Locations(Plane.XZ.offset(95 / 2 + 9)):\n with Locations((0, 16 / 2)):\n CounterSinkHole(5.5 / 2, 11.2 / 2, None, 90)\n \n show(ppp0103)\n \n got_mass = ppp0103.part.volume*densb\n want_mass = 96.13\n tolerance = 1\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.2f} g\")\n assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'\n \n\n.. _ttt-ppp0104:","api_names":"abs BuildPart BuildSketch Circle CounterSinkHole extrude Locations offset Rectangle RectangleRounded show","synonyms":"array bore channel drill fit gap groove hollow path cut pattern recessed fastener repeat shell tolerance wall thickness"},"284":{"title":"Party Pack 01-04 Angle Bracket","body":".. image:: assets/ttt/ttt-ppp0104.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 310.00 g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Too Tall Toby Party Pack 01-04 Angle Bracket\n \"\"\"\n \n from build123d import *\n from ocp_vscode import *\n \n densa = 7800 / 1e6 # carbon steel density g/mm^3\n densb = 2700 / 1e6 # aluminum alloy\n densc = 1020 / 1e6 # ABS\n \n d1, d2, d3 = 38, 26, 16\n h1, h2, h3, h4 = 20, 8, 7, 23\n w1, w2, w3 = 80, 10, 5\n f1, f2, f3 = 4, 10, 5\n sloth1, sloth2 = 18, 12\n slotw1, slotw2 = 17, 14\n \n with BuildPart() as p:\n with BuildSketch() as s:\n Circle(d1 / 2)\n extrude(amount=h1)\n with BuildSketch(Plane.XY.offset(h1)) as s2:\n Circle(d2 / 2)\n extrude(amount=h2)\n with BuildSketch(Plane.YZ) as s3:\n Rectangle(d1 + 15, h3, align=(Align.CENTER, Align.MIN))\n extrude(amount=w1 - d1 / 2)\n # fillet workaround \\/\n ped = p.part.edges().group_by(Axis.Z)[2].filter_by(GeomType.CIRCLE)\n fillet(ped, f1)\n with BuildSketch(Plane.YZ) as s3a:\n Rectangle(d1 + 15, 15, align=(Align.CENTER, Align.MIN))\n Rectangle(d1, 15, mode=Mode.SUBTRACT, align=(Align.CENTER, Align.MIN))\n extrude(amount=w1 - d1 / 2, mode=Mode.SUBTRACT)\n # end fillet workaround /\\\n with BuildSketch() as s4:\n Circle(d3 / 2)\n extrude(amount=h1 + h2, mode=Mode.SUBTRACT)\n with BuildSketch() as s5:\n with Locations((w1 - d1 / 2 - w2 / 2, 0)):\n Rectangle(w2, d1)\n extrude(amount=-h4)\n fillet(p.part.edges().group_by(Axis.X)[-1].sort_by(Axis.Z)[-1], f2)\n fillet(p.part.edges().group_by(Axis.X)[-4].sort_by(Axis.Z)[-2], f3)\n pln = Plane.YZ.offset(w1 - d1 / 2)\n with BuildSketch(pln) as s6:\n with Locations((0, -h4)):\n SlotOverall(slotw1 * 2, sloth1, 90)\n extrude(amount=-w3, mode=Mode.SUBTRACT)\n with BuildSketch(pln) as s6b:\n with Locations((0, -h4)):\n SlotOverall(slotw2 * 2, sloth2, 90)\n extrude(amount=-w2, mode=Mode.SUBTRACT)\n \n show(p)\n \n \n got_mass = p.part.volume*densa\n want_mass = 310\n tolerance = 1\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.2f} g\")\n assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'\n \n\n.. _ttt-ppp0105:","api_names":"abs BuildPart BuildSketch Circle edges extrude fillet filter_by group_by Locations offset Rectangle show SlotOverall sort_by","synonyms":"array bevel edge channel fit gap groove hollow path cut pattern repeat round edge shell tolerance wall thickness"},"285":{"title":"Party Pack 01-05 Paste Sleeve","body":".. image:: assets/ttt/ttt-ppp0105.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 57.08 g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Too Tall Toby Party Pack 01-05 Paste Sleeve\n \"\"\"\n \n from build123d import *\n from ocp_vscode import *\n \n densa = 7800 / 1e6 # carbon steel density g/mm^3\n densb = 2700 / 1e6 # aluminum alloy\n densc = 1020 / 1e6 # ABS\n \n with BuildPart() as p:\n with BuildSketch() as s:\n SlotOverall(45, 38)\n offset(amount=3)\n with BuildSketch(Plane.XY.offset(133 - 30)) as s2:\n SlotOverall(60, 4)\n offset(amount=3)\n loft()\n \n with BuildSketch() as s3:\n SlotOverall(45, 38)\n with BuildSketch(Plane.XY.offset(133 - 30)) as s4:\n SlotOverall(60, 4)\n loft(mode=Mode.SUBTRACT)\n \n extrude(p.part.faces().sort_by(Axis.Z)[0], amount=30)\n \n show(p)\n \n \n got_mass = p.part.volume*densc\n want_mass = 57.08\n tolerance = 1\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.2f} g\")\n assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'\n \n \n\n.. _ttt-ppp0106:","api_names":"abs BuildPart BuildSketch extrude faces loft offset show SlotOverall sort_by","synonyms":"blend profiles channel cross sections fit gap groove hollow path cut shell tolerance transition wall thickness"},"286":{"title":"Party Pack 01-06 Bearing Jig","body":".. image:: assets/ttt/ttt-ppp0106.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 328.02 g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Too Tall Toby Party Pack 01-06 Bearing Jig\n \"\"\"\n \n from build123d import *\n from ocp_vscode import *\n \n densa = 7800 / 1e6 # carbon steel density g/mm^3\n densb = 2700 / 1e6 # aluminum alloy\n densc = 1020 / 1e6 # ABS\n \n r1, r2, r3, r4, r5 = 30 / 2, 13 / 2, 12 / 2, 10, 6 # radii used\n x1 = 44 # lengths used\n y1, y2, y3, y4, y_tot = 36, 36 - 22 / 2, 22 / 2, 42, 69 # widths used\n \n with BuildSketch(Location((0, -r1, y3))) as sk_body:\n with BuildLine() as l:\n c1 = Line((r1, 0), (r1, y_tot), mode=Mode.PRIVATE) # construction line\n m1 = Line((0, y_tot), (x1 / 2, y_tot))\n m2 = JernArc(m1 @ 1, m1 % 1, r4, -90 - 45)\n m3 = IntersectingLine(m2 @ 1, m2 % 1, c1)\n m4 = Line(m3 @ 1, (r1, r1))\n m5 = JernArc(m4 @ 1, m4 % 1, r1, -90)\n mirror(about=Plane.YZ)\n make_face()\n fillet(sk_body.vertices().group_by(Axis.Y)[1], 12)\n with Locations((x1 / 2, y_tot - 10), (-x1 / 2, y_tot - 10)):\n Circle(r2, mode=Mode.SUBTRACT)\n # Keyway\n with Locations((0, r1)):\n Circle(r3, mode=Mode.SUBTRACT)\n Rectangle(4, 3 + 6, align=(Align.CENTER, Align.MIN), mode=Mode.SUBTRACT)\n \n with BuildPart() as p:\n Box(200, 200, 22) # Oversized plate\n # Cylinder underneath\n Cylinder(r1, y2, align=(Align.CENTER, Align.CENTER, Align.MAX))\n fillet(p.edges(Select.NEW), r5) # Weld together\n extrude(sk_body.sketch, amount=-y1, mode=Mode.INTERSECT) # Cut to shape\n # Remove slot\n with Locations((0, y_tot - r1 - y4, 0)):\n Box(\n y_tot,\n y_tot,\n 10,\n align=(Align.CENTER, Align.MIN, Align.CENTER),\n mode=Mode.SUBTRACT,\n )\n \n show(p)\n \n \n got_mass = p.part.volume*densa\n want_mass = 328.02\n tolerance = 1\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.2f} g\")\n assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'\n \n\n.. _ttt-ppp0107:","api_names":"abs Box BuildLine BuildPart BuildSketch Circle Cylinder edges extrude fillet group_by IntersectingLine JernArc Line Location Locations make_face mirror Rectangle show vertices","synonyms":"array bevel edge channel groove path cut pattern reflect repeat round edge symmetry"},"287":{"title":"Party Pack 01-07 Flanged Hub","body":".. image:: assets/ttt/ttt-ppp0107.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 372.99 g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Too Tall Toby Party Pack 01-07 Flanged Hub\n \"\"\"\n \n from build123d import *\n from ocp_vscode import *\n \n densa = 7800 / 1e6 # carbon steel density g/mm^3\n densb = 2700 / 1e6 # aluminum alloy\n densc = 1020 / 1e6 # ABS\n \n with BuildPart() as p:\n with BuildSketch() as s:\n Circle(130 / 2)\n extrude(amount=8)\n with BuildSketch(Plane.XY.offset(8)) as s2:\n Circle(84 / 2)\n extrude(amount=25 - 8)\n with BuildSketch(Plane.XY.offset(25)) as s3:\n Circle(35 / 2)\n extrude(amount=52 - 25)\n with BuildSketch() as s4:\n Circle(73 / 2)\n extrude(amount=18, mode=Mode.SUBTRACT)\n pln2 = p.part.faces().sort_by(Axis.Z)[5]\n with BuildSketch(Plane.XY.offset(52)) as s5:\n Circle(20 / 2)\n extrude(amount=-52, mode=Mode.SUBTRACT)\n fillet(\n p.part.edges()\n .filter_by(GeomType.CIRCLE)\n .sort_by(Axis.Z)[2:-2]\n .sort_by(SortBy.RADIUS)[1:],\n 3,\n )\n pln = Plane(pln2)\n pln.origin = pln.origin + Vector(20 / 2, 0, 0)\n pln = pln.rotated((0, 45, 0))\n pln = pln.offset(-25 + 3 + 0.10)\n with BuildSketch(pln) as s6:\n Rectangle((73 - 35) / 2 * 1.414 + 5, 3)\n zz = extrude(amount=15, taper=-20 / 2, mode=Mode.PRIVATE)\n zz2 = split(zz, bisect_by=Plane.XY.offset(25), mode=Mode.PRIVATE)\n zz3 = split(zz2, bisect_by=Plane.YZ.offset(35 / 2 - 1), mode=Mode.PRIVATE)\n with PolarLocations(0, 3):\n add(zz3)\n with Locations(Plane.XY.offset(8)):\n with PolarLocations(107.95 / 2, 6):\n CounterBoreHole(6 / 2, 13 / 2, 4)\n \n show(p)\n \n \n got_mass = p.part.volume*densb\n want_mass = 372.99\n tolerance = 1\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.2f} g\")\n assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'\n \n\n.. _ttt-ppp0108:","api_names":"abs add BuildPart BuildSketch Circle CounterBoreHole edges extrude faces fillet filter_by Locations offset Plane PolarLocations Rectangle rotated show sort_by split Vector","synonyms":"array bevel edge bore channel cut in half drill fit gap groove hollow path cut pattern recessed fastener repeat round edge shell slice tolerance trim wall thickness"},"288":{"title":"Party Pack 01-08 Tie Plate","body":".. image:: assets/ttt/ttt-ppp0108.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 3387.06 g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Too Tall Toby Party Pack 01-08 Tie Plate\n \"\"\"\n \n from build123d import *\n from ocp_vscode import *\n \n densa = 7800 / 1e6 # carbon steel density g/mm^3\n densb = 2700 / 1e6 # aluminum alloy\n densc = 1020 / 1e6 # ABS\n \n with BuildPart() as p:\n with BuildSketch() as s1:\n Rectangle(188 / 2 - 33, 162, align=(Align.MIN, Align.CENTER))\n with Locations((188 / 2 - 33, 0)):\n SlotOverall(190, 33 * 2, rotation=90)\n mirror(about=Plane.YZ)\n with GridLocations(188 - 2 * 33, 190 - 2 * 33, 2, 2):\n Circle(29 / 2, mode=Mode.SUBTRACT)\n Circle(84 / 2, mode=Mode.SUBTRACT)\n extrude(amount=16)\n \n with BuildPart() as p2:\n with BuildSketch(Plane.XZ) as s2:\n with BuildLine() as l1:\n l1 = Polyline(\n (222 / 2 + 14 - 40 - 40, 0),\n (222 / 2 + 14 - 40, -35 + 16),\n (222 / 2 + 14, -35 + 16),\n (222 / 2 + 14, -35 + 16 + 30),\n (222 / 2 + 14 - 40 - 40, -35 + 16 + 30),\n close=True,\n )\n make_face()\n with Locations((222 / 2, -35 + 16 + 14)):\n Circle(11 / 2, mode=Mode.SUBTRACT)\n extrude(amount=20 / 2, both=True)\n with BuildSketch() as s3:\n with Locations(l1 @ 0):\n Rectangle(40 + 40, 8, align=(Align.MIN, Align.CENTER))\n with Locations((40, 0)):\n Rectangle(40, 20, align=(Align.MIN, Align.CENTER))\n extrude(amount=30, both=True, mode=Mode.INTERSECT)\n mirror(about=Plane.YZ)\n \n show(p)\n \n \n got_mass = p.part.volume*densa\n want_mass = 3387.06\n tolerance = 1\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.2f} g\")\n assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'\n \n\n.. _ttt-ppp0109:","api_names":"abs BuildLine BuildPart BuildSketch Circle extrude GridLocations Locations make_face mirror Polyline Rectangle show SlotOverall","synonyms":"array channel groove path cut pattern reflect repeat symmetry"},"289":{"title":"Party Pack 01-09 Corner Tie","body":".. image:: assets/ttt/ttt-ppp0109.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 307.23 g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Too Tall Toby Party Pack 01-09 Corner Tie\n \"\"\"\n \n from math import sqrt\n from build123d import *\n from ocp_vscode import *\n \n densa = 7800 / 1e6 # carbon steel density g/mm^3\n densb = 2700 / 1e6 # aluminum alloy\n densc = 1020 / 1e6 # ABS\n \n with BuildPart() as ppp109:\n with BuildSketch() as one:\n Rectangle(69, 75, align=(Align.MAX, Align.CENTER))\n fillet(one.vertices().group_by(Axis.X)[0], 17)\n extrude(amount=13)\n centers = [\n arc.arc_center\n for arc in ppp109.edges().filter_by(GeomType.CIRCLE).group_by(Axis.Z)[-1]\n ]\n with Locations(*centers):\n CounterBoreHole(radius=8 / 2, counter_bore_radius=15 / 2, counter_bore_depth=4)\n \n with BuildSketch(Plane.YZ) as two:\n with Locations((0, 45)):\n Circle(15)\n with BuildLine() as bl:\n c = Line((75 / 2, 0), (75 / 2, 60), mode=Mode.PRIVATE)\n u = two.edge().find_tangent(75 / 2 + 90)[0] # where is the slope 75/2?\n l1 = IntersectingLine(\n two.edge().position_at(u), -two.edge().tangent_at(u), other=c\n )\n Line(l1 @ 0, (0, 45))\n Polyline((0, 0), c @ 0, l1 @ 1)\n mirror(about=Plane.YZ)\n make_face()\n with Locations((0, 45)):\n Circle(12 / 2, mode=Mode.SUBTRACT)\n extrude(amount=-13)\n \n with BuildSketch(Plane((0, 0, 0), x_dir=(1, 0, 0), z_dir=(1, 0, 1))) as three:\n Rectangle(45 * 2 / sqrt(2) - 37.5, 75, align=(Align.MIN, Align.CENTER))\n with Locations(three.edges().sort_by(Axis.X)[-1].center()):\n Circle(37.5)\n Circle(33 / 2, mode=Mode.SUBTRACT)\n split(bisect_by=Plane.YZ)\n extrude(amount=6)\n f = ppp109.faces().filter_by(Axis((0, 0, 0), (-1, 0, 1)))[0]\n extrude(f, until=Until.NEXT)\n fillet(ppp109.edges().filter_by(Axis.Y).sort_by(Axis.Z)[2], 16)\n # extrude(f, amount=10)\n # fillet(ppp109.edges(Select.NEW), 16)\n \n \n show(ppp109)\n \n got_mass = ppp109.part.volume * densb\n want_mass = 307.23\n tolerance = 1\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.2f} g\")\n assert delta < tolerance, f\"{got_mass=}, {want_mass=}, {delta=}, {tolerance=}\"\n \n\n.. _ttt-ppp0110:","api_names":"abs Axis BuildLine BuildPart BuildSketch center Circle CounterBoreHole edge edges extrude faces fillet filter_by find_tangent group_by IntersectingLine Line Locations make_face mirror Plane Polyline position_at Rectangle show sort_by split sqrt tangent_at vertices","synonyms":"array bevel edge bore channel cut in half drill groove path cut pattern recessed fastener reflect repeat round edge slice symmetry trim"},"290":{"title":"Party Pack 01-10 Light Cap","body":".. image:: assets/ttt/ttt-ppp0110.png\n :align: center\n\n.. dropdown:: Object Mass\n\n 211.30 g\n\n.. dropdown:: Reference Implementation\n\n .. code-block:: build123d\n\n \"\"\"\n Too Tall Toby Party Pack 01-10 Light Cap\n \"\"\"\n \n from math import sqrt, asin, pi\n from build123d import *\n from ocp_vscode import *\n \n densa = 7800 / 1e6 # carbon steel density g/mm^3\n densb = 2700 / 1e6 # aluminum alloy\n densc = 1020 / 1e6 # ABS\n \n # The smaller cross-section is defined as having R40, height 46,\n # and base width 84, so clearly it's not entirely a half-circle or\n # similar; the base's extreme points need to connect via tangents\n # to the R40 arc centered 6mm above the baseline.\n #\n # Compute the angle of the tangent line (working with the\n # left/negativeX side, given symmetry) by observing the tangent\n # point (T), the circle's center (O), and the baseline's edge (P)\n # form a right triangle, so:\n \n OT=40\n OP=sqrt((-84/2)**2+(-6)**2)\n TP=sqrt(OP**2-40**2)\n OPT_degrees = asin(OT/OP) * 180/pi\n # Correct for the fact that OP isn't horizontal.\n OP_to_X_axis_degrees = asin(6/OP) * 180/pi\n left_tangent_degrees = OPT_degrees + OP_to_X_axis_degrees\n left_tangent_length = TP\n with BuildPart() as outer:\n with BuildSketch(Plane.XZ) as sk:\n with BuildLine():\n l1 = PolarLine(start=(-84/2, 0), length=left_tangent_length, angle=left_tangent_degrees)\n l2 = TangentArc(l1@1, (0, 46), tangent=l1%1)\n l3 = offset(amount=-8, side=Side.RIGHT, closed=False, mode=Mode.ADD)\n l4 = Line(l1@0, l3@1)\n l5 = Line(l3@0, l2@1)\n make_face()\n \n with BuildLine():\n l6 = Line(l2 @ 1, (0, 46 - 16))\n l7 = IntersectingLine(start=l6 @ 1, direction=(-1, 0), other=l3)\n l8 = TangentArc(l7 @ 1, l2 @ 1, tangent=(-1, 0), tangent_from_first=False)\n \n make_face()\n \n revolve(axis=Axis.Z)\n sk = sk.sketch & Plane.XZ*Rectangle(1000, 1000, align=[Align.CENTER, Align.MIN])\n positive_Z = Box(100, 100, 100, align=[Align.CENTER, Align.MIN, Align.MIN])\n p = outer.part & positive_Z\n cross_section = sk + mirror(sk, about=Plane.YZ)\n p += extrude(cross_section, amount=50)\n p += mirror(p, about=Plane.XZ.offset(50))\n p += fillet(p.edges().filter_by(GeomType.LINE).filter_by(Axis.Y).group_by(Axis.Z)[-1], radius=8)\n ppp0110 = p\n \n got_mass = ppp0110.volume*densc\n want_mass = 211.30\n tolerance = 1\n delta = abs(got_mass - want_mass)\n print(f\"Mass: {got_mass:0.1f} g\")\n assert delta < tolerance, f'{got_mass=}, {want_mass=}, {delta=}, {tolerance=}'\n \n show(ppp0110)\n \n\n.. _ttt-23-02-02-sm_hanger:","api_names":"abs asin Box BuildLine BuildPart BuildSketch center edge edges extrude fillet filter_by group_by IntersectingLine line Line make_face mirror offset point PolarLine Rectangle revolve show sqrt TangentArc","synonyms":"axisymmetric bevel edge fit gap hollow lathe reflect round edge shell symmetry tolerance turned wall thickness"},"291":{"title":"Too Tall Toby (TTT) Tutorials","body":".. image:: assets/ttt.png\n :align: center\n\nTo enhance users' proficiency with Build123D, this section offers a series of challenges.\nIn these challenges, users are presented with a CAD drawing and tasked with designing the\npart. Their goal is to match the part's mass to a specified target.\n\nThese drawings were skillfully crafted and generously provided to Build123D by Too Tall Toby,\na renowned figure in the realm of 3D CAD. Too Tall Toby is the host of the World Championship\nof 3D CAD Speedmodeling. For additional 3D CAD challenges and content, be sure to\nvisit `Toby's youtube channel `_.\n\nFeel free to click on the parts below to embark on these engaging challenges.\n\n.. grid:: 3\n\n .. grid-item-card:: Party Pack 01-01 Bearing Bracket\n :img-top: assets/ttt/ttt-ppp0101_object.png\n :link: ttt-ppp0101\n :link-type: ref\n\n .. grid-item-card:: Party Pack 01-02 Post Cap\n :img-top: assets/ttt/ttt-ppp0102_object.png\n :link: ttt-ppp0102\n :link-type: ref\n\n .. grid-item-card:: Party Pack 01-03 C Clamp Base\n :img-top: assets/ttt/ttt-ppp0103_object.png\n :link: ttt-ppp0103\n :link-type: ref\n\n .. grid-item-card:: Party Pack 01-04 Angle Bracket\n :img-top: assets/ttt/ttt-ppp0104_object.png\n :link: ttt-ppp0104\n :link-type: ref\n\n .. grid-item-card:: Party Pack 01-05 Paste Sleeve\n :img-top: assets/ttt/ttt-ppp0105_object.png\n :link: ttt-ppp0105\n :link-type: ref\n\n .. grid-item-card:: Party Pack 01-06 Bearing Jig\n :img-top: assets/ttt/ttt-ppp0106_object.png\n :link: ttt-ppp0106\n :link-type: ref\n\n .. grid-item-card:: Party Pack 01-07 Flanged Hub\n :img-top: assets/ttt/ttt-ppp0107_object.png\n :link: ttt-ppp0107\n :link-type: ref\n\n .. grid-item-card:: Party Pack 01-08 Tie Plate\n :img-top: assets/ttt/ttt-ppp0108_object.png\n :link: ttt-ppp0108\n :link-type: ref\n\n .. grid-item-card:: Party Pack 01-09 Corner Tie\n :img-top: assets/ttt/ttt-ppp0109_object.png\n :link: ttt-ppp0109\n :link-type: ref\n\n .. grid-item-card:: Party Pack 01-10 Light Cap\n :img-top: assets/ttt/ttt-ppp0110_object.png\n :link: ttt-ppp0110\n :link-type: ref\n\n .. grid-item-card:: 23-02-02 SM Hanger\n :img-top: assets/ttt/ttt-23-02-02-sm_hanger_object.png\n :link: ttt-23-02-02-sm_hanger\n :link-type: ref\n\n .. grid-item-card:: 23-T-24 Curved Support\n :img-top: assets/ttt/ttt-23-t-24-curved_support_object.png\n :link: ttt-23-t-24\n :link-type: ref\n\n .. grid-item-card:: 24-SPO-06 Buffer Stand\n :img-top: assets/ttt/ttt-24-SPO-06-Buffer_Stand_object.png\n :link: ttt-24-spo-06\n :link-type: ref\n\n\n.. _ttt-ppp0101:","api_names":"Toby","synonyms":""},"292":{"title":"Algebra mode","body":"Use direct assignment and post-selection:\n\n.. code-block:: build123d\n\n arcs = ConstrainedArcs(..., sagitta=Sagitta.BOTH)\n chosen = arcs.edges().sort_by(Edge.length)[0]","api_names":"ConstrainedArcs edges sort_by","synonyms":""},"293":{"title":"Allowed constraint objects","body":"For arc constraints, accepted objects include:\n\n- :class:`~topology.Edge`\n- :class:`~geometry.Axis`\n- :class:`~geometry.Vertex` / :class:`~geometry.VectorLike` point\n- optional qualifier wrapper: ``(object, Tangency.XXX)``","api_names":"Axis Edge VectorLike Vertex","synonyms":""},"294":{"title":"Analytical Constraints","body":":class:`~objects_sketch.Triangle`\n Constructs a triangle from any three parameters (side lengths and/or interior angles) \n and solves for the others. Angle naming follows standard convention: side ``a`` is opposite\n angle ``A``, side ``b`` is opposite angle ``B``, and side ``c`` is opposite angle ``C``.","api_names":"a A b B c C parameters Triangle","synonyms":""},"295":{"title":"Analytical Constraints","body":"build123d includes a built-in :class:`~objects_sketch.Triangle` object that has an internal solver such that one can\nspecify any three parameters of a triangle and solve for the others. For example:\n\n.. code-block:: build123d\n\n >>> isosceles = Triangle(a=30, b=30, C=60)\n >>> isosceles.c\n 29.999999999999996\n >>> isosceles.A\n 60.00000000000001\n >>> isosceles.B\n 60.00000000000001\n >>> isosceles.vertex_A\n Vertex(-1.7763568394002505e-15, 17.32050807568877, 0.0)\n\nIn this example, side lengths ``a`` and ``b`` with included angle ``C`` are provided.\nThe object then computes the remaining side, angles, and vertices. This is useful when a\ndesign intent is naturally expressed as triangle dimensions instead of explicit coordinates.\n\nOne can easily use external solvers, say the symbolic solver ``sympy``, within your build123d code \nas follows:\n\n.. code-block:: build123d\n\n from math import sin, cos, tan, radians\n from build123d import *\n from ocp_vscode import *\n import sympy\n\n # This problem uses the sympy symbolic math solver\n\n # Define the symbols for the unknowns\n # - the center of the radius 30 arc (x30, y30)\n # - the center of the radius 66 arc (x66, y66)\n # - end of the 8° line (l8x, l8y)\n # - the point with the radius 30 and 66 arc meet i30_66\n # - the start of the horizontal line lh\n y30, x66, xl8, yl8 = sympy.symbols(\"y30 x66 xl8 yl8\")\n x30 = 77 - 55 / 2\n y66 = 66 + 32\n\n # There are 4 unknowns so we need 4 equations\n equations = [\n (x66 - x30) ** 2 + (y66 - y30) ** 2 - (66 + 30) ** 2, # distance between centers\n xl8 - (x30 + 30 * sin(radians(8))), # 8 degree slope\n yl8 - (y30 + 30 * cos(radians(8))), # 8 degree slope\n (yl8 - 50) / (55 / 2 - xl8) - tan(radians(8)), # 8 degree slope\n ]\n # There are two solutions but we want the 2nd one\n solution = {k: float(v) for k,v in sympy.solve(equations, dict=True)[1].items()}\n\n # Create the critical points\n c30 = Vector(x30, solution[y30])\n c66 = Vector(solution[x66], y66)\n l8 = Vector(solution[xl8], solution[yl8])\n\n ...\n\nThis pattern is useful when the governing relationships are algebraic but awkward to\nconstruct directly with primitives. Solve unknown parameters first, then feed the solved\nvalues into standard build123d geometry construction.","api_names":"a arc b C cos items line radians sin slope solve symbols sympy tan Triangle Vector Vertex","synonyms":""},"296":{"title":"Builder mode","body":"Prefer selecting inside the call to avoid adding unwanted candidates to context:\n\n.. code-block:: build123d\n\n with BuildLine() as bl:\n ConstrainedArcs(\n ...,\n sagitta=Sagitta.BOTH,\n selector=lambda arcs: arcs.sort_by(Edge.length)[0],\n )","api_names":"BuildLine ConstrainedArcs sort_by","synonyms":""},"297":{"title":"Builder vs Algebra mode","body":"","api_names":"","synonyms":""},"298":{"title":"Coincident","body":".. code-block:: build123d\n\n with BuildLine() as coincident_ex:\n l1 = Line((0, 0), (1, 2))\n l2 = Line(l1 @ 1, l1 @ 1 + (1, 0))\n \n.. figure:: ./assets/coincident_ex.svg\n :align: center\n\nThe second line starts at ``l1 @ 1`` (the end of ``l1``), creating an exact coincident\nrelationship without a separate constraint object.","api_names":"BuildLine l1 Line","synonyms":""},"299":{"title":"Complex Drawing Example","body":"This example pulls many of the techniques described above into a single example\nwhere the following full constrained, complex sketch is converted into build123d code.\n\n.. figure:: ./assets/complex_sketch.png\n :align: center\n\nWhen working with a drawing such as this one, the ``ImageFace`` functionality of the\n`ocp-vscode `_ viewer is very handy as \nit allows the image to be used as a visual guide when creating the sketch.\n\nWithin the following code the following conventions are used:\n\n- construction geometry is labeled with a ``c_...``\n- arcs are labeled with a ``a``\n- lines and polylines are labeled with a ``l...``\n\nThe code starts immediately above the origin (arbitrarily set to the origin of the circle)\nwhere a straight line 10° off the x-axis originates. The code then walks around the diagram\nclockwise creating the perimeter of the object.\n\n.. code-block:: build123d\n\n image = ImageFace(\n \"complex_sketch.png\",\n scale=29 / 264,\n origin_pixels=(297, 390),\n location=Location((0, 0, -0.1)),\n )\n\n with BuildSketch() as sketch:\n with BuildLine() as perimeter:\n c_l1 = PolarLine((0, 32 - 14), 50, -10, mode=Mode.PRIVATE)\n a19 = ConstrainedArcs(c_l1, (-14 + 81 - 29, -14 - 19 + 57), radius=19)\n l2 = Polyline(a19 @ 1, a19 @ 1 + (29 - 5, 0), a19 @ 1 + (29, -5), (-14 + 81, 0))\n l3 = Line(l2 @ 1, (-14 + 81 - 29, (-14 - 19)))\n c_l4 = Line((-14, -14), (-14 + 81, -14), mode=Mode.PRIVATE)\n c_a29_arc_center = l3.intersect(c_l4)[0]\n c_a29 = CenterArc(c_a29_arc_center, 29, 180, 50, mode=Mode.PRIVATE)\n l5 = PolarLine(l3 @ 1, length=c_a29, direction=(-1, 0))\n a5 = ConstrainedArcs(\n c_a29, c_l4, radius=5, selector=lambda a: a.sort_by(Axis.X)[0]\n )\n a29 = add(c_a29.trim(l5 @ 1, a5 @ 0))\n l6 = Polyline(\n a5 @ 1,\n (-14 + 7, -14),\n (-14, -14 + 7),\n (-14, -14 + 32 - 7),\n (-14 + 7, -14 + 32),\n (0, -14 + 32),\n a19 @ 0,\n )\n make_face()\n a14 = Circle(14 / 2, mode=Mode.SUBTRACT)\n\n.. figure:: ./assets/complex_ex.svg\n :align: center\n\nImplementation notes:\n\n1. Build in traversal order around the perimeter. This keeps references local and makes\n later edits easier because each segment depends on nearby geometry.\n2. Keep helper entities private (``mode=Mode.PRIVATE``) so only final profile edges\n contribute to the resulting face.\n3. Use named construction geometry (``c_...``) for intersections and arc centers; this\n improves readability and debugability.\n4. Use constrained constructors only where they add value (for example :class:`~objects_curve.ConstrainedArcs`),\n and use direct primitives elsewhere.\n5. Create a :class:`~topology.Face` (``make_face`` then center-hole subtraction) only after\n the perimeter is fully defined.","api_names":"a add BuildLine BuildSketch c_ CenterArc Circle ConstrainedArcs Face geometry ImageFace intersect l Line Location make_face mode origin PolarLine Polyline private sort_by trim value","synonyms":"bore channel drill groove path cut recessed fastener"},"300":{"title":"ConstrainedArcs","body":"","api_names":"","synonyms":""},"301":{"title":"ConstrainedLines","body":"","api_names":"","synonyms":""},"302":{"title":"Constraint Types","body":"build123d supports several practical forms of constrained construction. Rather than relying on\na single global sketch solver, it provides targeted tools that enforce specific geometric\nrelationships directly and predictably.","api_names":"","synonyms":""},"303":{"title":"Continuity Constraints","body":":class:`~objects_curve.BlendCurve`\n Creates a smooth Bézier transition between two existing edges.\n\n In this context, *continuity* describes how smoothly the new blend joins the input edges\n at each endpoint:\n\n - C0 (positional continuity): endpoints meet, but direction may kink.\n - C1 (tangent continuity): endpoints and tangent directions match, giving a visually smooth join with no corner.\n - C2 (curvature continuity): endpoints, tangents, and curvature trend match, reducing curvature jumps and producing a smoother fairing.\n\n :class:`~objects_curve.BlendCurve` builds a Bézier curve that satisfies these endpoint constraints:\n\n - cubic Bézier for C1 blending (position + first derivative),\n - quintic Bézier for C2 blending (position + first and second derivatives).\n\n The derivatives are sampled from the two source edges at the selected connection points,\n then converted into Bézier control points that enforce the requested continuity.\n Optional tangent scaling factors let you tune how strongly the blend departs from each\n source edge, which adjusts perceived tension and transition shape without changing the\n endpoint constraints.","api_names":"BlendCurve blending C0 C1 C2","synonyms":""},"304":{"title":"Continuity Constraints","body":"One may want to join two curves with a third curve such that the connector satisfies a\ngiven continuity where they meet as shown here where a semi-circle (on the left) is joined \nto a spline (on the right).\n\n.. code-block:: build123d\n\n m1 = CenterArc((-2, 0.6), 1, -10, 200).reversed()\n m2 = Spline((0.4, -0.6), (1, -1.6), (2, 0))\n connector = BlendCurve(m1, m2, tangent_scalars=(2, 1), continuity=ContinuityLevel.C2)\n comb = Curve(Wire([m1, connector, m2]).curvature_comb(200))\n\n.. figure:: ./assets/blend_curve_ex.svg\n :align: center\n\nThe key call is ``BlendCurve(..., continuity=ContinuityLevel.C2)``. ``C2`` continuity\nmatches endpoint curvature trend in addition to position and tangent, which reduces visible\nfairness breaks at joins. ``tangent_scalars`` controls how strongly the connector departs\nfrom each source curve.\n\n``curvature_comb`` is used here as a diagnostic. The normal \"comb\" lines represent local\ncurvature magnitude; smoother transitions produce gradual comb variation rather than abrupt\nspikes.","api_names":"BlendCurve C2 CenterArc circle curvature_comb Curve reversed spline Spline tangent_scalars Wire","synonyms":"control points interpolation smooth curve"},"305":{"title":"Drawing with Constraints","body":"","api_names":"","synonyms":""},"306":{"title":"Extent / Termination Constraints","body":":class:`~objects_curve.PolarLine`, :class:`~objects_curve.CenterArc`, :class:`~objects_curve.EllipticalCenterArc`, :class:`~objects_curve.EllipticalStartArc`, :class:`~objects_curve.JernArc`, :class:`~objects_curve.ParabolicCenterArc`, and :class:`~objects_curve.HyperbolicCenterArc`\n Construct curves from natural geometric parameters, then let another object determine\n where the result ends.\n\n In these constructors, the size argument can often be either:\n\n - a numeric angular or linear extent, or\n - a limiting object such as a :class:`~topology.Shape`, :class:`~geometry.Axis`,\n :class:`~geometry.Location`, :class:`~geometry.Plane`, or point-like object.\n\n When a limit object is provided, the constructor creates the candidate geometry from the\n supplied start conditions, trims it at the first valid intersection with the limit, and\n returns the shortest valid result from the start. If no valid intersection exists, a\n ``ValueError`` is raised.\n\n This pattern is especially useful when design intent is \"go in this direction until you\n meet that object\", because it removes helper construction lines and separate trim calls\n while keeping the relationship local to the constructor call.","api_names":"Axis CenterArc EllipticalCenterArc EllipticalStartArc HyperbolicCenterArc JernArc Location ParabolicCenterArc Plane PolarLine Shape ValueError","synonyms":""},"307":{"title":"Extent / Termination Constraints","body":".. code-block:: build123d\n\n with BuildLine() as intersect_ex:\n c1 = EllipticalCenterArc((0, 0), 1.2, 1.8, 0, arc_size=120, mode=Mode.PRIVATE)\n l1 = PolarLine(start=(-0.2, 0.1), length=c1, angle=10)\n l2 = PolarLine(start=(-0.2, 0.1), length=c1, angle=70)\n l3 = add(c1.trim(l1 @ 1, l2 @ 1))\n\n.. figure:: ./assets/intersect_ex.svg\n :align: center\n\n:class:`~objects_curve.PolarLine` creates each line from a start point and direction,\nthen limits it by intersection with the ellipse. This is often cleaner than creating long\nhelper lines and manually trimming afterward, and the same pattern applies to a wide range\nof arcs and conics.\n\nThe same extent-by-object pattern works with several curved constructors:\n\n- :class:`~objects_curve.CenterArc`\n- :class:`~objects_curve.EllipticalCenterArc`\n- :class:`~objects_curve.EllipticalStartArc`\n- :class:`~objects_curve.JernArc`\n- :class:`~objects_curve.ParabolicCenterArc`\n- :class:`~objects_curve.HyperbolicCenterArc`\n\nFor example, a parabola or hyperbola can be grown from a start condition and terminated by a\nline or axis in the same way:\n\n.. code-block:: build123d\n\n p1 = ParabolicCenterArc((0, 0), 0.5, 0, arc_size=Line((0, 1), (5, 1)))\n h1 = HyperbolicCenterArc((0, 0), 2, 1, 0, arc_size=Axis((0, 1), (1, 0)))\n\nThis is particularly useful when sketches are not symmetric and multiple local constructions\nmust terminate against different surrounding geometry.","api_names":"add Axis BuildLine CenterArc EllipticalCenterArc EllipticalStartArc HyperbolicCenterArc JernArc Line ParabolicCenterArc PolarLine trim","synonyms":""},"308":{"title":"Geometric Relationship Constraints","body":"``@`` and ``%`` operators\n Use ``@`` (position-at) and ``%`` (tangent-at) to construct geometry relative to existing\n geometry. Typical uses include starting a new edge at an exact point on another edge,\n or aligning a new edge direction to a sampled tangent.\n\n:class:`~operations_generic.mirror`\n Enforces symmetry by reflecting geometry about a plane, producing mirrored entities with\n exact geometric correspondence to the source.","api_names":"mirror","synonyms":"reflect symmetry"},"309":{"title":"Geometric Relationship Constraints","body":"","api_names":"","synonyms":""},"310":{"title":"Introduction","body":"CAD constraints are geometric and dimensional rules that define how sketch or assembly entities \nrelate to one another. They control degrees of freedom (for example, parallel,\nperpendicular, tangent, coincident, distance, or angle), so edits preserve design intent instead \nof introducing unintended shape changes. This is the foundation of parametric\nmodeling: behavior is driven by explicit relationships, not fixed manually drawn geometry.\nThis section only addresses sketch constraints.\n\nIn graphical CAD systems, sketching is usually a two-step workflow: first draw approximate\ngeometry, then add dimensions and constraints so a global solver can infer exact positions.\nThat model works well for interactive drawing, but it also encourages tightly coupled\nconstraint networks that can become difficult to predict and maintain as a design evolves.\nIt is also typically strongest for lines and circular arcs, with more limited and less\nrobust behavior for ellipses, splines, and other higher-order curves.\n\nIn build123d, the primary workflow is different. Geometry is defined precisely at creation\ntime using coordinates, parameters, and explicit geometric relationships in code. Instead of\nbuilding a large interdependent constraint graph and asking a global solver to resolve it,\nyou express intent directly: mirror about a plane, construct tangent features, derive points\nand frames from existing topology, and compose operations deterministically.\n\nThis does not eliminate constrained construction; it scopes it. build123d provides targeted\ngeometric local solvers for common high-value problems, including objects such as\n:class:`~objects_curve.BlendCurve`, :class:`~objects_curve.ConstrainedLines`,\n:class:`~objects_curve.ConstrainedArcs`, and :class:`~objects_sketch.Triangle`.\nIt also provides a growing family of constructors whose extent can be determined by other\ngeometry, including :class:`~objects_curve.PolarLine`, :class:`~objects_curve.CenterArc`,\n:class:`~objects_curve.EllipticalCenterArc`, :class:`~objects_curve.EllipticalStartArc`,\n:class:`~objects_curve.JernArc`, :class:`~objects_curve.ParabolicCenterArc`, and\n:class:`~objects_curve.HyperbolicCenterArc`. Together with operations such as\n:class:`~operations_sketch.make_hull`, :class:`~operations_generic.mirror`, and\n:class:`~operations_generic.offset`, these tools solve specific constraint patterns while\nkeeping model behavior explicit, deterministic, and readable in code.\n\nThe result is a practical hybrid approach: precise programmatic modeling by default, with\nspecialized constrained constructors when they provide clear leverage. For most production\nparts, this yields robust, maintainable sketches without the overhead and fragility of a\ngeneral-purpose sketch solver.","api_names":"BlendCurve CenterArc ConstrainedArcs ConstrainedLines EllipticalCenterArc EllipticalStartArc freedom HyperbolicCenterArc JernArc make_hull mirror offset ParabolicCenterArc PolarLine Triangle","synonyms":"control points fit gap hollow interpolation reflect shell smooth curve symmetry tolerance wall thickness"},"311":{"title":"Multiple solutions","body":"Constraint systems often yield multiple valid results. The ``selector`` callback is the\nmain tool for choosing the subset to keep.\n\n.. code-block:: build123d\n\n # Keep all solutions\n ConstrainedArcs(..., selector=lambda arcs: arcs)\n\n # Keep first\n ConstrainedArcs(..., selector=lambda arcs: arcs[0])\n\n # Keep shortest\n ConstrainedArcs(..., selector=lambda arcs: arcs.sort_by(Edge.length)[0])\n\nIn Builder mode, omitting ``selector`` can add all solutions to context, which is often\nnot what you want for production sketches.","api_names":"ConstrainedArcs selector sort_by","synonyms":""},"312":{"title":"Multiple Solutions and Qualification","body":"Tangency construction is typically multi-solution. A single problem statement can produce\nseveral valid geometric branches depending on where the solution lies relative to the\nreference entities.\n\nFor example, a circle of fixed radius tangent to two secant circles can produce up to\neight valid solutions as shown below. This is expected behavior, not an error.\n\n.. figure:: ./assets/tangent_circles.svg\n :align: center\n\nTo reduce ambiguity, tangency constraints support **qualification** of relative position:\n\n- ``Tangency.ENCLOSING``: the solution must enclose the argument.\n- ``Tangency.ENCLOSED``: the solution must be enclosed by the argument.\n- ``Tangency.OUTSIDE``: the solution and argument must be external to each other.\n- ``Tangency.UNQUALIFIED``: no positional filtering; all valid branches are returned.\n\nThese qualifiers are intuitive for circles (inside/outside). For general oriented curves,\ninterior is defined as the left-hand side of the curve with respect to its orientation.\n\nEven with qualification, more than one solution may remain. In that case, use a\n``selector`` to choose deterministic outputs.","api_names":"circles ENCLOSED ENCLOSING OUTSIDE selector UNQUALIFIED","synonyms":""},"313":{"title":"Offset / Equidistance Constraints","body":":class:`~operations_generic.offset`\n Creates geometry at a constant normal distance from a source edge or wire.\n\n This enforces an equidistance relationship commonly used for wall thickness, clearances,\n toolpaths, and parallel profile construction. Join behavior (for example at corners) can\n be controlled to match the design intent.","api_names":"behavior offset","synonyms":"fit gap hollow shell tolerance wall thickness"},"314":{"title":"Offset / Equidistance Constraints","body":".. code-block:: build123d\n\n inside = FilletPolyline((1.5, 0), (1.5, 1), (-1.5, 1), (-1.5, 0), radius=0.2)\n perimeter = offset(inside, amount=0.2, side=Side.RIGHT)\n\n\n.. figure:: ./assets/offset_ex.svg\n :align: center\n\n:class:`~operations_generic.offset` preserves the source profile shape while enforcing constant wall thickness.\nThis is a common pattern for clearances, shells, and manufacturing margins.","api_names":"FilletPolyline offset","synonyms":"bevel edge fit gap hollow round edge shell tolerance wall thickness"},"315":{"title":"Overview","body":":class:`~objects_curve.ConstrainedArcs` supports several signature families for planar circular arcs:\n\n1. Two tangency/contact objects + fixed radius\n2. Two tangency/contact objects + center constrained on a locus\n3. Three tangency/contact objects\n4. One tangency/contact object + fixed center\n5. One tangency/contact object + fixed radius + center constrained on a locus\n\n``sagitta`` selects short/long/both arc branches:\n\n- ``Sagitta.SHORT``\n- ``Sagitta.LONG``\n- ``Sagitta.BOTH``\n\nIn practice, use qualifiers and ``sagitta`` to reduce branch count, then finalize with\n``selector`` for deterministic output.","api_names":"BOTH ConstrainedArcs LONG sagitta selector SHORT","synonyms":""},"316":{"title":"Overview","body":":class:`~objects_curve.ConstrainedLines` supports these signature families:\n\n1. Tangent/contact to two objects\n2. Tangent/contact to one object and passing through a fixed point\n3. Tangent/contact to one object with fixed orientation (``angle`` or ``direction``)","api_names":"angle ConstrainedLines direction orientation","synonyms":""},"317":{"title":"Perpendicular","body":".. code-block:: build123d\n\n with BuildLine() as perpendicular_ex:\n l1 = CenterArc((0, 0), 1.5, 0, 45)\n l2 = PolarLine(\n start=l1 @ 1, length=1, direction=l1.tangent_at(1).rotate(Axis.Z, -90)\n )\n\n.. figure:: ./assets/perpendicular_ex.svg\n :align: center\n\nThe direction vector is built from ``l1.tangent_at(1)`` rotated by 90 degrees, giving an\nexplicit perpendicular relationship relative to curve orientation.","api_names":"BuildLine CenterArc PolarLine rotate tangent_at","synonyms":""},"318":{"title":"Practical Examples","body":"The following examples show how each constraint type is used in production-style sketching.\nEach example is intentionally small, with construction geometry kept visible in code so the\nrelationship logic is explicit and reusable.","api_names":"","synonyms":""},"319":{"title":"Selecting results","body":"In Algebra mode, select from returned edges after construction:\n\n.. code-block:: build123d\n\n arcs = ConstrainedArcs(..., sagitta=Sagitta.BOTH)\n chosen = arcs.edges().sort_by(Edge.length)[0]\n\nIn Builder mode, prefer the constructor ``selector`` argument so only desired branches\nare added to the active context:\n\n.. code-block:: build123d\n\n with BuildLine():\n ConstrainedArcs(\n ...,\n selector=lambda edges: edges.sort_by_distance((0, 0))[0],\n )\n\nThis combination of qualification + selection gives robust, explicit control over\ntangency branch choice.","api_names":"BuildLine ConstrainedArcs edges selector sort_by sort_by_distance","synonyms":""},"320":{"title":"Selection recipes","body":".. code-block:: build123d\n\n # Nearest to point\n selector=lambda edges: edges.sort_by_distance((0, 0))[0]\n\n # Longest\n selector=lambda edges: edges.sort_by(Edge.length)[-1]\n\n # Right most\n selector=lambda edges: edges.sort_by(Axis.X)[-1]\n\n # Keep two branches\n selector=lambda edges: edges[:2]\n\nPrefer geometric selection criteria (distance, axis ordering, length) over positional\nindexing when upstream geometry may change.","api_names":"criteria sort_by sort_by_distance","synonyms":""},"321":{"title":"Signature A: Two constraints","body":".. code-block:: build123d\n\n ConstrainedLines(\n tangency_one,\n tangency_two,\n selector=lambda lines: lines,\n )\n\n.. figure:: ./assets/lines_tan2_ex.svg\n :align: center","api_names":"ConstrainedLines","synonyms":""},"322":{"title":"Signature A: Two constraints + ``radius``","body":".. code-block:: build123d\n\n ConstrainedArcs(\n tangency_one,\n tangency_two,\n radius=...,\n sagitta=Sagitta.SHORT,\n selector=lambda arcs: arcs,\n )\n\n.. figure:: ./assets/tan2_rad_ex.svg\n :align: center\n\nUse when radius is known and arc must satisfy two contact/tangency conditions.","api_names":"ConstrainedArcs radius","synonyms":""},"323":{"title":"Signature B: One constraint + through point","body":".. code-block:: build123d\n\n ConstrainedLines(\n tangency_one,\n (x, y), # through point\n selector=lambda lines: lines,\n )\n\n.. figure:: ./assets/lines_tan_pnt_ex.svg\n :align: center","api_names":"ConstrainedLines","synonyms":""},"324":{"title":"Signature B: Two constraints + ``center_on``","body":".. code-block:: build123d\n\n ConstrainedArcs(\n tangency_one,\n tangency_two,\n center_on=Axis(...), # or Edge\n sagitta=Sagitta.SHORT,\n selector=lambda arcs: arcs,\n )\n\n.. figure:: ./assets/tan2_on_ex.svg\n :align: center\n\nUse when center must lie on a specific line/curve rather than radius being fixed.","api_names":"Axis center_on ConstrainedArcs","synonyms":""},"325":{"title":"Signature C: One constraint + fixed orientation","body":".. code-block:: build123d\n\n ConstrainedLines(\n tangency_one,\n Axis.Y,\n angle=30, # OR direction=(dx, dy)\n selector=lambda lines: lines,\n )\n\n.. figure:: ./assets/lines_angle_ex.svg\n :align: center\n\nExactly one of ``angle`` or ``direction`` should be provided.\n\nFor all signatures, qualifiers can be attached to tangency inputs when side selection\nmust be controlled.","api_names":"angle ConstrainedLines direction","synonyms":""},"326":{"title":"Signature C: Three constraints","body":".. code-block:: build123d\n\n ConstrainedArcs(\n tangency_one,\n tangency_two,\n tangency_three,\n sagitta=Sagitta.BOTH,\n selector=lambda arcs: arcs,\n )\n\n.. figure:: ./assets/tan3_ex.svg\n :align: center\n\nUse for \"arc tangent/contact to three entities\". This can produce several branches;\nalways consider using ``selector``.","api_names":"ConstrainedArcs selector","synonyms":""},"327":{"title":"Signature D: One constraint + fixed ``center``","body":".. code-block:: build123d\n\n ConstrainedArcs(\n tangency_one,\n center=(x, y),\n selector=lambda arcs: arcs[0],\n )\n\n.. figure:: ./assets/pnt_center_ex.svg\n :align: center\n\nUseful for \"center-known\" constructions.","api_names":"center ConstrainedArcs","synonyms":""},"328":{"title":"Signature E: One constraint + radius + ``center_on``","body":".. code-block:: build123d\n\n ConstrainedArcs(\n tangency_one,\n radius=...,\n center_on=some_edge,\n selector=lambda arcs: arcs,\n )\n\n.. figure:: ./assets/tan_rad_on_ex.svg\n :align: center\n\nUseful for guided-center constructions with fixed radius.","api_names":"center_on ConstrainedArcs","synonyms":""},"329":{"title":"Tangency Constraints","body":":class:`~objects_curve.ConstrainedArcs` and :class:`~objects_curve.ConstrainedLines`\n Provide local constrained solving for 2D\n line-and-circle constructions. These APIs solve common geometric construction problems\n from explicit numeric and geometric constraints relative to existing curves.\n\n Supported constraint patterns include:\n\n - circle with specified radius,\n - line at a specified angle to another line,\n - tangency of a line or circle to a reference curve,\n - line or circle passing through a point,\n - circle center constrained to a point or to lie on a curve.\n\n For example, you can construct a circle with a given radius whose center lies on a\n specified line and which is tangent to another circle. This style of targeted solving\n covers high-value sketch workflows while keeping branch selection explicit and\n deterministic in code.","api_names":"ConstrainedArcs ConstrainedLines","synonyms":""},"330":{"title":"Tangency Constraints","body":"Both :class:`~objects_curve.ConstrainedArcs` and :class:`~objects_curve.ConstrainedLines` \nreturn a :class:`~topology.Curve` containing one or more :class:`~topology.Edge` objects.\n\nThese constructors solve tangent/contact problems from mixed numeric and geometric inputs.\nBecause tangency is often ambiguous, multiple valid branches are expected.","api_names":"ConstrainedArcs ConstrainedLines Curve Edge","synonyms":""},"331":{"title":"Tangency qualifiers","body":"Tangency qualifiers come from OCCT and are exposed as ``Tangency``:\n\n- ``Tangency.UNQUALIFIED``:\n no side preference (OCCT ``Unqualified``).\n- ``Tangency.OUTSIDE``:\n tangent on the exterior side of the target (OCCT ``Outside``).\n- ``Tangency.ENCLOSING``:\n solution encloses/includes the target (OCCT ``Enclosing``).\n- ``Tangency.ENCLOSED``:\n solution is enclosed/included by the target (OCCT ``Enclosed``).\n\nThese semantics are most visible for curve-vs-curve constraints (for example circle\nto circle, line to circle). In many practical cases, ``UNQUALIFIED`` is a good default\nfollowed by filtering via ``selector``.\n\n.. code-block:: build123d\n\n with BuildLine() as egg_plant:\n # Construction Geometry\n c1 = CenterArc((-2, 0), 0.75, 80, 240, mode=Mode.PRIVATE)\n c2 = CenterArc((2, 0), 1, 220, 250, mode=Mode.PRIVATE)\n\n # egg_plant perimeter\n l1 = ConstrainedArcs((c2, Tangency.OUTSIDE), (c1, Tangency.OUTSIDE), radius=6)\n l2 = ConstrainedArcs(\n (c2, Tangency.ENCLOSING),\n (c1, Tangency.ENCLOSING),\n radius=8,\n selector=lambda a: a.sort_by(Axis.Y)[-1],\n )\n l3 = add(c1.trim(l1 @ 1, l2 @ 1))\n l4 = add(c2.trim(l1 @ 0, l2 @ 0))\n\n.. figure:: ./assets/enclosing_ex.svg\n :align: center\n\nIn the \"egg-plant\" example, ``Tangency.OUTSIDE`` and ``Tangency.ENCLOSING`` reduce the\ncandidate branches to the intended outer profile. The selector on ``l2`` then resolves\nthe remaining ambiguity deterministically by choosing the highest branch in ``Y``.\n\nOCCT defines exterior/interior using orientation:\n\n- Circle: exterior is on the right side when traversing by its orientation\n (interior/material is on the left side).\n- Line/open curve: interior is the left side with respect to traversal direction,\n exterior is the opposite side.\n\nBecause of this, changing an input edge direction can change which branches satisfy\n``OUTSIDE``/``ENCLOSING``/``ENCLOSED``.\n\nIf qualifier behavior appears inverted, inspect input edge orientation first.","api_names":"add BuildLine CenterArc ConstrainedArcs constraints Enclosed ENCLOSED Enclosing ENCLOSING l2 orientation Outside OUTSIDE preference selector sort_by Tangency target trim Unqualified UNQUALIFIED Y","synonyms":""},"332":{"title":"Tangent","body":".. code-block:: build123d\n\n with BuildLine() as tangent_ex:\n l1 = Line((0, 0), (1, 1))\n l2 = JernArc(start=l1 @ 1, tangent=l1 % 1, radius=1, arc_size=70)\n\n.. figure:: ./assets/tangent_ex.svg\n :align: center\n\nThe arc starts at the line endpoint and uses ``l1 % 1`` as its initial tangent direction.\nThis is a direct tangent construction: continuity is encoded in the creation call.","api_names":"BuildLine JernArc l1 Line","synonyms":""},"333":{"title":"Troubleshooting","body":"- Too many results:\n add qualifiers and a stricter ``selector``.\n- No results:\n relax qualifier (start with ``UNQUALIFIED``) and verify geometry is coplanar.\n- Unstable branch selection:\n avoid index-only selection when topology changes; prefer geometric sorting.\n- Builder mode unexpectedly adds many edges:\n provide ``selector`` explicitly in the constructor call.","api_names":"qualifier selector UNQUALIFIED","synonyms":""},"334":{"title":"Designing a Part in build123d","body":"Designing a part with build123d involves a systematic approach that leverages the power\nof 2D profiles, extrusions, and revolutions. Where possible, always work in the lowest\npossible dimension, 1D lines before 2D sketches before 3D parts. The following guide will\nget you started:\n\n*As an example, we'll go through the design process for this bracket:*\n\n.. image:: assets/bracket_hand_drawing.jpg\n :align: center","api_names":"","synonyms":""},"335":{"title":"Step 1. Examine the Part in All Three Orientations","body":"Start by visualizing the part from the front, top, and side views. Identify any symmetries\nin these orientations, as symmetries can simplify the design by reducing the number of\nunique features you need to model.\n\n*In the following view of the bracket one can see two planes of symmetry\nso we'll only need to design one quarter of it.*\n\n.. image:: assets/bracket_with_symmetry.png\n :align: center","api_names":"","synonyms":""},"336":{"title":"Step 10. Plan for Parametric Flexibility","body":"Wherever possible, make your design parametric, allowing dimensions and features to be \neasily adjusted later. This flexibility can be crucial if the design needs modifications \nor if variations of the part are needed.\n\n*The dimensions of the bracket are defined as follows:*\n\n.. code-block:: build123d\n\n thickness = 3 * MM\n width = 25 * MM\n length = 50 * MM\n height = 25 * MM\n hole_diameter = 5 * MM\n bend_radius = 5 * MM\n fillet_radius = 2 * MM","api_names":"","synonyms":"bevel edge bore drill recessed fastener round edge"},"337":{"title":"Step 11. Test Fit and Tolerances","body":"Visualize the fit of the part within its intended assembly. Consider tolerances for \nmanufacturing, such as clearance between moving parts or shrinkage for 3D-printed parts. \nAdjust the design as needed to ensure real-world functionality.","api_names":"","synonyms":"fit gap tolerance"},"338":{"title":"Step 2. Identify Rotational Symmetries","body":"Look for structures that could be created through the rotation of a 2D shape. For instance,\ncylindrical or spherical features are often the result of revolving a profile around an axis.\nIdentify the axis of rotation and make a note of it.\n\n*There are no rotational structures in the example bracket.*","api_names":"","synonyms":""},"339":{"title":"Step 3. Select a Convenient Origin","body":"Choose an origin point that minimizes the need to move or transform components later in the\ndesign process. Ideally, the origin should be placed at a natural center of symmetry or a\ncritical reference point on the part.\n\n*The planes of symmetry for the bracket was identified in step 1, making it logical to\nplace the origin at the intersection of these planes on the bracket's front face. Additionally,\nwe'll define the coordinate system we'll be working in: Plane.XY (the default), where\nthe origin is set at the global (0,0,0) position. In this system, the x-axis aligns with\nthe front of the bracket, and the z-axis corresponds to its width. It’s important to note\nthat all coordinate systems/planes in build123d adhere to the*\n`right-hand rule `_ *meaning the y-axis is\nautomatically determined by this convention.*\n\n.. image:: assets/bracket_with_origin.png\n :align: center","api_names":"global XY","synonyms":""},"340":{"title":"Step 4. Create 2D Profiles","body":"Design the 2D profiles of your part in the appropriate orientation(s). These profiles are\nthe foundation of the part's geometry and can often represent cross-sections of the part.\nMirror parts of profiles across any axes of symmetry identified earlier.\n\n*The 2D profile of the bracket is as follows:*\n\n.. image:: assets/bracket_sketch.png\n :align: center\n\n*The build123d code to generate this profile is as follows:*\n\n.. code-block:: build123d\n\n with BuildSketch() as sketch:\n with BuildLine() as profile:\n FilletPolyline(\n (0, 0), (length / 2, 0), (length / 2, height), radius=bend_radius\n )\n offset(amount=thickness, side=Side.LEFT)\n make_face()\n mirror(about=Plane.YZ)\n\n*This code creates a 2D sketch of a mirrored profile in the build123d CAD system. Here's a step-by-step explanation of what it does:*\n\n with BuildSketch() as sketch:\n *This starts a context for creating a 2D sketch, which defines the overall boundary and geometric features. The sketch will be stored in the variable sketch.*\n\n with BuildLine() as profile:\n *This starts another context, this time for drawing lines (or profiles) within the sketch. The profile consists of connected line segments, arcs, or polylines.*\n\n FilletPolyline((0, 0), (length / 2, 0), (length / 2, height), radius=bend_radius)\n *This object draws a polyline with three points: (0,0), (length/2, 0), and (length/2, height). A fillet (curved corner) with a radius of bend_radius is added where applicable between the segments of the polyline.*\n\n offset(amount=thickness, side=Side.LEFT)\n *This applies an offset to the polyline created earlier. The offset creates a parallel line at a distance of thickness to the left side of the original polyline. This operation essentially thickens the profile by a given amount.*\n\n make_face()\n *This command creates a 2D face from the closed profile. The offset operation ensures that the profile is closed, allowing the creation of a solid face from the boundary defined.*\n\n mirror(about=Plane.YZ)\n *This mirrors the entire face about the YZ plane (which runs along the center of the sketch), creating a symmetrical counterpart of the face. The mirrored geometry will complete the final shape.*","api_names":"BuildLine BuildSketch fillet FilletPolyline lines make_face mirror offset orientation plane","synonyms":"bevel edge fit gap hollow reflect round edge shell symmetry tolerance wall thickness"},"341":{"title":"Step 5. Use Extrusion for Prismatic Features","body":"For solid or prismatic shapes, extrude the 2D profiles along the necessary axis. You can \nalso combine multiple extrusions by intersecting or unionizing them to form complex shapes. \nUse the resulting geometry as sub-parts if needed.\n\n*The next step in implementing our design in build123d is to convert the above sketch into\na part by extruding it as shown in this code:*\n\n.. code-block:: build123d\n\n with BuildPart() as bracket:\n with BuildSketch() as sketch:\n with BuildLine() as profile:\n FilletPolyline(\n (0, 0), (length / 2, 0), (length / 2, height), radius=bend_radius\n )\n offset(amount=thickness, side=Side.LEFT)\n make_face()\n mirror(about=Plane.YZ)\n extrude(amount=width / 2)\n mirror(about=Plane.XY)\n\n*In this example, we've wrapped the sketch within a BuildPart context, which is used \nfor creating 3D parts. We utilized the extrude function to extend the 2D sketch into \na solid object, turning it into a 3D part. Additionally, we applied the mirror function \nto replicate the partial part across a plane of symmetry, ensuring a symmetrical design.*","api_names":"BuildLine BuildPart BuildSketch extrude FilletPolyline make_face mirror offset","synonyms":"bevel edge fit gap hollow reflect round edge shell symmetry tolerance wall thickness"},"342":{"title":"Step 6. Generate Revolved Features","body":"If any part of the geometry can be created by revolving a 2D profile around an axis, use \nthe revolve operation. This is particularly useful for parts that include cylindrical, \nconical, or spherical features. Combine these revolved sub-parts with existing features \nusing additive, subtractive, or intersecting operations.\n\n*Our example has no revolved features.*","api_names":"","synonyms":"axisymmetric lathe turned"},"343":{"title":"Step 7. Combine Sub-parts Intelligently","body":"When combining multiple sub-parts, keep in mind whether they need to be added, subtracted, \nor intersected. Subtracting or intersecting can create more refined details, while addition \nis useful for creating complex assemblies.\n\n*Out example only has one sub-part but further sub-parts could be created in the\nBuildPart context by defining more sketches and extruding or revolving them.*","api_names":"","synonyms":""},"344":{"title":"Step 8. Apply Chamfers and Fillets","body":"Identify critical edges or vertices that need chamfering or filleting. Use build123d’s \nselectors to apply these operations accurately. Always visually inspect the results to \nensure the correct edges have been modified.\n\n*The back corners of the bracket need to be rounded off or filleted so the edges that\ndefine these corners need to be isolated. The following code, placed to follow the previous\ncode block, captures just these edges:*\n\n.. code-block:: build123d\n\n corners = bracket.edges().filter_by(Axis.X).group_by(Axis.Y)[-1]\n fillet(corners, fillet_radius)\n\n*These lines isolates specific corner edges that are then filleted.*\n\n corners = bracket.edges().filter_by(Axis.X).group_by(Axis.Y)[-1]\n *This line is used to select specific edges from the 3D part (bracket) that was \n created by the extrusion.*\n\n - bracket.edges() *retrieves all the edges of the bracket part.*\n - filter_by(Axis.X) *filters the edges to only those that are aligned along the \n X-axis.*\n - group_by(Axis.Y) *groups the edges by their positions along the Y-axis. This \n operation essentially organizes the filtered X-axis edges into groups based on \n their Y-coordinate positions.*\n - [-1] *selects the last group of edges along the Y-axis, which corresponds \n to the back of the part - the edges we are looking for.*\n\n\n fillet(corners, fillet_radius)\n *This function applies a fillet (a rounded edge) to the selected corners, with a \n specified radius (fillet_radius). The fillet smooths the sharp edges at the corners, \n giving the part a more refined shape.*","api_names":"edges fillet filter_by group_by part radius","synonyms":"bevel edge round edge"},"345":{"title":"Step 9. Design for Assembly","body":"If the part is intended to connect with others, add features like joints, holes, or other \nattachment points. Ensure that these features are precisely located to ensure proper fitment \nand functionality in the final assembly.\n\n*Our example has two circular holes and a slot that need to be created. First we'll create\nthe two circular holes:*\n\n.. code-block:: build123d\n\n with Locations(bracket.faces().sort_by(Axis.X)[-1]):\n Hole(hole_diameter / 2)\n\n*This code creates a hole in a specific face of the bracket part.*\n\n with Locations(bracket.faces().sort_by(Axis.X)[-1]):\n *This context sets a location(s) for subsequent operations.*\n\n - bracket.faces() *retrieves all the faces of the bracket part.*\n - sort_by(Axis.X) *sorts these faces based on their position along the X-axis (from \n one side of the bracket to the other).*\n - [-1] *selects the last face in this sorted list, which would be the face farthest \n along the X-axis, the extreme right side of the part.*\n - Locations() *creates a new local context or coordinate system at the selected face, \n effectively setting this face as the working location for any subsequent operations \n inside the with block.*\n\n Hole(hole_diameter / 2)\n *This creates a hole in the selected face. The radius of the hole is specified as \n hole_diameter / 2. The hole is placed at the origin of the selected face, based on \n the local coordinate system created by Locations(). As the depth of the hole is\n not provided it is assumed to go entirely through the part.*\n\n*Next the slot needs to be created in the bracket with will be done by sketching a slot on \nthe front of the bracket and extruding the sketch through the part.*\n\n.. code-block:: build123d\n\n with BuildSketch(bracket.faces().sort_by(Axis.Y)[0]):\n SlotOverall(20 * MM, hole_diameter)\n extrude(amount=-thickness, mode=Mode.SUBTRACT)\n\n*Here’s a detailed explanation of what each part does:*\n\n with BuildSketch(bracket.faces().sort_by(Axis.Y)[0]):\n *This line sets up a sketching context.*\n\n - bracket.faces() *retrieves all the faces of the bracket part.*\n - sort_by(Axis.Y) *sorts the faces along the Y-axis, arranging them from the lowest \n Y-coordinate to the highest.*\n - [0] *selects the first face in this sorted list, which is the one located at the \n lowest Y-coordinate, the nearest face of the part.*\n - BuildSketch() *creates a new sketching context on this selected face, where 2D \n geometry will be drawn.*\n\n SlotOverall(20, hole_diameter)\n *This command draws a slot (a rounded rectangle or elongated hole) on the selected \n face. The slot has a total length of 20 mm and a width equal to hole_diameter. \n The slot is defined within the 2D sketch on the selected face of the bracket.*\n\n extrude(amount=-thickness, mode=Mode.SUBTRACT)\n extrude() *takes the 2D sketch (the slot) and extends it into the 3D space by a \n distance equal to -thickness, creating a cut into the part. The negative value \n (-thickness) indicates that the extrusion is directed inward into the part (a cut).*\n mode=Mode.SUBTRACT *specifies that the extrusion is a subtractive operation, \n meaning it removes material from the bracket, effectively cutting the slot through \n the face of the part.*\n\n*Although beyond the scope of this tutorial, joints could be defined for each of the\nholes to allow programmatic connection to other parts.*","api_names":"axis BuildSketch extrude faces Hole location Locations part sketch slot SlotOverall sort_by value","synonyms":"array bore channel drill groove path cut pattern recessed fastener repeat"},"346":{"title":"Summary","body":"These steps should guide you through a logical and efficient workflow in build123d\n(or any CAD tool), helping you to design parts with accuracy and ease.\n\n*The entire code block for the bracket example is shown here:*\n\n.. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import show_all\n\n thickness = 3 * MM\n width = 25 * MM\n length = 50 * MM\n height = 25 * MM\n hole_diameter = 5 * MM\n bend_radius = 5 * MM\n fillet_radius = 2 * MM\n\n with BuildPart() as bracket:\n with BuildSketch() as sketch:\n with BuildLine() as profile:\n FilletPolyline(\n (0, 0), (length / 2, 0), (length / 2, height), radius=bend_radius\n )\n offset(amount=thickness, side=Side.LEFT)\n make_face()\n mirror(about=Plane.YZ)\n extrude(amount=width / 2)\n mirror(about=Plane.XY)\n corners = bracket.edges().filter_by(Axis.X).group_by(Axis.Y)[-1]\n fillet(corners, fillet_radius)\n with Locations(bracket.faces().sort_by(Axis.X)[-1]):\n Hole(hole_diameter / 2)\n with BuildSketch(bracket.faces().sort_by(Axis.Y)[0]):\n SlotOverall(20 * MM, hole_diameter)\n extrude(amount=-thickness, mode=Mode.SUBTRACT)\n\n show_all()\n\n.. image:: assets/bracket.png\n :align: center","api_names":"build123d BuildLine BuildPart BuildSketch edges extrude faces fillet FilletPolyline filter_by group_by Hole Locations make_face mirror offset show_all SlotOverall sort_by","synonyms":"array bevel edge bore channel drill fit gap groove hollow path cut pattern recessed fastener reflect repeat round edge shell symmetry tolerance wall thickness"},"347":{"title":"Conclusion","body":"Use a :class:`~topology.Joint` to locate two objects relative to each other with some degree of motion.\nKeep in mind that when using the ``connect_to`` method, ``self`` is always fixed\nand ``other`` will move to the appropriate :class:`~geometry.Location`.\n\n.. note::\n\n The joint symbols can be displayed as follows (your viewer may use ``show`` instead\n of ``show_object``):\n\n .. code:: python\n\n show_object(box.joints[\"hinge_attachment\"].symbol, name=\"box attachment point\")\n\n or\n\n .. code:: python\n\n show_object(m6_joint.symbol, name=\"m6 screw symbol\")\n\n or, with the ocp_vscode viewer\n\n .. code:: python\n\n show(box, render_joints=True)","api_names":"connect_to follows Joint Location other self show show_object","synonyms":""},"348":{"title":"Joint Tutorial","body":"This tutorial provides a step by step guide in using :class:`~topology.Joint`'s as we create\na box with a hinged lid to illustrate the use of three different :class:`~topology.Joint` types.\n\n.. image:: assets/tutorial_joint.svg\n :align: center","api_names":"Joint","synonyms":""},"349":{"title":"Step 1: Setup","body":"Before getting to the CAD operations, this selector script needs to import the build123d\nenvironment.\n\n.. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import *","api_names":"","synonyms":""},"350":{"title":"Step 2: Create Hinge","body":"This example uses a common Butt Hinge to connect the lid to the box base so a ``Hinge`` class\nis used to create that can create either of the two hinge leaves. As the focus of this\ntutorial is the joints and not the CAD operations to create objects, this code is not\ndescribed in detail.\n\n.. code-block:: build123d\n\n class Hinge(Compound):\n \"\"\"Hinge\n \n Half a simple hinge with several joints. The joints are:\n - \"leaf\": RigidJoint where hinge attaches to object\n - \"hinge_axis\": RigidJoint (inner) or RevoluteJoint (outer)\n - \"hole0\", \"hole1\", \"hole2\": CylindricalJoints for attachment screws\n \n Args:\n width (float): width of one leaf\n length (float): hinge length\n barrel_diameter (float): size of hinge pin barrel\n thickness (float): hinge leaf thickness\n pin_diameter (float): hinge pin diameter\n inner (bool, optional): inner or outer half of hinge . Defaults to True.\n \"\"\"\n \n def __init__(\n self,\n width: float,\n length: float,\n barrel_diameter: float,\n thickness: float,\n pin_diameter: float,\n inner: bool = True,\n ):\n # The profile of the hinge used to create the tabs\n with BuildPart() as hinge_profile:\n with BuildSketch():\n for i, loc in enumerate(\n GridLocations(0, length / 5, 1, 5, align=(Align.MIN, Align.MIN))\n ):\n if i % 2 == inner:\n with Locations(loc):\n Rectangle(width, length / 5, align=(Align.MIN, Align.MIN))\n Rectangle(\n width - barrel_diameter,\n length,\n align=(Align.MIN, Align.MIN),\n )\n extrude(amount=-barrel_diameter)\n \n # The hinge pin\n with BuildPart() as pin:\n Cylinder(\n radius=pin_diameter / 2,\n height=length,\n align=(Align.CENTER, Align.CENTER, Align.MIN),\n )\n with BuildPart(pin.part.faces().sort_by(Axis.Z)[-1]) as pin_head:\n Cylinder(\n radius=barrel_diameter / 2,\n height=pin_diameter,\n align=(Align.CENTER, Align.CENTER, Align.MIN),\n )\n fillet(\n pin_head.edges(Select.LAST).filter_by(GeomType.CIRCLE),\n radius=pin_diameter / 3,\n )\n \n # Either the external and internal leaf with joints\n with BuildPart() as leaf_builder:\n with BuildSketch():\n with BuildLine():\n l1 = Line((0, 0), (width - barrel_diameter / 2, 0))\n l2 = RadiusArc(\n l1 @ 1,\n l1 @ 1 + Vector(0, barrel_diameter),\n -barrel_diameter / 2,\n )\n l3 = RadiusArc(\n l2 @ 1,\n (\n width - barrel_diameter,\n barrel_diameter / 2,\n ),\n -barrel_diameter / 2,\n )\n l4 = Line(l3 @ 1, (width - barrel_diameter, thickness))\n l5 = Line(l4 @ 1, (0, thickness))\n Line(l5 @ 1, l1 @ 0)\n make_face()\n with Locations(\n (width - barrel_diameter / 2, barrel_diameter / 2)\n ) as pin_center:\n Circle(pin_diameter / 2 + 0.1 * MM, mode=Mode.SUBTRACT)\n extrude(amount=length)\n add(hinge_profile.part, rotation=(90, 0, 0), mode=Mode.INTERSECT)\n \n # Create holes for fasteners\n with Locations(leaf_builder.part.faces().filter_by(Axis.Y)[-1]):\n with GridLocations(0, length / 3, 1, 3):\n holes = CounterSinkHole(3 * MM, 5 * MM)\n # Add the hinge pin to the external leaf\n if not inner:\n with Locations(pin_center.locations[0]):\n add(pin.part)\n \n\nOnce the two leaves have been created they will look as follows:\n\n.. image:: assets/tutorial_joint_outer_leaf.svg\n :width: 40 %\n.. image:: assets/tutorial_joint_inner_leaf.svg\n :width: 40 %\n\nNote that the XYZ indicators and a circle around the hinge pin indicate\njoints that are discussed below.","api_names":"__init__ add barrel_diameter BuildLine BuildPart BuildSketch Circle CounterSinkHole Cylinder edges extrude faces fillet filter_by GridLocations Hinge inner length Line Locations make_face pin_diameter RadiusArc Rectangle RevoluteJoint RigidJoint sort_by thickness Vector width","synonyms":"array bevel edge bore channel drill groove path cut pattern recessed fastener repeat round edge"},"351":{"title":"Step 3: Add Joints to the Hinge Leaf","body":"The hinge includes five joints:\n\n* A :class:`~topology.RigidJoint` to attach the leaf\n* A :class:`~topology.RigidJoint` or :class:`~topology.RevoluteJoint` as the hinge Axis\n* Three :class:`~topology.CylindricalJoint`'s for the countersunk screws","api_names":"CylindricalJoint RevoluteJoint RigidJoint","synonyms":""},"352":{"title":"Step 3a: Leaf Joint","body":"The first joint to add is a :class:`~topology.RigidJoint` that is used to fix the hinge leaf to the box\nor lid.\n\n.. code-block:: build123d\n\n #\n # Leaf attachment\n RigidJoint(\n label=\"leaf\",\n joint_location=Location(\n (width - barrel_diameter, 0, length / 2), (90, 0, 0)\n ),\n )\n\nEach joint has a label which identifies it - here the string \"leaf\" is used, the ``to_part``\nbinds the joint to ``leaf_builder.part`` (i.e. the part being built), and ``joint_location``\nis specified as middle of the leaf along the edge of the pin. Note that\n:class:`~geometry.Location` objects describe both a position and orientation which is\nwhy there are two tuples (the orientation listed is rotate about the X axis 90 degrees).","api_names":"joint_location Location part RigidJoint to_part tuples","synonyms":""},"353":{"title":"Step 3b: Hinge Joint","body":"The second joint to add is either a :class:`~topology.RigidJoint` (on the inner leaf) or a :class:`~topology.RevoluteJoint`\n(on the outer leaf) that describes the hinge axis.\n\n.. code-block:: build123d\n\n #\n # Leaf attachment\n RigidJoint(\n label=\"leaf\",\n joint_location=Location(\n (width - barrel_diameter, 0, length / 2), (90, 0, 0)\n ),\n )\n # [Hinge Axis] (fixed with inner)\n if inner:\n RigidJoint(\n \"hinge_axis\",\n joint_location=Location(\n (width - barrel_diameter / 2, barrel_diameter / 2, 0)\n ),\n )\n else:\n RevoluteJoint(\n \"hinge_axis\",\n axis=Axis(\n (width - barrel_diameter / 2, barrel_diameter / 2, 0), (0, 0, 1)\n ),\n angular_range=(90, 270),\n )\n\nThe inner leaf just pivots around the outer leaf and therefore the simple :class:`~topology.RigidJoint` is\nused to define the Location of this pivot. The outer leaf contains the more complex\n:class:`~topology.RevoluteJoint` which defines an axis of rotation and angular limits to that rotation (90\nand 270 in this example as the two leaves will interfere with each other outside of this range).\nNote that the maximum angle must be greater than the minimum angle and therefore may be greater\nthan 360°. Other types of joints have linear ranges as well as angular ranges.","api_names":"Axis Location RevoluteJoint RigidJoint rotation","synonyms":""},"354":{"title":"Step 3c: Fastener Joints","body":"The third set of joints to add are :class:`~topology.CylindricalJoint`'s that describe how the countersunk\nscrews used to attach the leaves move.\n\n.. code-block:: build123d\n\n hole_locations = [hole.location for hole in holes]\n for hole, hole_location in enumerate(hole_locations):\n CylindricalJoint(\n label=\"hole\" + str(hole),\n axis=Axis(hole_location),\n linear_range=(-2 * CM, 2 * CM),\n angular_range=(0, 360),\n )\n\nMuch like the :class:`~topology.RevoluteJoint`, a :class:`~topology.CylindricalJoint` has an Axis of motion but this type\nof joint allows both movement around and along this axis - exactly as a screw would move.\nHere is the Axis is setup such that a position of 0 aligns with the screw being fully set\nin the hole and positive numbers indicate the distance the head of the screw is above the\nleaf surface. One could have reversed the direction of the Axis such that negative position\nvalues would correspond to a screw now fully in the hole - whatever makes sense to the situation.\nThe angular range of this joint is set to (0°, 360°) as there is no limit to the angular rotation\nof the screw (one could choose to model thread pitch and calculate position from angle or\nvice-versa).","api_names":"Axis CylindricalJoint RevoluteJoint screw to","synonyms":"array bore drill pattern recessed fastener repeat"},"355":{"title":"Step 3d: Call Super","body":"To finish off, the base class for the Hinge class is initialized:\n\n.. code-block:: build123d\n\n super().__init__(leaf_builder.part.wrapped, joints=leaf_builder.part.joints)","api_names":"__init__ super","synonyms":""},"356":{"title":"Step 3e: Instantiate Hinge Leaves","body":"Now that the Hinge class is complete it can be used to instantiate the two hinge leaves\nrequired to attach the box and lid together.\n\n.. code-block:: build123d\n\n hinge_inner = Hinge(\n width=5 * CM,\n length=12 * CM,\n barrel_diameter=1 * CM,\n thickness=2 * MM,\n pin_diameter=4 * MM,\n )\n hinge_outer = Hinge(\n width=5 * CM,\n length=12 * CM,\n barrel_diameter=1 * CM,\n thickness=2 * MM,\n pin_diameter=4 * MM,\n inner=False,\n )","api_names":"Hinge","synonyms":""},"357":{"title":"Step 4: Create the Box","body":"The box is created with :class:`~build_part.BuildPart` as a simple object - as shown below - let's focus on\nthe joint used to attach the outer hinge leaf.\n\n.. image:: assets/tutorial_joint_box.svg\n :align: center\n\n.. code-block:: build123d\n\n with BuildPart() as box_builder:\n box = Box(30 * CM, 30 * CM, 10 * CM)\n offset(amount=-1 * CM, openings=box_builder.faces().sort_by(Axis.Z)[-1])\n # Create a notch for the hinge\n with Locations((-15 * CM, 0, 5 * CM)):\n Box(2 * CM, 12 * CM, 4 * MM, mode=Mode.SUBTRACT)\n bbox = box.bounding_box()\n with Locations(\n Plane(origin=(bbox.min.X, 0, bbox.max.Z - 30 * MM), z_dir=(-1, 0, 0))\n ):\n with GridLocations(0, 40 * MM, 1, 3):\n Hole(3 * MM, 1 * CM)\n RigidJoint(\n \"hinge_attachment\",\n joint_location=Location((-15 * CM, 0, 4 * CM), (180, 90, 0)),\n )\n\nSince the hinge will be fixed to the box another :class:`~topology.RigidJoint` is used mark where the hinge\nwill go. Note that the orientation of this :class:`~topology.Joint` will control how the hinge leaf is\nattached and is independent of the orientation of the hinge as it was constructed.","api_names":"bounding_box Box BuildPart faces GridLocations Hole Joint Location Locations offset Plane RigidJoint sort_by","synonyms":"array bore channel drill fit gap groove hollow path cut pattern recessed fastener repeat shell tolerance wall thickness"},"358":{"title":"Step 4a: Relocate Box","body":"Note that the position and orientation of the box's joints are given as a global :class:`~geometry.Location`\nwhen created but will be translated to a relative :class:`~geometry.Location` internally to allow the :class:`~topology.Joint`\nto \"move\" with the parent object. This allows users the freedom to relocate objects without\nhaving to recreate or modify :class:`~topology.Joint`'s. Here is the box is moved upwards to show this\nproperty.\n\n.. code-block:: build123d\n\n box = box_builder.part.moved(Location((0, 0, 5 * CM)))","api_names":"Joint Location moved","synonyms":""},"359":{"title":"Step 5: Create the Lid","body":"Much like the box, the lid is created in a :class:`~build_part.BuildPart` context and is assigned a :class:`~topology.RigidJoint`.\n\n.. image:: assets/tutorial_joint_lid.svg\n :align: center\n\n.. code-block:: build123d\n\n with BuildPart() as lid_builder:\n Box(30 * CM, 30 * CM, 1 * CM, align=(Align.MIN, Align.CENTER, Align.MIN))\n with Locations((2 * CM, 0, 0)):\n with GridLocations(0, 40 * MM, 1, 3):\n Hole(3 * MM, 1 * CM)\n RigidJoint(\n \"hinge_attachment\",\n joint_location=Location((0, 0, 0), (0, 0, 180)),\n )\n lid = lid_builder.part\n \n\nAgain, the original orientation of the lid and hinge inner leaf are not important, when the\njoints are connected together the parts will move into the correct position.","api_names":"Box BuildPart GridLocations Hole Location Locations RigidJoint","synonyms":"array bore drill pattern recessed fastener repeat"},"360":{"title":"Step 6: Import a Screw and bind a Joint to it","body":":class:`~topology.Joint`'s can be bound to simple objects the a :class:`~topology.Compound` imported - in this case a\nscrew.\n\n- screw STEP model: :download:`M6-1x12-countersunk-screw.step `\n\n.. image:: assets/tutorial_joint_m6_screw.svg\n :align: center\n\n.. code-block:: build123d\n\n m6_screw = import_step(\"M6-1x12-countersunk-screw.step\")\n m6_joint = RigidJoint(\"head\", m6_screw, Location((0, 0, 0), (0, 0, 0)))\n\nHere a simple :class:`~topology.RigidJoint` is bound to the top of the screw head such that it can be\nconnected to the hinge's :class:`~topology.CylindricalJoint`.","api_names":"Compound CylindricalJoint import_step Joint Location RigidJoint","synonyms":""},"361":{"title":"Step 7: Connect the Joints together","body":"This last step is the most interesting. Now that all of the joints have been defined\nand bound to their parent objects, they can be connected together.","api_names":"","synonyms":""},"362":{"title":"Step 7a: Hinge to Box","body":"To start, the outer hinge leaf will be connected to the box, as follows:\n\n.. code-block:: build123d\n\n box.joints[\"hinge_attachment\"].connect_to(hinge_outer.joints[\"leaf\"])\n\nHere the ``hinge_attachment`` joint of the ``box`` is connected to the ``leaf`` joint\nof ``hinge_outer``. Note that the hinge leaf is the object to move. Once this line\nis executed, we get the following:\n\n.. image:: assets/tutorial_joint_box_outer.svg\n :align: center","api_names":"box connect_to hinge_attachment hinge_outer leaf","synonyms":""},"363":{"title":"Step 7b: Hinge to Hinge","body":"Next, the hinge inner leaf is connected to the hinge outer leaf which is attached to the\nbox.\n\n.. code-block:: build123d\n\n hinge_outer.joints[\"hinge_axis\"].connect_to(hinge_inner.joints[\"hinge_axis\"], angle=120)\n\nAs ``hinge_outer.joints[\"hinge_axis\"]`` is a :class:`~topology.RevoluteJoint` there is an ``angle``\nparameter that can be set (angles default to the minimum range value) - here to 120°.\nThis is what that looks like:\n\n.. image:: assets/tutorial_joint_box_outer_inner.svg\n :align: center","api_names":"angle connect_to joints RevoluteJoint","synonyms":""},"364":{"title":"Step 7c: Lid to Hinge","body":"Now the ``lid`` is connected to the ``hinge_inner``:\n\n.. code-block:: build123d\n\n hinge_inner.joints[\"leaf\"].connect_to(lid.joints[\"hinge_attachment\"])\n\nwhich results in:\n\n.. image:: assets/tutorial_joint_box_outer_inner_lid.svg\n :align: center\n\nNote how the lid is now in an open position. To close the lid just change the above ``angle``\nparameter from 120° to 90°.","api_names":"angle connect_to hinge_inner lid","synonyms":""},"365":{"title":"Step 7d: Screw to Hinge","body":"The last step in this example is to place a screw in one of the hinges:\n\n.. code-block:: build123d\n\n hinge_outer.joints[\"hole2\"].connect_to(m6_joint, position=5 * MM, angle=30)\n\nAs the position is a positive number the screw is still proud of the hinge face as shown\nhere:\n\n.. image:: assets/tutorial_joint.svg\n :align: center\n\nTry changing these position and angle values to \"tighten\" the screw.","api_names":"connect_to","synonyms":"bore drill recessed fastener"},"366":{"title":"Lego Tutorial","body":"This tutorial provides a step by step guide to creating a script to build a parametric\nLego block as shown here:\n\n.. image:: assets/lego.svg\n :align: center","api_names":"","synonyms":""},"367":{"title":"Step 1: Setup","body":"Before getting to the CAD operations, this Lego script needs to import the build123d\nenvironment. There are over 100 python classes in build123d so we'll just import them\nall with a ``from build123d import *`` but :ref:`there are other options ` that we won't explore\nhere.\n\nThe dimensions of the Lego block follow. A key parameter is ``pip_count``, the length\nof the Lego blocks in pips. This parameter must be at least 2.\n\n.. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import show_object\n pip_count = 6\n \n lego_unit_size = 8\n pip_height = 1.8\n pip_diameter = 4.8\n block_length = lego_unit_size * pip_count\n block_width = 16\n base_height = 9.6\n block_height = base_height + pip_height\n support_outer_diameter = 6.5\n support_inner_diameter = 4.8\n ridge_width = 0.6\n ridge_depth = 0.3\n wall_thickness = 1.2","api_names":"from pip_count","synonyms":""},"368":{"title":"Step 10: Adding a Top","body":"Now that the walls are complete, the top of the block needs to be added. Although this\ncould be done with another sketch, we'll add a box to the top of the walls.\n\n.. code-block:: build123d\n\n with BuildPart() as lego:\n # Draw the bottom of the block\n with BuildSketch() as plan:\n # Start with a Rectangle the size of the block\n perimeter = Rectangle(width=block_length, height=block_width)\n # Subtract an offset to create the block walls\n offset(\n perimeter,\n -wall_thickness,\n kind=Kind.INTERSECTION,\n mode=Mode.SUBTRACT,\n )\n # Add a grid of lengthwise and widthwise bars\n with GridLocations(x_spacing=0, y_spacing=lego_unit_size, x_count=1, y_count=2):\n Rectangle(width=block_length, height=ridge_width)\n with GridLocations(lego_unit_size, 0, pip_count, 1):\n Rectangle(width=ridge_width, height=block_width)\n # Subtract a rectangle leaving ribs on the block walls\n Rectangle(\n block_length - 2 * (wall_thickness + ridge_depth),\n block_width - 2 * (wall_thickness + ridge_depth),\n mode=Mode.SUBTRACT,\n )\n # Add a row of hollow circles to the center\n with GridLocations(\n x_spacing=lego_unit_size, y_spacing=0, x_count=pip_count - 1, y_count=1\n ):\n Circle(radius=support_outer_diameter / 2)\n Circle(radius=support_inner_diameter / 2, mode=Mode.SUBTRACT)\n # Extrude this base sketch to the height of the walls\n extrude(amount=base_height - wall_thickness)\n # Create a box on the top of the walls\n with Locations((0, 0, lego.vertices().sort_by(Axis.Z)[-1].Z)):\n # Create the top of the block\n Box(\n length=block_length,\n width=block_width,\n height=wall_thickness,\n align=(Align.CENTER, Align.CENTER, Align.MIN),\n )\n\nTo position the top, we'll describe the top center of the lego walls with a ``Locations`` context.\nTo determine the height we'll extract that from the\n``lego.part`` by using the ``vertices()`` method which returns a list of the positions\nof all of the vertices of the Lego block so far. Since we're interested in the top,\nwe'll sort by the vertical (Z) axis and take the top of the list ``sort_by(Axis.Z)[-1]``. Finally,\nthe ``Z`` property of this vertex will return just the height of the top. Note that\nthe ``X`` and ``Y`` values are not used from the selected vertex as there are no\nvertices in the center of the block.\n\nWithin the scope of this ``Locations`` context, a ``Box`` is created, centered at\nthe intersection of the x and y axis but not in the z thus aligning with the top of the walls.\n\nThe base is closed now as shown here:\n\n.. image:: assets/lego_step10.svg\n :align: center","api_names":"Box BuildPart BuildSketch Circle extrude GridLocations Locations offset part Rectangle sort_by vertical vertices X Y Z","synonyms":"array channel fit gap groove hollow path cut pattern repeat shell tolerance wall thickness"},"369":{"title":"Step 11: Adding Pips","body":"The final step is to add the pips to the top of the Lego block. To do this we'll create\na new workplane on top of the block where we can position the pips.\n\n.. code-block:: build123d\n\n with BuildPart() as lego:\n # Draw the bottom of the block\n with BuildSketch() as plan:\n # Start with a Rectangle the size of the block\n perimeter = Rectangle(width=block_length, height=block_width)\n # Subtract an offset to create the block walls\n offset(\n perimeter,\n -wall_thickness,\n kind=Kind.INTERSECTION,\n mode=Mode.SUBTRACT,\n )\n # Add a grid of lengthwise and widthwise bars\n with GridLocations(x_spacing=0, y_spacing=lego_unit_size, x_count=1, y_count=2):\n Rectangle(width=block_length, height=ridge_width)\n with GridLocations(lego_unit_size, 0, pip_count, 1):\n Rectangle(width=ridge_width, height=block_width)\n # Subtract a rectangle leaving ribs on the block walls\n Rectangle(\n block_length - 2 * (wall_thickness + ridge_depth),\n block_width - 2 * (wall_thickness + ridge_depth),\n mode=Mode.SUBTRACT,\n )\n # Add a row of hollow circles to the center\n with GridLocations(\n x_spacing=lego_unit_size, y_spacing=0, x_count=pip_count - 1, y_count=1\n ):\n Circle(radius=support_outer_diameter / 2)\n Circle(radius=support_inner_diameter / 2, mode=Mode.SUBTRACT)\n # Extrude this base sketch to the height of the walls\n extrude(amount=base_height - wall_thickness)\n # Create a box on the top of the walls\n with Locations((0, 0, lego.vertices().sort_by(Axis.Z)[-1].Z)):\n # Create the top of the block\n Box(\n length=block_length,\n width=block_width,\n height=wall_thickness,\n align=(Align.CENTER, Align.CENTER, Align.MIN),\n )\n # Create a workplane on the top of the block\n with BuildPart(lego.faces().sort_by(Axis.Z)[-1]):\n # Create a grid of pips\n with GridLocations(lego_unit_size, lego_unit_size, pip_count, 2):\n Cylinder(\n radius=pip_diameter / 2,\n height=pip_height,\n align=(Align.CENTER, Align.CENTER, Align.MIN),\n )\n\nIn this case, the workplane is created from the top Face of the Lego block by using the\n``faces`` method and then sorted vertically and taking the top one ``sort_by(Axis.Z)[-1]``.\n\nOn the new workplane, a grid of locations is created and a number of ``Cylinder``'s are positioned\nat each location.\n\n.. image:: assets/lego.svg\n :align: center\n\nThis completes the Lego block. To access the finished product, refer to the builder's internal\nobject as shown here:\n\n+-------------+--------+\n| Builder | Object |\n+=============+========+\n| BuildLine | line |\n+-------------+--------+\n| BuildSketch | sketch |\n+-------------+--------+\n| BuildPart | part |\n+-------------+--------+\n\nso in this case the Lego block is ``lego.part``. To display the part use ``show_object(lego.part)``\nor ``show(lego.part)`` depending on the viewer. The part could also be exported to a STL or STEP\nfile by referencing ``lego.part``.\n\n.. note::\n Viewers that don't directly support build123d my require a raw OpenCascade object. In this\n case, append ``.wrapped`` to the object (e.g.) ``show_object(lego.part.wrapped)``.","api_names":"Box BuildPart BuildSketch Circle Cylinder extrude faces GridLocations Locations object offset part Rectangle show show_object sort_by vertices","synonyms":"array channel fit gap groove hollow path cut pattern repeat shell tolerance wall thickness"},"370":{"title":"Step 2: Part Builder","body":"The Lego block will be created by the ``BuildPart`` builder as it's a discrete three\ndimensional part; therefore, we'll instantiate a ``BuildPart`` with the name ``lego``.\n\n.. code-block:: build123d\n\n with BuildPart() as lego:","api_names":"BuildPart lego","synonyms":""},"371":{"title":"Step 3: Sketch Builder","body":"Lego blocks have quite a bit of internal structure. To create this structure we'll\ndraw a two dimensional sketch that will later be extruded into a three dimensional\nobject. As this sketch will be part of the lego part, we'll create a sketch builder\nin the context of the part builder as follows:\n\n.. code-block:: build123d\n\n with BuildPart() as lego:\n # Draw the bottom of the block\n with BuildSketch() as plan:\n\n\nNote that builder instance names are optional - we'll use ``plan`` to reference the sketch.\nAlso note that all sketch objects are filled or 2D faces not just perimeter lines.","api_names":"BuildPart BuildSketch plan","synonyms":""},"372":{"title":"Step 4: Perimeter Rectangle","body":"The first object in the sketch is going to be a rectangle with the dimensions of the outside\nof the Lego block. The following step is going to refer to this rectangle, so it will\nbe assigned the identifier ``perimeter``.\n\n.. code-block:: build123d\n\n with BuildPart() as lego:\n # Draw the bottom of the block\n with BuildSketch() as plan:\n # Start with a Rectangle the size of the block\n perimeter = Rectangle(width=block_length, height=block_width)\n\nOnce the ``Rectangle`` object is created the sketch appears as follows:\n\n.. image:: assets/lego_step4.svg\n :align: center","api_names":"BuildPart BuildSketch perimeter Rectangle","synonyms":""},"373":{"title":"Step 5: Offset to Create Walls","body":"To create the walls of the block the rectangle that we've created needs to be\nhollowed out. This will be done with the ``Offset`` operation which is going to\ncreate a new object from ``perimeter``.\n\n.. code-block:: build123d\n\n with BuildPart() as lego:\n # Draw the bottom of the block\n with BuildSketch() as plan:\n # Start with a Rectangle the size of the block\n perimeter = Rectangle(width=block_length, height=block_width)\n # Subtract an offset to create the block walls\n offset(\n perimeter,\n -wall_thickness,\n kind=Kind.INTERSECTION,\n mode=Mode.SUBTRACT,\n )\n\nThe first parameter to ``Offset`` is the reference object. The ``amount`` is a\nnegative value to indicate that the offset should be internal. The ``kind``\nparameter controls the shape of the corners - ``Kind.INTERSECTION`` will create\nsquare corners. Finally, the ``mode`` parameter controls how this object will\nbe placed in the sketch - in this case subtracted from the existing sketch.\nThe result is shown here:\n\n.. image:: assets/lego_step5.svg\n :align: center\n\nNow the sketch consists of a hollow rectangle.","api_names":"amount BuildPart BuildSketch INTERSECTION kind mode offset Offset perimeter Rectangle","synonyms":"channel fit gap groove hollow path cut shell tolerance wall thickness"},"374":{"title":"Step 6: Create Internal Grid","body":"The interior of the Lego block has small ridges on all four internal walls.\nThese ridges will be created as a grid of thin rectangles so the positions\nof the centers of these rectangles need to be defined. A pair of\n``GridLocations`` location contexts will define these positions, one for\nthe horizontal bars and one for the vertical bars. As the ``Rectangle``\nobjects are in the scope of a location context (``GridLocations`` in this case)\nthat defined multiple points, multiple rectangles are created.\n\n.. code-block:: build123d\n\n with BuildPart() as lego:\n # Draw the bottom of the block\n with BuildSketch() as plan:\n # Start with a Rectangle the size of the block\n perimeter = Rectangle(width=block_length, height=block_width)\n # Subtract an offset to create the block walls\n offset(\n perimeter,\n -wall_thickness,\n kind=Kind.INTERSECTION,\n mode=Mode.SUBTRACT,\n )\n # Add a grid of lengthwise and widthwise bars\n with GridLocations(x_spacing=0, y_spacing=lego_unit_size, x_count=1, y_count=2):\n Rectangle(width=block_length, height=ridge_width)\n with GridLocations(lego_unit_size, 0, pip_count, 1):\n Rectangle(width=ridge_width, height=block_width)\n\nHere we can see that the first ``GridLocations`` creates two positions which causes\ntwo horizontal rectangles to be created. The second ``GridLocations`` works in the same way\nbut creates ``pip_count`` positions and therefore ``pip_count`` rectangles. Note that keyword\nparameter are optional in this case.\n\nThe result looks like this:\n\n.. image:: assets/lego_step6.svg\n :align: center","api_names":"BuildPart BuildSketch context GridLocations offset pip_count Rectangle","synonyms":"array channel fit gap groove hollow path cut pattern repeat shell tolerance wall thickness"},"375":{"title":"Step 7: Create Ridges","body":"To convert the internal grid to ridges, the center needs to be removed. This will be done\nwith another ``Rectangle``.\n\n.. code-block:: build123d\n\n with BuildPart() as lego:\n # Draw the bottom of the block\n with BuildSketch() as plan:\n # Start with a Rectangle the size of the block\n perimeter = Rectangle(width=block_length, height=block_width)\n # Subtract an offset to create the block walls\n offset(\n perimeter,\n -wall_thickness,\n kind=Kind.INTERSECTION,\n mode=Mode.SUBTRACT,\n )\n # Add a grid of lengthwise and widthwise bars\n with GridLocations(x_spacing=0, y_spacing=lego_unit_size, x_count=1, y_count=2):\n Rectangle(width=block_length, height=ridge_width)\n with GridLocations(lego_unit_size, 0, pip_count, 1):\n Rectangle(width=ridge_width, height=block_width)\n # Subtract a rectangle leaving ribs on the block walls\n Rectangle(\n block_length - 2 * (wall_thickness + ridge_depth),\n block_width - 2 * (wall_thickness + ridge_depth),\n mode=Mode.SUBTRACT,\n )\n\nThe ``Rectangle`` is subtracted from the sketch to leave the ridges as follows:\n\n.. image:: assets/lego_step7.svg\n :align: center","api_names":"BuildPart BuildSketch GridLocations offset Rectangle","synonyms":"array channel fit gap groove hollow path cut pattern repeat shell tolerance wall thickness"},"376":{"title":"Step 8: Hollow Circles","body":"Lego blocks use a set of internal hollow cylinders that the pips push against\nto hold two blocks together. These will be created with ``Circle``.\n\n.. code-block:: build123d\n\n with BuildPart() as lego:\n # Draw the bottom of the block\n with BuildSketch() as plan:\n # Start with a Rectangle the size of the block\n perimeter = Rectangle(width=block_length, height=block_width)\n # Subtract an offset to create the block walls\n offset(\n perimeter,\n -wall_thickness,\n kind=Kind.INTERSECTION,\n mode=Mode.SUBTRACT,\n )\n # Add a grid of lengthwise and widthwise bars\n with GridLocations(x_spacing=0, y_spacing=lego_unit_size, x_count=1, y_count=2):\n Rectangle(width=block_length, height=ridge_width)\n with GridLocations(lego_unit_size, 0, pip_count, 1):\n Rectangle(width=ridge_width, height=block_width)\n # Subtract a rectangle leaving ribs on the block walls\n Rectangle(\n block_length - 2 * (wall_thickness + ridge_depth),\n block_width - 2 * (wall_thickness + ridge_depth),\n mode=Mode.SUBTRACT,\n )\n # Add a row of hollow circles to the center\n with GridLocations(\n x_spacing=lego_unit_size, y_spacing=0, x_count=pip_count - 1, y_count=1\n ):\n Circle(radius=support_outer_diameter / 2)\n Circle(radius=support_inner_diameter / 2, mode=Mode.SUBTRACT)\n\nHere another ``GridLocations`` is used to position the centers of the circles. Note\nthat since both ``Circle`` objects are in the scope of the location context, both\nCircles will be positioned at these locations.\n\nOnce the Circles are added, the sketch is complete and looks as follows:\n\n.. image:: assets/lego_step8.svg\n :align: center","api_names":"BuildPart BuildSketch Circle GridLocations offset Rectangle","synonyms":"array channel fit gap groove hollow path cut pattern repeat shell tolerance wall thickness"},"377":{"title":"Step 9: Extruding Sketch into Walls","body":"Now that the sketch is complete it needs to be extruded into the three dimensional\nwall object.\n\n.. code-block:: build123d\n\n with BuildPart() as lego:\n # Draw the bottom of the block\n with BuildSketch() as plan:\n # Start with a Rectangle the size of the block\n perimeter = Rectangle(width=block_length, height=block_width)\n # Subtract an offset to create the block walls\n offset(\n perimeter,\n -wall_thickness,\n kind=Kind.INTERSECTION,\n mode=Mode.SUBTRACT,\n )\n # Add a grid of lengthwise and widthwise bars\n with GridLocations(x_spacing=0, y_spacing=lego_unit_size, x_count=1, y_count=2):\n Rectangle(width=block_length, height=ridge_width)\n with GridLocations(lego_unit_size, 0, pip_count, 1):\n Rectangle(width=ridge_width, height=block_width)\n # Subtract a rectangle leaving ribs on the block walls\n Rectangle(\n block_length - 2 * (wall_thickness + ridge_depth),\n block_width - 2 * (wall_thickness + ridge_depth),\n mode=Mode.SUBTRACT,\n )\n # Add a row of hollow circles to the center\n with GridLocations(\n x_spacing=lego_unit_size, y_spacing=0, x_count=pip_count - 1, y_count=1\n ):\n Circle(radius=support_outer_diameter / 2)\n Circle(radius=support_inner_diameter / 2, mode=Mode.SUBTRACT)\n # Extrude this base sketch to the height of the walls\n extrude(amount=base_height - wall_thickness)\n\nNote how the ``Extrude`` operation is no longer in the ``BuildSketch`` scope and has returned\nback into the ``BuildPart`` scope. This causes ``BuildSketch`` to exit and transfer the\nsketch that we've created to ``BuildPart`` for further processing by ``Extrude``.\n\nThe result is:\n\n.. image:: assets/lego_step9.svg\n :align: center","api_names":"BuildPart BuildSketch Circle extrude Extrude GridLocations offset Rectangle","synonyms":"array channel fit gap groove hollow path cut pattern repeat shell tolerance wall thickness"},"378":{"title":"Conclusion","body":"By using selectors as we have in this example we've used methods\nof identifying features that are robust to features changing within\nthe part. We've also avoided the classic CAD \"Topological naming problem\"\nby never referring to features with names or tags that could become obsolete\nas the part changes.\n\nWhen possible, avoid using static list indices to refer to features\nextracted from methods like ``edges()`` as the order within the list\nis not guaranteed to remain the same.","api_names":"edges","synonyms":""},"379":{"title":"Selector Tutorial","body":"This tutorial provides a step by step guide in using selectors as we create\nthis part:\n\n.. image:: assets/selector_after.svg\n :align: center\n\n.. note::\n One can see any object in the following tutorial by using the ``ocp_vscode`` (or\n any other supported viewer) by using the ``show(object_to_be_viewed)`` command.\n Alternatively, the ``show_all()`` command will display all objects that have been\n assigned an identifier.","api_names":"ocp_vscode show show_all","synonyms":""},"380":{"title":"Step 1: Setup","body":"Before getting to the CAD operations, this selector script needs to import the build123d\nenvironment.\n\n.. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import *","api_names":"","synonyms":""},"381":{"title":"Step 2: Create Base with BuildPart","body":"To start off, the part will be based on a cylinder so we'll use the :class:`~objects_part.Cylinder` object\nof :class:`~build_part.BuildPart`:\n\n.. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import *\n \n with BuildPart() as example:\n Cylinder(radius=10, height=3)","api_names":"BuildPart Cylinder","synonyms":""},"382":{"title":"Step 3: Place Sketch on top of base","body":"The next set of features in this design will be created on the top of the cylinder\nand be described by a planar sketch (:class:`~build_sketch.BuildSketch` is the tool for drawing on planar\nsurfaces) , so we'll create a sketch centered on the top of the cylinder. To locate\nthis sketch we'll use the cylinder's top Face as shown here:\n\n.. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import *\n \n with BuildPart() as example:\n Cylinder(radius=10, height=3)\n with BuildSketch(example.faces().sort_by(Axis.Z)[-1]):\n\nHere we're using selectors to find that top Face - let's break down\n``example.faces().sort_by(Axis.Z)[-1]``:","api_names":"BuildPart BuildSketch Cylinder faces sketch sort_by","synonyms":""},"383":{"title":"Step 3a: Extract Faces from a part","body":"The first sub-step is the extraction of all of the Faces from the part that we're\nbuilding. The :class:`~build_part.BuildPart` instance was assigned the identifier ``example`` so\n``example.faces()`` will extract all of the Faces from that part into a custom\npython ``list`` - a :class:`~topology.ShapeList`.","api_names":"BuildPart example faces ShapeList","synonyms":""},"384":{"title":"Step 3b: Get top Face","body":"The next sub-step is to sort the ShapeList of Faces by their position with\nrespect to the Z Axis. The ``sort_by`` method will sort the list by relative position\nof the object's center to the ``Axis.Z`` and ``[-1]``\nselects the last item on that list - or return the top Face of the ``example`` part.","api_names":"example sort_by Z","synonyms":""},"385":{"title":"Step 4: Create hole shape","body":"The object has a hexagonal hole in the top with a central cylinder which we'll describe\nin the sketch.\n\n.. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import *\n \n with BuildPart() as example:\n Cylinder(radius=10, height=3)\n with BuildSketch(example.faces().sort_by(Axis.Z)[-1]):\n RegularPolygon(radius=7, side_count=6)\n Circle(radius=4, mode=Mode.SUBTRACT)","api_names":"BuildPart BuildSketch Circle Cylinder faces RegularPolygon sort_by","synonyms":"bore channel drill groove path cut recessed fastener"},"386":{"title":"Step 4a: Draw a hexagon","body":"We'll create a hexagon with the use of :class:`~objects_sketch.RegularPolygon` object with six sides.","api_names":"RegularPolygon","synonyms":""},"387":{"title":"Step 4b: Create a hole in the hexagon","body":"To create the hole we'll subtract a :class:`~objects_sketch.Circle` from the sketch by using\n``mode=Mode.SUBTRACT``. The sketch now described the hexagonal hole that we\nwant to make in the :class:`~objects_part.Cylinder`.","api_names":"Circle Cylinder mode","synonyms":"bore channel drill groove path cut recessed fastener"},"388":{"title":"Step 5: Create the hole","body":"To create the hole we'll :func:`~operations_part.extrude` the sketch we just created into\nthe :class:`~objects_part.Cylinder` and subtract it.\n\n.. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import *\n \n with BuildPart() as example:\n Cylinder(radius=10, height=3)\n with BuildSketch(example.faces().sort_by(Axis.Z)[-1]):\n RegularPolygon(radius=7, side_count=6)\n Circle(radius=4, mode=Mode.SUBTRACT)\n extrude(amount=-2, mode=Mode.SUBTRACT)\n\nNote that ``amount=-2`` indicates extruding into the part and - just like\nwith the sketch - ``mode=Mode.SUBTRACT`` instructs the builder to subtract\nthis hexagonal shape from the part under construction.\n\nAt this point the part looks like:\n\n.. image:: assets/selector_before.svg\n :align: center","api_names":"amount BuildPart BuildSketch Circle Cylinder extrude faces mode RegularPolygon sort_by","synonyms":"bore channel drill groove path cut recessed fastener"},"389":{"title":"Step 6: Fillet the top perimeter Edge","body":"The final step is to apply a fillet to the top perimeter.\n\n.. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import *\n \n with BuildPart() as example:\n Cylinder(radius=10, height=3)\n with BuildSketch(example.faces().sort_by(Axis.Z)[-1]):\n RegularPolygon(radius=7, side_count=6)\n Circle(radius=4, mode=Mode.SUBTRACT)\n extrude(amount=-2, mode=Mode.SUBTRACT)\n fillet(\n example.edges()\n .filter_by(GeomType.CIRCLE)\n .sort_by(SortBy.RADIUS)[-2:]\n .sort_by(Axis.Z)[-1],\n radius=1,\n )\n \n show(example)\n\nHere we're using the :func:`~operations_generic.fillet` operation which needs two things:\nthe edge(s) to fillet and the radius of the fillet. To provide\nthe edge, we'll use more selectors as described in the following\nsub-steps.","api_names":"BuildPart BuildSketch Circle Cylinder edge edges extrude faces fillet filter_by RegularPolygon show sort_by","synonyms":"bevel edge channel groove path cut round edge"},"390":{"title":"Step 6a: Extract all the Edges","body":"Much like selecting Faces in Step 3a, we'll select all of the ``example``\npart's edges with ``example.edges()``.","api_names":"edges example","synonyms":""},"391":{"title":"Step 6b: Filter the Edges for circles","body":"Since we know that the edge we're looking for is a circle, we can\nfilter the edges selected in Step 6a for just those that are of\ngeometric type ``CIRCLE`` with ``example.edges().filter_by(GeomType.CIRCLE)``.\nThis step removes all of the Edges of the hexagon hole.","api_names":"CIRCLE edges filter_by","synonyms":"bore drill recessed fastener"},"392":{"title":"Step 6c: Sort the circles by radius","body":"The perimeter are the largest circles - the central cylinder must be\nexcluded - so we'll sort all of the circles by their radius with:\n``example.edges().filter_by(GeomType.CIRCLE).sort_by(SortBy.RADIUS)``.","api_names":"edges filter_by sort_by","synonyms":""},"393":{"title":"Step 6d: Slice the list to get the two largest","body":"We know that the ``example`` part has two perimeter circles so we'll\nselect just the top two edges from the sorted circle list with:\n``example.edges().filter_by(GeomType.CIRCLE).sort_by(SortBy.RADIUS)[-2:]``. The\nsyntax of this slicing operation is standard python list slicing.","api_names":"edges example filter_by sort_by","synonyms":""},"394":{"title":"Step 6e: Select the top Edge","body":"The last sub-step is to select the top perimeter edge, the one with\nthe greatest Z value which we'll do with the ``sort_by(Axis.Z)[-1]`` method just like\nStep 3b - note that these methods work on all Shape objects (Edges, Wires,\nFaces, Solids, and Compounds) - with:\n``example.edges().filter_by(GeomType.CIRCLE).sort_by(SortBy.RADIUS)[-2:].sort_by(Axis.Z)[-1]``.","api_names":"edges filter_by objects sort_by","synonyms":""},"395":{"title":"Complete listing","body":"For convenience, here is the full script in one block:\n\n.. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n wing_span = 36 * FT + 10 * IN\n wing_leading = 2.5 * FT\n wing_trailing = wing_span / 4 - wing_leading\n wing_leading_fraction = wing_leading / (wing_leading + wing_trailing)\n wing_tip_section = wing_span / 2 - 1 * IN # distance from root to last section\n \n # Create leading and trailing edges\n leading_edge = EllipticalCenterArc(\n (0, 0), wing_span / 2, wing_leading, start_angle=270, end_angle=360\n )\n trailing_edge = EllipticalCenterArc(\n (0, 0), wing_span / 2, wing_trailing, start_angle=0, end_angle=90\n )\n \n # [AirfoilSizes]\n # Calculate the airfoil sizes from the leading/trailing edges\n airfoil_sizes = []\n for i in [0, 1]:\n tip_axis = Axis(i * (wing_tip_section, 0, 0), (0, 1, 0))\n leading_pnt = leading_edge.intersect(tip_axis)[0]\n trailing_pnt = trailing_edge.intersect(tip_axis)[0]\n airfoil_sizes.append(trailing_pnt.Y - leading_pnt.Y)\n \n # [Airfoils]\n # Create the root and tip airfoils - note that they are different NACA profiles\n airfoil_root = Plane.YZ * scale(\n Airfoil(\"2213\").translate((-wing_leading_fraction, 0, 0)), airfoil_sizes[0]\n )\n airfoil_tip = (\n Plane.YZ\n * Pos(Z=wing_tip_section)\n * scale(Airfoil(\"2205\").translate((-wing_leading_fraction, 0, 0)), airfoil_sizes[1])\n )\n \n # [Profiles]\n # Create the Gordon surface profiles and guides\n profiles = airfoil_root.edges() + airfoil_tip.edges()\n profiles.append(leading_edge @ 1) # wing tip\n guides = [leading_edge, trailing_edge]\n # Create the wing surface as a Gordon Surface\n wing_surface = -Face.make_gordon_surface(profiles, guides)\n # Create the root of the wing\n wing_root = -Face(Wire(wing_surface.edges().filter_by(Edge.is_closed)))\n \n # [Solid]\n # Create the wing Solid\n wing = Solid(Shell([wing_surface, wing_root]))\n wing.color = 0x99A3B9 # Azure Blue\n \n show(wing)","api_names":"Airfoil append Axis edges EllipticalCenterArc Face filter_by intersect make_gordon_surface Pos scale Shell show Solid translate Wire","synonyms":""},"396":{"title":"Overview","body":"We will:\n\n1. Define overall wing dimensions and elliptic leading/trailing edge guide curves\n2. Sample the guides to size the root and tip airfoils (different NACA profiles)\n3. Build the Gordon surface from the airfoil *profiles* and wing‑edge *guides*\n4. Close the root with a planar face and build the final :class:`~topology.Solid`\n\n.. raw:: html\n\n \n ","api_names":"airfoils Solid","synonyms":""},"397":{"title":"Step 1 - Dimensions and guide curves","body":"We model a single wing (half‑span), with an elliptic leading and trailing edge.\nThese two edges act as the *guides* for the Gordon surface.\n\n.. code-block:: build123d\n\n \n from build123d import *\n from ocp_vscode import show\n \n wing_span = 36 * FT + 10 * IN\n wing_leading = 2.5 * FT\n wing_trailing = wing_span / 4 - wing_leading\n wing_leading_fraction = wing_leading / (wing_leading + wing_trailing)\n wing_tip_section = wing_span / 2 - 1 * IN # distance from root to last section\n \n # Create leading and trailing edges\n leading_edge = EllipticalCenterArc(\n (0, 0), wing_span / 2, wing_leading, start_angle=270, end_angle=360\n )\n trailing_edge = EllipticalCenterArc(\n (0, 0), wing_span / 2, wing_trailing, start_angle=0, end_angle=90\n )","api_names":"EllipticalCenterArc wing","synonyms":""},"398":{"title":"Step 2 - Root and tip airfoil sizing","body":"We intersect the guides with planes normal to the span to size the airfoil sections.\nThe resulting chord lengths define uniform scales for each airfoil curve.\n\n.. code-block:: build123d\n\n # Calculate the airfoil sizes from the leading/trailing edges\n airfoil_sizes = []\n for i in [0, 1]:\n tip_axis = Axis(i * (wing_tip_section, 0, 0), (0, 1, 0))\n leading_pnt = leading_edge.intersect(tip_axis)[0]\n trailing_pnt = trailing_edge.intersect(tip_axis)[0]\n airfoil_sizes.append(trailing_pnt.Y - leading_pnt.Y)","api_names":"append Axis intersect","synonyms":""},"399":{"title":"Step 3 - Build airfoil profiles (root and tip)","body":"We place two different NACA airfoils on :data:`Plane.YZ`-with the airfoil origins\nshifted so the leading edge fraction is aligned-then scale to the chord lengths\nfrom Step 2.\n\n.. code-block:: build123d\n\n # Create the root and tip airfoils - note that they are different NACA profiles\n airfoil_root = Plane.YZ * scale(\n Airfoil(\"2213\").translate((-wing_leading_fraction, 0, 0)), airfoil_sizes[0]\n )\n airfoil_tip = (\n Plane.YZ\n * Pos(Z=wing_tip_section)\n * scale(Airfoil(\"2205\").translate((-wing_leading_fraction, 0, 0)), airfoil_sizes[1])\n )","api_names":"Airfoil Pos profiles scale translate YZ","synonyms":""},"400":{"title":"Step 4 - Gordon surface construction","body":"A Gordon surface needs *profiles* and *guides*. Here the airfoil edges are the\nprofiles; the elliptic edges are the guides. We also add the wing tip section\nso the profile grid closes at the tip.\n\n.. code-block:: build123d\n\n # Create the Gordon surface profiles and guides\n profiles = airfoil_root.edges() + airfoil_tip.edges()\n profiles.append(leading_edge @ 1) # wing tip\n guides = [leading_edge, trailing_edge]\n # Create the wing surface as a Gordon Surface\n wing_surface = -Face.make_gordon_surface(profiles, guides)\n # Create the root of the wing\n wing_root = -Face(Wire(wing_surface.edges().filter_by(Edge.is_closed)))\n \n\n.. image:: ./assets/surface_modeling/spitfire_wing_profiles_guides.svg\n :align: center\n :alt: Elliptic leading/trailing guides","api_names":"append edges Face filter_by make_gordon_surface Wire","synonyms":""},"401":{"title":"Step 5 - Cap the root and create the solid","body":"We extract the closed root edge loop, make a planar cap, and form a solid shell.\n\n.. code-block:: build123d\n\n # Create the wing Solid\n wing = Solid(Shell([wing_surface, wing_root]))\n wing.color = 0x99A3B9 # Azure Blue\n \n show(wing)\n\n.. image:: ./assets/surface_modeling/spitfire_wing.png\n :align: center\n :alt: Final wing solid","api_names":"Shell show Solid","synonyms":""},"402":{"title":"Tips for robust Gordon surfaces","body":"- Ensure each profile intersects each guide once and only once\n- Keep the curve network coherent (no duplicated or missing intersections)\n- When possible, reuse the same :class:`~topology.Edge` objects across adjacent faces","api_names":"coherent Edge","synonyms":""},"403":{"title":"Tutorial: Spitfire Wing with Gordon Surface","body":"In this advanced tutorial we construct a Supermarine Spitfire wing as a\n:meth:`~topology.Face.make_gordon_surface`-a powerful technique for surfacing\nfrom intersecting *profiles* and *guides*. A Gordon surface blends a grid of\ncurves into a smooth, coherent surface as long as the profiles and guides\nintersect consistently.\n\n.. note::\n Gordon surfaces work best when *each profile intersects each guide exactly\n once*, producing a well‑formed curve network.","api_names":"make_gordon_surface","synonyms":""},"404":{"title":"1. Examine the primitives visually","body":"Look at the returned ``primitives`` and decide what the detector found well.\n\nUseful questions include:\n\n* Are the expected planar faces present?\n* Do fillets appear as cylinders?\n* Do rounded corners appear as spheres?\n* Are repeated features recognized consistently?\n\nIn a simple mechanical part, good output often consists of a small number of\ncommon planes, repeated cylinders with similar radii, and only a few leftovers.","api_names":"primitives","synonyms":"bevel edge round edge"},"405":{"title":"2. Examine the leftovers","body":"``leftovers`` show what still needs manual interpretation.\n\nLarge leftover regions often indicate one of three things:\n\n* the part contains geometry that is not well approximated by planes,\n cylinders, or spheres\n* the mesh is noisy or irregular\n* the working section is still too large to interpret comfortably\n\nIf too much of the mesh appears in ``leftovers``, it may be better to refine\nthe working section, identify more symmetry, or redesign that area manually\ninstead of trying to automate it further.","api_names":"leftovers","synonyms":""},"406":{"title":"3. Examine the generated code","body":"The generated ``code_lines`` are intentionally written in Algebra mode and use\n``Plane * Pos`` structure to make repeated placement patterns easier to spot.\n\nThis often helps answer questions such as:\n\n* which faces lie on the same construction plane?\n* which circles belong to the same sketch?\n* which cylindrical or spherical regions are repeated instances of one feature?\n\nTreat this code as an annotated report, not necessarily as the final model.\n\nFor planar parts in particular, the generated lines are often naturally grouped\nby plane. A sequence such as ``Plane.XY.offset(...)`` with a few repeated\noffset values usually indicates related structure that may belong to one sketch\nor one construction stage.","api_names":"code_lines offset Plane","synonyms":"fit gap hollow shell tolerance wall thickness"},"407":{"title":"Inspecting the Results","body":"The inspection step is the heart of this workflow.","api_names":"","synonyms":""},"408":{"title":"Overview","body":"The workflow described here is:\n\n1. Import the STL with :class:`~mesher.Mesher`.\n2. Split the mesh by symmetry planes and isolate the region to redesign.\n3. Save that reduced mesh section as a BREP file.\n4. Reload the BREP section while iterating on reconstruction.\n5. Run :func:`~build123d.detect_primitives`.\n6. Inspect the returned primitives, leftovers, and generated code.\n7. Rebuild the design intentionally from those clues.\n\nThe key output of ``detect_primitives`` is guidance:\n\n* ``primitives`` shows what was recognized analytically\n* ``leftovers`` shows what was not covered\n* ``code_lines`` provides algebra-mode fragments that often reveal common\n planes and likely sketch structure","api_names":"code_lines detect_primitives leftovers Mesher primitives","synonyms":"cut in half slice trim"},"409":{"title":"Preparing the Mesh","body":"Start with the STL import and isolate the smallest useful section of the part.\n\n.. code-block:: build123d\n\n from build123d import *\n\n importer = Mesher()\n full_mesh = importer.read(\"target_part.stl\")[0]\n\n # Example: reduce the work to one quarter of a symmetric model\n quarter_mesh = split(full_mesh, Plane.YZ)\n quarter_mesh = split(quarter_mesh, Plane.XZ)\n\n export_brep(quarter_mesh, \"target_part_quarter.brep\")\n\nThe exact planes depend on the part. The point is not to begin running\n``detect_primitives`` on the full mesh if symmetry can remove most of the work.","api_names":"detect_primitives export_brep Mesher read split","synonyms":"cut in half slice trim"},"410":{"title":"Reconstruction Script","body":"Once the mesh section has been cached as BREP, iterate on a separate script or\nenable a reconstruction section of the same script with a Boolean switch.\n\n.. code-block:: build123d\n\n from build123d import *\n\n working_mesh = import_brep(\"target_part_quarter.brep\")\n\n primitives, leftovers, code_lines = detect_primitives(working_mesh)\n\n print(*code_lines, sep=\"\\n\")\n\nThis call returns three complementary outputs:\n\n``primitives``\n A :class:`~topology.ShapeList` of analytic faces that were recognized from\n the mesh. These are typically planes, cylinders, and spheres. Planar\n primitives are returned as rectangles sized to the planar region's\n bounding box, not as the original tessellated mesh patch.\n\n``leftovers``\n Mesh faces that were not matched by the primitive detectors. These indicate\n freeform regions, noisy regions, or places where manual work is still\n required.\n\n``code_lines``\n Generated algebra-mode code corresponding to the recognized primitives.","api_names":"code_lines detect_primitives import_brep leftovers primitives ShapeList","synonyms":""},"411":{"title":"Signs of Good Output","body":"``detect_primitives`` is most helpful when:\n\n* the mesh is reasonably clean\n* the part is mostly mechanical\n* many surfaces are planar, cylindrical, or spherical\n* there are clear planes of symmetry or repeated features\n\nIn these cases, primitives and generated code often cluster into obvious\nreconstruction steps.","api_names":"detect_primitives","synonyms":""},"412":{"title":"Signs of Poor Output","body":"Expect more manual work when:\n\n* the mesh contains freeform surfaces\n* the STL is noisy or heavily tessellated\n* the part has no obvious symmetry\n* many important regions remain in ``leftovers``\n* the generated code contains many tiny or redundant fragments\n\nWhen this happens, it may be faster to use the mesh only as a visual reference\nand rebuild the part manually from dimensions and intent.","api_names":"leftovers","synonyms":""},"413":{"title":"Summary","body":"The STL reconstruction workflow in build123d is:\n\n1. analyze the part as a designer, not as a mesh processor\n2. isolate the smallest useful region with symmetry and splitting\n3. cache that region as BREP\n4. run :func:`~build123d.detect_primitives`\n5. inspect primitives, leftovers, and code\n6. rebuild the part intentionally in build123d\n\nThe most useful mindset is to treat ``detect_primitives`` as a design assistant.\nIt can show where the planes, cylinders, and spheres probably are, but the\nfinal parametric model still comes from careful human interpretation.","api_names":"detect_primitives","synonyms":"cut in half slice trim"},"414":{"title":"Turning Primitive Hints into Sketches","body":"Once repeated planes become obvious in ``code_lines``, start grouping related\nfeatures into sketches and features of your own.\n\nFor example:\n\n* several rectangles on ``Plane.XY`` may indicate one base sketch and one or\n more extrusions\n* repeated circles on one plane may indicate hole or boss locations\n* a collection of cylinders with the same radius may indicate that a fillet or\n round was part of the original design intent\n\nThe generated code is often most useful when treated as:\n\n* a list of candidate construction planes\n* a list of likely sketch elements\n* a list of repeated primitive sizes and placements","api_names":"code_lines XY","synonyms":"array bevel edge bore drill pattern recessed fastener repeat round edge"},"415":{"title":"Tutorial: Reconstructing a Design from an STL","body":"This tutorial describes a practical workflow for using\n:func:`~build123d.detect_primitives` to help reconstruct a parametric build123d\nmodel from an STL mesh.\n\nThis is not a push-button STL-to-CAD converter. It is a mesh-guided redesign\nprocess. The goal is to extract enough analytic structure from a triangulated\nmodel to make manual reconstruction faster and more reliable.\n\n.. warning::\n\n Rebuilding a design from STL is usually slow, approximate, and manual.\n STL files contain triangles, not modeling intent. Even when\n :func:`~build123d.detect_primitives` finds useful planes, cylinders, and\n spheres, the final build123d model still needs to be designed deliberately.\n\nBefore working through this tutorial, review Steps 1-3 of\n:ref:`design_tutorial`. The same ideas apply here:\n\n* identify planes of symmetry\n* identify likely axes of rotation\n* choose a convenient origin before doing any serious work\n\nThese preparation steps often reduce the amount of mesh that needs to be\nreconstructed to one half, one quarter, or even less.","api_names":"detect_primitives","synonyms":""},"416":{"title":"Why Cache a Working Section as BREP?","body":"Importing STL with :class:`~mesher.Mesher` is convenient, but large meshes can be\nslow to load and process. Once a useful section of the part has been isolated,\nsave it as a BREP file and use that for repeated experimentation.\n\nBREP files reload much more efficiently in build123d and are better suited to\nan iterative reconstruction script.","api_names":"Mesher","synonyms":""},"417":{"title":"Worked Example: Filleted Box","body":"As a controlled example, consider a filleted box:\n\n.. code-block:: build123d\n\n fillet_box = fillet(Box(1, 1, 1).edges(), 0.1)\n\nRunning ``detect_primitives`` on this geometry produces output like:\n\n.. code-block:: build123d\n\n r00 = Plane.XY.offset(-0.5) * Pos(-0.4, -0.4) * Rectangle(0.8, 0.8, align=Align.MIN)\n c01 = Plane.XY.offset(-0.4) * Pos(0.4, 0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n c02 = Plane.XY.offset(-0.4) * Pos(-0.4, 0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n c03 = Plane.XY.offset(-0.4) * Pos(-0.4, -0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n c04 = Plane.XY.offset(-0.4) * Pos(0.4, -0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n r05 = Plane.XY.offset(0.5) * Pos(-0.4, -0.4) * Rectangle(0.8, 0.8, align=Align.MIN)\n r06 = Plane.YZ.offset(-0.5) * Pos(-0.4, -0.4) * Rectangle(0.8, 0.8, align=Align.MIN)\n c07 = Plane.YZ.offset(-0.4) * Pos(-0.4, -0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n c08 = Plane.YZ.offset(-0.4) * Pos(-0.4, 0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n c09 = Plane.YZ.offset(-0.4) * Pos(0.4, -0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n c10 = Plane.YZ.offset(-0.4) * Pos(0.4, 0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n r11 = Plane.YZ.offset(0.5) * Pos(-0.4, -0.4) * Rectangle(0.8, 0.8, align=Align.MIN)\n r12 = Plane.ZX.offset(-0.5) * Pos(-0.4, -0.4) * Rectangle(0.8, 0.8, align=Align.MIN)\n c13 = Plane.ZX.offset(-0.4) * Pos(-0.4, 0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n c14 = Plane.ZX.offset(-0.4) * Pos(-0.4, -0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n c15 = Plane.ZX.offset(-0.4) * Pos(0.4, -0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n c16 = Plane.ZX.offset(-0.4) * Pos(0.4, 0.4) * Face.extrude(Circle(0.0999996).edge(), (0, 0, 0.8))\n r17 = Plane.ZX.offset(0.5) * Pos(-0.4, -0.4) * Rectangle(0.8, 0.8, align=Align.MIN)\n s18 = Pos((0.399999, -0.399999, 0.400026)) * Sphere(0.099983).faces().filter_by(GeomType.SPHERE)[0]\n s19 = Pos((-0.399999, 0.399999, -0.400026)) * Sphere(0.099983).faces().filter_by(GeomType.SPHERE)[0]\n s20 = Pos((-0.399999, -0.399999, -0.400026)) * Sphere(0.099983).faces().filter_by(GeomType.SPHERE)[0]\n s21 = Pos((0.399999, 0.399999, -0.400026)) * Sphere(0.099983).faces().filter_by(GeomType.SPHERE)[0]\n s22 = Pos((-0.399999, 0.400026, 0.399999)) * Sphere(0.099983).faces().filter_by(GeomType.SPHERE)[0]\n s23 = Pos((-0.399999, -0.399999, 0.400026)) * Sphere(0.099983).faces().filter_by(GeomType.SPHERE)[0]\n s24 = Pos((0.399999, 0.400026, 0.399999)) * Sphere(0.099983).faces().filter_by(GeomType.SPHERE)[0]\n s25 = Pos((0.399999, -0.399999, -0.400026)) * Sphere(0.099983).faces().filter_by(GeomType.SPHERE)[0]\n\nThis output is informative in several ways:\n\n* the six box faces appear as rectangles on three principal planes\n* the edge fillets appear as cylinders grouped around those same planes\n* the corner blends appear as spheres near the eight cube corners\n\nThe generated code is also structured by plane:\n\n* ``Plane.XY.offset(...)`` appears with three distinct offsets\n* ``Plane.YZ.offset(...)`` appears with three distinct offsets\n* ``Plane.ZX.offset(...)`` appears with three distinct offsets\n\nThat organization is often more useful than any one primitive by itself\nbecause it suggests how the model could be regrouped into sketches and\nconstruction steps.\n\nAlthough this output is correct and useful, it still does not represent the\nbest final build123d model. The original design intent is much simpler:\n\n.. code-block:: build123d\n\n fillet(Box(1, 1, 1).edges(), 0.1)\n\nThat is a good example of the main lesson of this tutorial: the generated code\nhelps reveal structure, but the final model should usually be rewritten in a\ncleaner, higher-level form.","api_names":"Box Circle detect_primitives edge edges extrude faces fillet filter_by offset Pos Rectangle Sphere","synonyms":"bevel edge fit gap hollow round edge shell tolerance wall thickness"},"418":{"title":"Next steps","body":"Continue to :doc:`tutorial_spitfire_wing_gordon` for an advanced example using\n:meth:`~topology.Face.make_gordon_surface` to create a Supermarine Spitfire wing.","api_names":"make_gordon_surface","synonyms":""},"419":{"title":"Summary","body":"In this tutorial, we've explored surface modeling techniques to create a non-planar\nheart-shaped object using build123d. By utilizing methods from the :class:`~topology.Face`\nclass, such as :meth:`~topology.Face.make_surface`, we constructed the perimeter and\ncentral point of the surface. We then assembled the complete boundary of the object\nby creating the top, bottom, and sides, and combined them into a :class:`~topology.Shell`\nand eventually a :class:`~topology.Solid`. Finally, we added a frame around the heart\nusing the :func:`~operations_generic.offset` function to maintain a constant distance\nfrom the heart.","api_names":"Face make_surface offset Shell Solid","synonyms":"fit gap hollow shell tolerance wall thickness"},"420":{"title":"Tutorial: Heart Token (Basics)","body":"This hands‑on tutorial introduces the fundamentals of surface modeling by building\na heart‑shaped token from a small set of non‑planar faces. We’ll create\nnon‑planar surfaces, mirror them, add side faces, and assemble a closed shell\ninto a solid.\n\nAs described in the `topology_` section, a BREP model consists of vertices, edges, faces,\nand other elements that define the boundary of an object. When creating objects with\nnon-planar faces, it is often more convenient to explicitly create the boundary faces of\nthe object. To illustrate this process, we will create the following game token:\n\n.. raw:: html\n\n \n \n\nUseful :class:`~topology.Face` creation methods include\n:meth:`~topology.Face.make_surface`, :meth:`~topology.Face.make_bezier_surface`,\nand :meth:`~topology.Face.make_surface_from_array_of_points`. See the\n:doc:`tutorial_surface_modeling` overview for the full list.\n\nIn this case, we'll use the ``make_surface`` method, providing it with the edges that define\nthe perimeter of the surface and a central point on that surface.\n\nTo create the perimeter, we'll define the perimeter edges. Since the heart is\nsymmetric, we'll only create half of its surface here:\n\n.. code-block:: build123d\n\n from build123d import *\n from ocp_vscode import show\n \n # Create the edges of one half the heart surface\n l1 = JernArc((0, 0), (1, 1.4), 40, -17)\n l2 = JernArc(l1 @ 1, l1 % 1, 4.5, 175)\n l3 = IntersectingLine(l2 @ 1, l2 % 1, other=Edge.make_line((0, 0), (0, 20)))\n l4 = ThreePointArc(l3 @ 1, (0, 0, 1.5) + (l3 @ 1 + l1 @ 0) / 2, l1 @ 0)\n heart_half = Wire([l1, l2, l3, l4])\n\nNote that ``l4`` is not in the same plane as the other lines; it defines the center line\nof the heart and archs up off ``Plane.XY``.\n\n.. image:: ./assets/surface_modeling/token_heart_perimeter.png\n :align: center\n :alt: token perimeter\n\nIn preparation for creating the surface, we'll define a point on the surface:\n\n.. code-block:: build123d\n\n \n # Create a point elevated off the center\n surface_pnt = l2.arc_center + (0, 0, 1.5)\n\nWe will then use this point to create a non-planar ``Face``:\n\n.. code-block:: build123d\n\n \n # Create the surface from the edges and point\n top_right_surface = Pos(Z=0.5) * -Face.make_surface(heart_half, [surface_pnt])\n\n.. image:: ./assets/surface_modeling/token_half_surface.png\n :align: center\n :alt: token perimeter\n\nNote that the surface was raised up by 0.5 using an Algebra expression with Pos. Also,\nnote that the ``-`` in front of ``Face`` simply flips the face normal so that the colored\nside is up, which isn't necessary but helps with viewing.\n\nNow that one half of the top of the heart has been created, the remainder of the top\nand bottom can be created by mirroring:\n\n.. code-block:: build123d\n\n \n # Use the mirror method to create the other top and bottom surfaces\n top_left_surface = top_right_surface.mirror(Plane.YZ)\n bottom_right_surface = top_right_surface.mirror(Plane.XY)\n bottom_left_surface = -top_left_surface.mirror(Plane.XY)\n\nThe sides of the heart are going to be created by extruding the outside of the perimeter\nas follows:\n\n.. code-block:: build123d\n\n \n # Create the left and right sides\n left_wire = Wire([l3, l2, l1])\n left_side = Pos(Z=-0.5) * Shell.extrude(left_wire, (0, 0, 1))\n right_side = left_side.mirror(Plane.YZ)\n\n.. image:: ./assets/surface_modeling/token_sides.png\n :align: center\n :alt: token sides\n\nWith the top, bottom, and sides, the complete boundary of the object is defined. We can\nnow put them together, first into a :class:`~topology.Shell` and then into a\n:class:`~topology.Solid`:\n\n.. code-block:: build123d\n\n \n # Put all of the faces together into a Shell/Solid\n heart = Solid(\n Shell(\n [\n top_right_surface,\n top_left_surface,\n bottom_right_surface,\n bottom_left_surface,\n left_side,\n right_side,\n ]\n )\n )\n\n.. image:: ./assets/surface_modeling/token_heart_solid.png\n :align: center\n :alt: token heart solid\n\n.. note::\n When creating a Solid from a Shell, the Shell must be \"water-tight,\" meaning it\n should have no holes. For objects with complex Edges, it's best practice to reuse\n Edges in adjoining Faces whenever possible to avoid slight mismatches that can\n create openings.\n\nFinally, we'll create the frame around the heart as a simple extrusion of a planar\nshape defined by the perimeter of the heart and merge all of the components together:\n\n.. code-block:: build123d\n\n \n # Build a frame around the heart\n with BuildPart() as heart_token:\n with BuildSketch() as outline:\n with BuildLine():\n add(l1)\n add(l2)\n add(l3)\n Line(l3 @ 1, l1 @ 0)\n make_face()\n mirror(about=Plane.YZ)\n center = outline.sketch\n offset(amount=2, kind=Kind.INTERSECTION)\n add(center, mode=Mode.SUBTRACT)\n extrude(amount=2, both=True)\n add(heart)\n \n heart_token.part.color = \"Red\"\n \n show(heart_token)\n\nNote that an additional planar line is used to close ``l1`` and ``l3`` so a ``Face``\ncan be created. The :func:`~operations_generic.offset` function defines the outside of\nthe frame as a constant distance from the heart itself.","api_names":"add BuildLine BuildPart BuildSketch extrude Face IntersectingLine JernArc l1 l3 l4 Line make_bezier_surface make_face make_line make_surface make_surface_from_array_of_points mirror offset Pos Shell show Solid ThreePointArc Token Wire XY","synonyms":"bore channel drill fit gap groove hollow path cut recessed fastener reflect shell symmetry tolerance wall thickness"},"421":{"title":"Surface Modeling","body":"Surface modeling refers to the direct creation and manipulation of the skin of a 3D\nobject-its bounding faces-rather than starting from volumetric primitives or solid\noperations.\n\nInstead of defining a shape by extruding or revolving a 2D profile to fill a volume,\nsurface modeling focuses on building the individual curved or planar faces that together\ndefine the outer boundary of a part. This approach allows for precise control of complex\nfreeform geometry such as aerodynamic surfaces, boat hulls, or organic transitions that\ncannot easily be expressed with simple parametric solids.\n\nIn build123d, as in other CAD kernels based on BREP (Boundary Representation) modeling,\nall solids are ultimately defined by their boundaries: a hierarchy of faces, edges, and\nvertices. Each face represents a finite patch of a geometric surface (plane, cylinder,\nBézier patch, etc.) bounded by one or more edge loops or wires. When adjacent faces share\nedges consistently and close into a continuous boundary, they form a manifold\n:class:`~topology.Shell`-the watertight surface of a volume. If this shell is properly\noriented and encloses a finite region of space, the model becomes a solid.\n\nSurface modeling therefore operates at the most fundamental level of BREP construction.\nRather than relying on higher-level modeling operations to implicitly generate faces,\nit allows you to construct and connect those faces explicitly. This provides a path to\nbuild geometry that blends analytical and freeform shapes seamlessly, with full control\nover continuity, tangency, and curvature across boundaries.\n\nThis section provides:\n- A concise overview of surface‑building tools in build123d\n- Hands‑on tutorials, from fundamentals to advanced techniques like Gordon surfaces\n\n.. rubric:: Available surface methods\n\nMethods on :class:`~topology.Face` for creating non‑planar surfaces:\n\n* :meth:`~topology.Face.make_bezier_surface`\n* :meth:`~topology.Face.make_gordon_surface`\n* :meth:`~topology.Face.make_surface`\n* :meth:`~topology.Face.make_surface_from_array_of_points`\n* :meth:`~topology.Face.make_surface_from_curves`\n* :meth:`~topology.Face.make_surface_patch`\n\n.. note::\n Surface modeling is an advanced technique. Robust results usually come from\n reusing the same :class:`~topology.Edge` objects across adjacent faces and\n ensuring the final :class:`~topology.Shell` is *water‑tight* or *manifold* (no gaps).\n\n.. toctree::\n :maxdepth: 1\n\n tutorial_surface_heart_token.rst\n tutorial_spitfire_wing_gordon.rst","api_names":"BREP Edge Face make_bezier_surface make_gordon_surface make_surface make_surface_from_array_of_points make_surface_from_curves make_surface_patch Shell surface","synonyms":""},"422":{"title":"Tutorials","body":"There are several tutorials to help guide uses through the concepts of build123d\nin a step by step way. Working through these tutorials in order is recommended\nas later tutorials build on the concepts introduced in earlier ones.\n\n.. toctree::\n :maxdepth: 2\n\n tutorial_design.rst\n tutorial_selectors.rst\n tutorial_constraints.rst\n tutorial_lego.rst\n tutorial_joints.rst\n examples_1.rst\n tttt.rst\n tutorial_stl_reconstruction.rst\n tutorial_surface_modeling.rst\n tech_drawing_tutorial.rst","api_names":"","synonyms":""}},"dirtCount":0,"index":[["$fn",{"1":{"230":1}}],["│",{"1":{"206":25}}],["\t└──",{"1":{"206":1}}],["\t",{"1":{"206":31}}],["\tfor",{"1":{"206":1}}],["\tfaces",{"1":{"206":3}}],["\twires",{"1":{"206":1}}],["\twithin",{"1":{"206":1}}],["\tmodeling",{"1":{"206":1}}],["\ttool",{"1":{"206":1}}],["\tthem",{"1":{"206":1}}],["\tthe",{"1":{"130":2,"206":1}}],["\tsolid",{"1":{"206":1}}],["\tshapes",{"1":{"206":1}}],["\tsubtraction",{"1":{"206":1}}],["\tsequence",{"1":{"206":1}}],["\tclosed",{"1":{"206":1}}],["\tconnected",{"1":{"206":1}}],["\tconstructing",{"1":{"206":1}}],["\tvolume",{"1":{"206":1}}],["\tor",{"1":{"206":1}}],["\tenabling",{"1":{"206":1}}],["\tedges",{"1":{"206":1}}],["\telement",{"1":{"206":1}}],["\tboundary",{"1":{"206":1}}],["\tdefine",{"1":{"206":1}}],["\ta",{"1":{"206":6}}],["\tan",{"1":{"206":1}}],["\t\t\t└──",{"1":{"131":1}}],["\t\t\t├──",{"1":{"131":5}}],["\t\t└──",{"1":{"131":1}}],["\t\tsolid",{"1":{"131":1}}],["\t>>>",{"1":{"128":5,"129":5,"130":1,"131":3}}],["✏️",{"1":{"79":1}}],["🔨",{"1":{"79":1}}],["🚨",{"1":{"79":1}}],["q",{"1":{"76":4}}],["questions",{"1":{"404":1,"406":1}}],["queries",{"1":{"233":1}}],["querying",{"1":{"230":3}}],["queen",{"1":{"76":3}}],["quarter",{"1":{"335":1,"409":6,"410":1,"415":1}}],["qualification",{"0":{"312":1},"1":{"312":2,"319":1}}],["qualifiers",{"0":{"331":1},"1":{"312":1,"315":1,"325":1,"331":1,"333":1}}],["qualifier",{"1":{"293":1,"331":1,"333":1},"2":{"333":1}}],["quality",{"1":{"61":1,"123":1,"134":2}}],["quaternion",{"1":{"197":1}}],["quintic",{"1":{"303":1}}],["quick",{"0":{"241":1},"1":{"117":1,"237":1}}],["quickly",{"1":{"99":1,"134":1,"139":1,"140":1,"197":1,"203":1}}],["quite",{"1":{"4":1,"129":1,"217":1,"262":1,"371":1}}],["~0",{"1":{"74":2}}],["○",{"1":{"48":1}}],["△",{"1":{"48":1}}],["✓",{"1":{"48":10,"238":62}}],["□",{"1":{"48":1}}],["^",{"1":{"34":1,"49":1,"68":2,"78":2,"124":1}}],["½",{"1":{"34":1,"78":2,"124":1}}],["96",{"1":{"283":2}}],["9>`",{"1":{"238":2}}],["999999999999996",{"1":{"295":1}}],["999999999999993",{"1":{"204":1}}],["99",{"1":{"76":3,"110":3,"243":3,"287":2}}],["95",{"1":{"76":1,"283":6,"287":1}}],["975",{"1":{"65":2}}],["97",{"1":{"60":1,"76":1}}],["9167",{"1":{"62":2}}],["91",{"1":{"60":2}}],["93",{"1":{"60":1}}],["98",{"1":{"60":3,"63":1}}],["923",{"1":{"280":1}}],["925",{"1":{"65":2,"70":4}}],["92",{"1":{"26":1,"76":1,"222":1,"280":1}}],["94",{"1":{"26":1,"60":2,"68":1,"76":3,"222":1,"282":1}}],["9",{"0":{"177":1,"345":1,"377":1},"1":{"26":1,"60":6,"61":1,"76":7,"77":1,"80":1,"163":4,"176":1,"179":1,"222":1,"281":1,"282":2,"283":1,"367":1}}],["90°",{"1":{"364":1}}],["90",{"1":{"14":7,"61":1,"62":2,"65":1,"70":2,"76":1,"77":2,"81":2,"147":2,"163":2,"173":2,"179":2,"198":4,"201":1,"230":1,"278":1,"280":4,"281":1,"282":1,"283":1,"284":2,"286":2,"289":1,"317":2,"350":1,"352":2,"353":3,"357":1}}],[">=",{"1":{"182":1,"271":1}}],["><",{"1":{"124":2,"396":2,"420":2}}],[">>>",{"1":{"204":13,"295":5}}],[">>",{"1":{"49":1,"241":2}}],[">",{"1":{"49":1,"61":4,"69":2,"76":1,"208":2,"241":2,"243":1}}],[">`",{"1":{"20":1,"82":1,"87":1,"90":1,"91":3,"92":1,"124":2,"129":1}}],[">z",{"1":{"7":1}}],["¼",{"1":{"19":1}}],["6e",{"0":{"394":1}}],["6d",{"0":{"393":1}}],["6c",{"0":{"392":1}}],["6b",{"0":{"391":1}}],["6a",{"0":{"390":1},"1":{"391":1}}],["6mm",{"1":{"290":1}}],["66",{"1":{"109":1,"279":9,"295":5}}],["644",{"1":{"70":1}}],["6427",{"1":{"62":2}}],["64",{"1":{"60":1}}],["625",{"1":{"66":2,"280":1}}],["6267",{"1":{"62":2}}],["62",{"1":{"60":1,"76":1,"81":2}}],["65",{"1":{"60":2,"64":2,"182":1,"278":7}}],["68",{"1":{"182":1}}],["685950",{"1":{"51":1}}],["681751",{"1":{"51":1}}],["691604",{"1":{"51":1}}],["690072",{"1":{"51":1}}],["69",{"1":{"34":1,"60":3,"76":1,"78":2,"124":1,"286":1,"289":1}}],["6781",{"1":{"62":2}}],["678646",{"1":{"51":1}}],["679888",{"1":{"51":1}}],["679233",{"1":{"51":1}}],["67",{"1":{"26":1,"60":1,"76":2,"222":1}}],["6188",{"1":{"62":2}}],["61",{"1":{"26":1,"60":2,"76":2,"222":1}}],["6",{"0":{"174":1,"342":1,"360":1,"374":1,"389":1},"1":{"19":2,"26":2,"31":1,"60":4,"61":1,"66":1,"68":4,"71":1,"74":4,"75":6,"76":5,"80":3,"81":1,"158":4,"163":3,"166":5,"167":4,"168":2,"171":2,"173":1,"222":1,"243":3,"256":1,"262":1,"278":1,"279":1,"280":4,"281":2,"286":2,"287":2,"290":2,"304":3,"367":4,"408":1,"413":1}}],["600",{"1":{"66":1}}],["60",{"1":{"14":5,"32":1,"34":1,"37":1,"60":1,"64":2,"65":3,"78":2,"81":2,"124":1,"142":2,"143":1,"144":2,"145":3,"149":2,"151":2,"153":2,"154":2,"155":2,"156":2,"158":2,"160":2,"161":2,"163":2,"164":2,"165":2,"169":2,"170":2,"172":2,"174":2,"175":2,"177":2,"182":1,"190":1,"256":1,"278":1,"281":1,"285":2,"289":1,"295":2}}],["7d",{"0":{"365":1}}],["7c",{"0":{"364":1}}],["7b",{"0":{"363":1}}],["7a",{"0":{"362":1}}],["73",{"1":{"287":2}}],["797",{"1":{"281":2}}],["7800e",{"1":{"279":1,"280":1}}],["7800",{"1":{"278":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["7808",{"1":{"62":2}}],["78",{"1":{"60":4}}],["7763568394002505e",{"1":{"295":1}}],["77052487945",{"1":{"78":1}}],["77361455046953",{"1":{"68":1}}],["7752",{"1":{"62":2}}],["77",{"1":{"60":2,"279":1,"295":1}}],["74b11c1ff2bfc977adc96e5c7b4cd162>`",{"1":{"92":1}}],["740",{"1":{"60":1}}],["747358",{"1":{"51":1}}],["72",{"1":{"60":1,"75":1,"76":1}}],["728681",{"1":{"51":1}}],["724628",{"1":{"51":1}}],["75",{"1":{"34":1,"61":1,"65":6,"67":2,"78":2,"80":2,"81":2,"124":1,"243":1,"278":1,"289":6,"331":1}}],["7",{"0":{"175":1,"343":1,"361":1,"375":1},"1":{"25":4,"34":1,"60":3,"61":1,"67":2,"74":2,"76":10,"78":2,"80":1,"124":1,"128":2,"167":2,"173":2,"174":1,"182":1,"278":4,"280":1,"283":1,"284":1,"299":4,"408":1}}],["70",{"1":{"14":1,"42":1,"74":2,"76":1,"80":1,"182":1}}],["766729",{"1":{"51":1}}],["766106",{"1":{"51":1}}],["765380",{"1":{"51":1}}],["762429",{"1":{"51":1}}],["76",{"1":{"11":1,"26":1,"60":2,"63":1,"76":1,"222":1}}],["└──",{"1":{"14":2,"206":13}}],["├──",{"1":{"14":7,"206":15}}],["knot",{"1":{"218":1}}],["knob",{"1":{"182":2}}],["knows",{"1":{"189":1}}],["know",{"1":{"163":1,"171":1,"188":1,"197":1,"391":1,"393":1}}],["known",{"1":{"75":1,"94":1,"160":1,"267":1,"322":1,"327":1}}],["knowing",{"1":{"5":1,"268":1}}],["khronos",{"1":{"117":1}}],["kink",{"1":{"303":1}}],["king",{"1":{"76":3}}],["kind=kind",{"1":{"159":2,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"420":1}}],["kind`",{"1":{"49":1,"159":1}}],["kind",{"1":{"44":1,"278":1},"2":{"44":1,"49":1,"159":1,"373":1}}],["k",{"0":{"217":1},"1":{"75":4,"76":4,"279":2,"295":2}}],["kept",{"1":{"318":1}}],["kernels",{"1":{"421":1}}],["kernel",{"1":{"124":1,"163":1}}],["keyway",{"1":{"286":1}}],["keyword",{"1":{"199":2,"374":1}}],["keys",{"1":{"265":3,"268":1}}],["keybird42",{"1":{"102":1}}],["keyerror",{"1":{"75":1}}],["key",{"0":{"70":1,"137":1,"186":1,"196":1,"197":1,"203":1},"1":{"37":1,"60":1,"61":1,"69":1,"70":23,"71":1,"73":3,"126":3,"137":1,"197":1,"203":1,"234":1,"258":1,"268":1,"269":1,"276":1,"304":1,"367":1,"408":1},"2":{"268":1}}],["keeping",{"1":{"306":1,"310":1,"329":1}}],["keep=keep",{"1":{"59":1,"74":2}}],["keep`",{"1":{"49":1}}],["keeps",{"1":{"34":1,"61":1,"194":1,"299":1}}],["keep",{"1":{"13":1,"31":1,"44":1,"74":2,"141":1,"157":1,"225":2,"236":1,"261":1,"299":1,"311":4,"320":1,"343":1,"347":1,"402":1},"2":{"44":1,"49":1}}],["kbd",{"1":{"102":1}}],["kb",{"1":{"19":2}}],["8°",{"1":{"279":1,"295":1}}],["875",{"1":{"65":2}}],["8900473617498",{"1":{"70":1}}],["89",{"1":{"60":1,"179":1}}],["88°",{"1":{"80":1}}],["88331045553787",{"1":{"69":2}}],["88",{"1":{"60":1,"76":1,"80":1,"278":1}}],["82",{"1":{"60":1,"74":2}}],["85",{"1":{"60":1,"67":1,"70":2,"80":1}}],["84",{"1":{"60":3,"287":1,"288":1,"290":3}}],["8146",{"1":{"62":2}}],["81",{"1":{"26":1,"60":2,"76":1,"222":1,"299":4}}],["8",{"0":{"176":1,"344":1,"376":1},"1":{"11":2,"31":2,"34":1,"60":8,"61":3,"74":2,"75":6,"76":3,"77":3,"78":2,"80":3,"124":2,"152":2,"163":1,"175":1,"179":2,"182":1,"208":1,"278":1,"279":8,"280":1,"281":2,"282":2,"284":1,"287":3,"288":1,"290":1,"295":6,"307":1,"367":4,"417":24}}],["80°",{"1":{"80":1}}],["80",{"1":{"11":1,"32":1,"34":1,"42":2,"61":2,"78":2,"80":2,"124":1,"142":2,"143":1,"144":2,"148":2,"149":2,"151":2,"152":2,"153":2,"154":2,"156":2,"158":2,"160":2,"161":2,"162":2,"164":2,"166":2,"167":2,"168":2,"169":2,"170":2,"172":2,"174":2,"175":2,"177":2,"190":1,"209":7,"247":1,"256":1,"278":2,"284":1,"331":1}}],["glob",{"1":{"255":2,"257":1,"367":1}}],["global",{"0":{"39":1},"1":{"31":4,"67":1,"198":1,"255":2,"257":1,"262":1,"302":1,"310":2,"339":1,"358":1},"2":{"339":1}}],["glb",{"1":{"124":1,"396":1,"420":1}}],["gl",{"1":{"117":1}}],["gltf",{"0":{"117":1},"1":{"106":1,"117":4},"2":{"106":1,"117":1}}],["guaranteed",{"1":{"378":1}}],["gutter",{"1":{"264":1,"265":1,"266":1}}],["gumyr",{"1":{"87":1,"104":1,"128":1,"129":3,"278":2}}],["guidance",{"1":{"408":1}}],["guided",{"1":{"328":1,"415":1}}],["guidelines",{"1":{"119":1}}],["guides=",{"1":{"61":1}}],["guides",{"1":{"61":1,"395":3,"396":2,"397":1,"398":1,"400":7,"403":2}}],["guide",{"0":{"397":1},"1":{"61":2,"234":1,"299":1,"334":1,"346":1,"348":1,"366":1,"379":1,"396":1,"402":1,"403":1,"422":1}}],["gui",{"0":{"127":1},"1":{"86":1,"127":1,"141":3,"250":1,"255":1,"258":1}}],["giving",{"1":{"257":1,"303":1,"317":1,"344":1}}],["gives",{"1":{"196":1,"319":1}}],["given",{"1":{"48":1,"62":2,"110":1,"147":1,"171":1,"201":1,"217":1,"238":1,"290":1,"304":1,"329":1,"340":1,"358":1}}],["gimbal",{"1":{"179":1,"181":1}}],["git+https",{"1":{"128":1,"129":3}}],["git",{"1":{"128":2,"129":2,"133":1,"141":11}}],["githubusercontent",{"1":{"104":1}}],["github",{"0":{"129":1},"1":{"73":2,"85":1,"86":1,"87":5,"90":1,"91":1,"93":2,"94":1,"95":1,"99":1,"101":1,"102":1,"104":2,"128":2,"129":5,"130":1,"141":1,"181":1,"251":1,"299":1}}],["games",{"1":{"135":1}}],["game",{"1":{"117":1,"420":2}}],["garrybgoode",{"1":{"101":1}}],["garages",{"1":{"74":1}}],["gallery",{"1":{"59":1}}],["gaps",{"1":{"421":1}}],["gap",{"1":{"61":1,"76":3,"179":2},"3":{"34":1,"42":1,"49":1,"52":1,"61":1,"62":1,"71":1,"72":1,"76":1,"78":1,"80":1,"81":1,"124":1,"149":1,"152":1,"154":1,"158":1,"159":1,"160":1,"161":1,"163":1,"182":1,"238":1,"239":1,"241":1,"243":1,"278":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"287":1,"290":1,"310":1,"313":1,"314":1,"337":1,"340":1,"341":1,"346":1,"357":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"406":1,"417":1,"419":1,"420":1}}],["gt",{"1":{"58":1}}],["going",{"1":{"372":2,"373":1,"420":1}}],["governing",{"1":{"278":1,"295":1}}],["governments",{"1":{"138":1}}],["gone",{"1":{"131":1}}],["google",{"1":{"124":1,"396":1,"420":1}}],["good",{"0":{"411":1},"1":{"34":1,"61":1,"134":1,"135":1,"140":1,"255":2,"263":1,"331":1,"404":1,"417":1}}],["goals",{"1":{"260":1}}],["goal",{"1":{"91":1,"141":1,"229":1,"255":1,"291":1,"415":1}}],["golden",{"1":{"75":1}}],["got=",{"1":{"72":1}}],["got",{"1":{"72":2,"278":6,"279":4,"280":4,"281":4,"282":4,"283":4,"284":4,"285":4,"286":4,"287":4,"288":4,"289":4,"290":4}}],["goes",{"1":{"61":1}}],["gordon`",{"1":{"418":1}}],["gordon",{"0":{"400":1,"402":1,"403":1},"1":{"61":5,"395":3,"396":1,"397":1,"400":4,"403":3,"418":1,"421":3},"2":{"61":1,"395":1,"400":1,"403":1,"418":1,"421":1}}],["go",{"1":{"42":1,"77":1,"306":1,"334":1,"345":1,"357":1}}],["genre",{"1":{"197":1}}],["generously",{"1":{"291":1}}],["generator",{"0":{"101":1}}],["generators",{"1":{"90":1}}],["generative",{"1":{"92":1,"98":1}}],["generation",{"1":{"82":1,"84":1,"101":1},"2":{"82":1}}],["generating",{"1":{"78":1,"139":1}}],["generate",{"0":{"342":1},"1":{"28":2,"31":1,"69":1,"78":1,"99":1,"110":3,"122":1,"133":5,"139":1,"182":1,"201":1,"238":1,"243":1,"245":1,"248":1,"340":1,"421":1}}],["generated",{"0":{"406":1},"1":{"25":2,"26":2,"31":1,"66":1,"110":1,"184":1,"202":1,"406":2,"408":1,"410":1,"411":1,"412":1,"414":1,"417":2}}],["generates",{"1":{"25":1,"26":1,"30":1,"31":1,"51":1,"67":1,"110":1,"235":1},"2":{"30":1}}],["generally",{"1":{"40":1,"141":1,"250":1,"255":1}}],["general",{"1":{"32":1,"119":2,"140":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"178":1,"209":1,"310":1,"312":1}}],["generic",{"1":{"25":1,"34":2,"39":1,"49":25,"143":2,"147":2,"159":2,"160":2,"176":1,"177":2,"188":1,"199":1,"238":10,"239":10,"250":1,"252":1,"308":1,"310":2,"313":1,"314":1,"389":1,"419":1,"420":1}}],["gears",{"1":{"101":1}}],["gear",{"1":{"101":1}}],["gearworks>`",{"1":{"101":1}}],["gearworks",{"0":{"101":1},"1":{"101":1}}],["geometries",{"1":{"233":1,"235":1}}],["geometrical",{"1":{"78":1}}],["geometric",{"0":{"55":1,"308":1,"309":1},"1":{"55":1,"112":1,"113":1,"124":1,"200":1,"204":3,"206":7,"218":2,"236":1,"271":1,"276":1,"277":1,"302":1,"306":1,"308":1,"310":3,"312":1,"320":1,"329":2,"330":1,"333":1,"340":1,"391":1,"421":1}}],["geometry",{"0":{"148":1,"231":1},"1":{"48":1,"49":1,"55":2,"60":1,"61":1,"80":1,"111":1,"112":1,"120":1,"121":2,"124":1,"139":1,"194":1,"206":1,"230":2,"231":1,"232":1,"234":1,"245":1,"250":1,"295":1,"299":3,"306":1,"307":1,"308":3,"310":4,"313":1,"318":1,"320":1,"331":1,"333":1,"340":2,"341":1,"342":1,"345":1,"405":1,"417":1,"421":2},"2":{"230":1,"231":1,"234":1,"250":1,"299":1}}],["geomtype`",{"1":{"49":2,"241":1,"271":1}}],["geomtype",{"1":{"34":1,"42":1,"44":1,"69":2,"72":2,"78":2,"81":2,"124":1,"241":4,"256":1,"266":3,"280":2,"282":1,"284":1,"287":1,"289":1,"290":1,"350":1,"389":1,"391":1,"392":1,"393":1,"394":1,"417":8},"2":{"44":1,"49":1,"241":1,"271":1}}],["getting",{"1":{"349":1,"367":1,"380":1}}],["getter",{"1":{"204":1}}],["getters",{"1":{"204":1}}],["getitem",{"1":{"58":1}}],["getlogger",{"1":{"51":2},"2":{"51":1}}],["get",{"0":{"252":1,"384":1,"393":1},"1":{"11":1,"42":1,"61":1,"102":1,"129":1,"252":1,"268":1,"334":1,"362":1}}],["g",{"1":{"19":1,"91":1,"135":2,"178":4,"199":1,"241":1,"278":1,"279":2,"281":3,"282":3,"283":3,"284":3,"285":3,"286":3,"287":3,"288":3,"289":3,"290":3,"369":1}}],["gradual",{"1":{"304":1}}],["graph",{"1":{"276":1,"310":1}}],["graphic",{"1":{"123":3}}],["graphics",{"1":{"123":6}}],["graphical",{"1":{"113":1,"310":1}}],["granular",{"1":{"141":1}}],["grill",{"1":{"80":8}}],["grid",{"0":{"66":1,"374":1},"1":{"40":2,"49":12,"65":1,"66":5,"73":26,"144":2,"211":2,"218":29,"219":19,"220":11,"264":5,"265":4,"266":7,"291":14,"368":1,"369":3,"374":2,"375":2,"376":1,"377":1,"400":1,"403":1}}],["gridlocations`",{"1":{"40":1,"49":1,"144":2,"156":1,"211":1}}],["gridlocations",{"0":{"144":1},"1":{"11":3,"42":1,"45":1,"51":2,"60":1,"63":1,"64":2,"76":1,"77":1,"80":3,"144":2,"149":2,"156":2,"166":2,"182":1,"198":2,"256":1,"288":1,"350":2,"357":1,"359":1,"368":3,"369":4,"374":2,"375":2,"376":3,"377":3},"2":{"11":1,"40":1,"42":1,"49":1,"60":1,"63":1,"64":1,"76":1,"77":1,"80":1,"144":1,"149":1,"156":1,"166":1,"182":1,"198":1,"211":1,"256":1,"288":1,"350":1,"357":1,"359":1,"368":1,"369":1,"374":1,"375":1,"376":1,"377":1}}],["great",{"1":{"140":3,"268":1}}],["greater",{"1":{"72":1,"236":1,"353":2}}],["greatest",{"1":{"49":1,"202":1,"260":1,"275":1,"394":1}}],["greek",{"1":{"75":1}}],["growing",{"1":{"310":1}}],["grown",{"1":{"307":1}}],["grow",{"1":{"236":1}}],["groupby",{"2":{"268":1,"269":1}}],["grouping",{"1":{"206":2,"268":3,"414":1}}],["grouped",{"1":{"177":1,"268":1,"274":1,"276":1,"406":1,"417":1}}],["group",{"0":{"268":1},"1":{"10":1,"49":2,"59":3,"69":2,"80":13,"117":1,"143":2,"144":2,"150":1,"151":2,"152":3,"154":1,"156":2,"158":1,"162":2,"177":5,"182":2,"241":4,"243":2,"262":2,"265":7,"266":1,"268":6,"269":1,"271":1,"273":1,"276":4,"278":4,"281":1,"282":2,"284":3,"286":1,"289":2,"290":1,"344":4,"346":1},"2":{"49":1,"59":1,"69":1,"80":1,"143":1,"144":1,"150":1,"151":1,"152":1,"154":1,"156":1,"158":1,"162":1,"177":1,"182":1,"243":1,"262":1,"266":1,"268":3,"276":1,"278":1,"281":1,"282":1,"284":1,"286":1,"289":1,"290":1,"344":1,"346":1}}],["groups",{"1":{"10":2,"80":1,"166":2,"276":3,"344":2}}],["groove",{"3":{"4":1,"16":1,"25":1,"31":1,"32":1,"34":1,"37":1,"42":1,"49":1,"51":1,"59":1,"60":1,"61":1,"62":1,"64":1,"65":1,"68":1,"69":1,"70":1,"71":1,"74":1,"76":1,"78":1,"80":1,"124":1,"144":1,"147":1,"149":1,"151":1,"152":1,"153":1,"156":1,"161":1,"164":1,"169":1,"170":1,"173":1,"174":1,"175":1,"179":1,"182":1,"184":1,"192":1,"193":1,"224":1,"229":1,"235":1,"236":1,"238":1,"239":1,"252":1,"278":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"299":1,"345":1,"346":1,"350":1,"357":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"385":1,"387":1,"388":1,"389":1,"420":1}}],["jig",{"0":{"286":1},"1":{"286":1,"291":1}}],["js",{"1":{"124":1,"396":1,"420":1}}],["jpeg",{"1":{"117":1}}],["jpg",{"1":{"80":1,"334":1}}],["jern",{"1":{"94":1,"218":1}}],["jernarc`",{"1":{"49":1,"218":1,"306":1,"307":1,"310":1}}],["jernarc",{"1":{"30":1,"31":1,"71":1,"74":6,"147":4,"225":1,"286":2,"332":1,"420":2},"2":{"10":1,"30":1,"31":1,"49":1,"71":1,"74":1,"147":1,"218":1,"225":1,"286":1,"306":1,"307":1,"310":1,"332":1,"420":1}}],["jmwright",{"1":{"86":1}}],["jdegenstein",{"1":{"86":2}}],["jack",{"1":{"76":3}}],["j",{"1":{"63":3,"73":1,"74":1,"75":16,"76":4,"168":2}}],["joined",{"1":{"183":1,"304":1}}],["join",{"1":{"61":1,"158":1,"303":1,"304":1,"313":1}}],["joins",{"1":{"61":1,"303":1,"304":1}}],["joint`",{"1":{"181":6,"347":1,"348":2,"357":1,"358":2,"360":1}}],["joints=leaf",{"1":{"355":1}}],["joints=true``",{"1":{"184":1}}],["joints=true",{"1":{"182":3,"184":1,"347":1}}],["joints=false",{"1":{"77":1}}],["joints",{"0":{"181":1,"351":1,"354":1,"361":1},"1":{"77":7,"80":4,"126":1,"179":2,"180":2,"181":7,"182":3,"183":2,"184":11,"345":2,"347":1,"350":5,"351":1,"353":1,"354":1,"355":1,"358":1,"359":1,"361":1,"362":2,"363":3,"364":2,"365":1,"422":1},"2":{"184":1,"363":1}}],["joint",{"0":{"57":1,"179":1,"180":1,"182":1,"183":1,"184":1,"348":1,"352":1,"353":1,"360":1},"1":{"57":3,"77":2,"80":4,"179":4,"180":3,"182":5,"183":2,"184":10,"347":2,"348":1,"350":2,"352":4,"353":3,"354":2,"357":3,"359":2,"360":2,"362":3,"363":1,"364":1,"365":2},"2":{"57":1,"181":1,"184":2,"347":1,"348":1,"352":1,"357":1,"358":1,"360":1}}],["jumps",{"1":{"303":1}}],["july",{"1":{"278":1}}],["junctions",{"1":{"30":1}}],["justified",{"1":{"221":1}}],["just",{"1":{"4":1,"11":1,"13":1,"19":2,"31":1,"37":1,"52":1,"71":1,"124":1,"142":1,"182":1,"194":1,"198":1,"217":1,"278":1,"344":1,"353":1,"364":1,"367":1,"368":1,"371":1,"388":2,"391":1,"393":1,"394":1}}],["+++",{"1":{"218":28,"219":18,"220":10}}],["+0",{"1":{"61":1}}],["+=============+========+",{"1":{"369":1}}],["+=============+===================================+===================+===================+",{"1":{"241":1}}],["+======================+==================================================================+=======================================================+",{"1":{"271":1}}],["+=================================+======================================+======+========+======+",{"1":{"238":1}}],["+==============================================+====================================+====+====+====+====+===================================+",{"1":{"238":1}}],["+=======================================+=====================================================================+====================+",{"1":{"181":1}}],["+==============+================+===============================================+=======================+",{"1":{"270":1}}],["+==========+=======================+====================+=======================================================+===========================================================================+",{"1":{"241":1}}],["+==========+=============================+=====================================+",{"1":{"49":1}}],["+==========+==============================+=====================================+=====================+",{"1":{"49":1}}],["+==========+=========================================================================================================================================+=============================+",{"1":{"49":1}}],["+==========+=========================================================================================================+================================================+",{"1":{"49":1}}],["+==========+======================================+=============================+",{"1":{"49":1}}],["+==========+===========================+=========================================+=============================================+",{"1":{"49":1}}],["+==========+=====================+=========================================+=================================+",{"1":{"49":1}}],["+=",{"1":{"11":1,"61":1,"62":1,"67":5,"68":1,"69":2,"70":4,"72":1,"74":1,"78":3,"81":2,"124":1,"148":1,"150":1,"154":1,"155":1,"157":1,"158":1,"163":2,"166":1,"167":1,"169":1,"170":2,"171":1,"176":1,"204":1,"215":1,"216":1,"230":1,"290":3}}],["+",{"0":{"322":1,"323":1,"324":1,"325":1,"327":1,"328":2},"1":{"10":13,"11":3,"28":3,"30":2,"31":3,"34":3,"49":242,"61":4,"62":7,"65":2,"67":10,"68":4,"69":3,"71":1,"72":4,"74":5,"75":8,"76":8,"77":2,"78":6,"80":1,"81":15,"110":1,"124":3,"143":1,"144":2,"147":4,"148":8,"149":1,"151":1,"152":1,"156":1,"158":1,"159":1,"163":6,"165":1,"166":1,"167":3,"168":5,"172":4,"177":1,"181":24,"185":1,"187":1,"208":1,"238":254,"241":78,"243":3,"270":30,"271":24,"272":1,"273":2,"278":2,"279":6,"281":4,"283":1,"284":3,"286":1,"287":4,"288":14,"289":1,"290":2,"295":5,"298":1,"299":13,"303":2,"315":5,"319":1,"350":2,"354":1,"367":1,"368":2,"369":14,"375":2,"376":2,"377":2,"395":3,"397":2,"400":1,"420":3}}],["3e",{"0":{"356":1}}],["3c",{"0":{"354":1}}],["3b",{"0":{"353":1,"384":1},"1":{"394":1}}],["3a",{"0":{"352":1,"383":1},"1":{"390":1}}],["3>`",{"1":{"238":1}}],["3mf",{"0":{"111":1},"1":{"108":3,"109":2,"111":3}}],["3f",{"1":{"66":1}}],["399999",{"1":{"417":16}}],["390",{"1":{"299":1}}],["39",{"1":{"60":2}}],["372",{"1":{"287":2}}],["371288916",{"1":{"278":1}}],["375",{"1":{"62":2}}],["37",{"1":{"60":3,"76":1,"147":1,"282":1,"289":2}}],["360°",{"1":{"71":1,"353":1,"354":1}}],["360",{"1":{"60":2,"65":2,"137":1,"179":1,"250":1,"354":1}}],["36",{"0":{"171":1},"1":{"60":3,"170":1,"286":2,"395":1,"397":1}}],["310",{"1":{"284":2}}],["3125",{"1":{"62":2}}],["31",{"0":{"166":1},"1":{"60":4,"76":2,"165":1}}],["3875",{"1":{"62":2}}],["38",{"1":{"59":1,"60":2,"284":1,"285":2}}],["35",{"0":{"170":1},"1":{"34":2,"42":1,"60":3,"64":2,"67":2,"74":2,"78":4,"80":1,"124":2,"145":2,"157":6,"169":1,"279":1,"287":3,"288":5}}],["32050807568877",{"1":{"295":1}}],["328",{"1":{"286":2}}],["3277",{"1":{"62":2}}],["32",{"0":{"167":1},"1":{"26":1,"60":2,"76":1,"166":1,"182":1,"222":1,"279":3,"295":1,"299":4}}],["3387",{"1":{"288":2}}],["3362",{"1":{"62":2}}],["33",{"0":{"168":1},"1":{"26":1,"60":3,"76":1,"167":1,"222":1,"288":5,"289":1}}],["3d",{"0":{"106":1,"107":1,"108":1,"109":1,"110":1,"149":1,"220":1,"250":1,"355":1},"1":{"22":1,"48":1,"49":3,"58":2,"60":1,"61":7,"65":2,"66":4,"67":2,"74":3,"81":2,"82":2,"87":1,"92":1,"104":2,"108":1,"110":3,"111":6,"112":3,"113":1,"117":5,"120":2,"121":6,"124":3,"135":4,"149":1,"160":2,"163":1,"189":1,"193":1,"194":1,"201":1,"202":2,"204":2,"206":12,"221":2,"224":2,"229":1,"230":3,"231":1,"232":2,"233":2,"234":1,"235":5,"236":4,"237":1,"238":6,"243":2,"245":2,"246":2,"248":1,"250":6,"253":2,"257":1,"262":3,"291":3,"334":1,"337":1,"341":2,"344":1,"345":1,"421":1}}],["3",{"0":{"164":1,"339":1,"351":1,"371":1,"382":1,"399":1,"406":1},"1":{"17":1,"25":4,"28":1,"31":4,"34":1,"49":3,"59":1,"60":3,"61":2,"62":2,"67":6,"68":3,"69":7,"70":5,"72":2,"73":1,"76":9,"77":3,"78":3,"80":5,"81":9,"124":1,"131":2,"149":1,"153":1,"154":2,"158":2,"159":4,"165":2,"166":11,"167":2,"175":4,"178":1,"179":2,"185":1,"187":4,"188":13,"189":2,"194":1,"202":3,"204":3,"208":1,"209":6,"211":1,"218":1,"219":1,"220":1,"230":5,"241":1,"243":3,"245":1,"251":1,"264":2,"265":2,"266":2,"279":1,"280":5,"282":1,"286":1,"287":4,"291":1,"299":1,"315":1,"316":1,"336":1,"346":1,"350":4,"357":2,"359":2,"367":1,"396":1,"408":1,"413":1,"415":1}}],["3405290344635",{"1":{"72":1}}],["3433",{"1":{"62":2}}],["34",{"0":{"169":1},"1":{"16":3,"168":1,"281":1,"283":4}}],["3``",{"1":{"10":2,"271":1}}],["3`",{"1":{"9":2,"10":4}}],["307",{"1":{"289":2}}],["30",{"0":{"165":1},"1":{"4":1,"11":1,"14":2,"34":2,"42":1,"51":4,"60":1,"61":2,"64":6,"65":1,"69":2,"70":2,"78":4,"108":1,"110":1,"124":2,"145":7,"150":2,"159":2,"163":1,"179":2,"182":4,"199":1,"201":3,"204":1,"208":1,"209":5,"211":1,"230":1,"278":2,"279":9,"285":2,"286":1,"288":2,"290":2,"295":5,"357":3,"359":2}}],["|filter",{"1":{"266":2,"267":3,"271":2}}],["|faces|",{"1":{"266":1,"270":1}}],["|topo",{"1":{"266":1,"271":1,"276":1}}],["|group",{"1":{"266":1,"268":2,"269":1,"271":1}}],["|shapelist|",{"1":{"266":1,"274":1,"277":2}}],["|sort",{"1":{"266":2,"271":2,"275":2}}],["|solids|",{"1":{"266":1,"270":1}}],["|siren|",{"1":{"79":1}}],["|wires|",{"1":{"266":1,"270":1}}],["|edges|",{"1":{"266":1,"268":1,"270":1,"272":1}}],["|vertices|",{"1":{"266":1,"270":1,"275":1}}],["|algebra|",{"1":{"61":1,"62":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"72":1,"73":16,"74":1,"75":1,"77":1,"78":1,"79":1,"81":2}}],["|builder|",{"1":{"59":1,"60":1,"62":1,"63":1,"64":1,"65":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":18,"74":1,"76":1,"78":1,"79":1,"80":1,"81":2}}],["|",{"1":{"9":2,"49":351,"181":24,"238":253,"241":80,"267":1,"268":1,"270":30,"271":24,"275":1,"369":12}}],["|x",{"1":{"9":1}}],["|z",{"1":{"7":1,"9":1}}],["∈",{"1":{"9":1}}],["xxx",{"1":{"293":1}}],["x1",{"1":{"286":4}}],["xc1",{"1":{"282":1}}],["xl8",{"1":{"279":5,"295":5}}],["x66",{"1":{"279":5,"295":5}}],["x30",{"1":{"279":5,"295":5}}],["x`",{"1":{"241":1}}],["x``",{"1":{"152":1,"241":1,"275":1}}],["x>",{"1":{"201":1}}],["x04",{"1":{"189":1}}],["x0pherl",{"1":{"99":1}}],["xml",{"1":{"123":1}}],["x=0",{"1":{"188":2}}],["x=1",{"1":{"188":3}}],["x=30",{"1":{"185":1}}],["x=5",{"1":{"124":1}}],["x=r",{"1":{"60":1}}],["x=",{"1":{"51":1,"52":1,"185":1}}],["xz``",{"1":{"188":5,"202":1,"263":1}}],["xzx",{"1":{"49":2}}],["xzy",{"1":{"49":2}}],["xz",{"0":{"262":1},"1":{"34":2,"67":2,"71":2,"74":2,"76":1,"78":3,"80":3,"124":3,"147":2,"149":2,"157":2,"182":1,"185":1,"188":4,"198":1,"202":1,"208":1,"262":1,"263":1,"278":4,"280":2,"281":2,"282":3,"283":3,"288":1,"290":3,"409":1},"2":{"124":1,"188":1,"202":1,"263":1}}],["xyx",{"1":{"49":2}}],["xyz",{"1":{"49":2,"92":1,"350":1}}],["xy``",{"1":{"31":1,"32":1,"39":4,"42":1,"188":1,"202":3,"254":1,"262":4,"263":5,"414":1,"420":1}}],["xy",{"0":{"208":1},"1":{"7":1,"16":2,"21":1,"22":1,"23":1,"37":1,"39":1,"52":1,"61":1,"62":2,"63":1,"69":2,"71":1,"80":1,"149":2,"159":4,"163":1,"188":4,"198":1,"202":1,"278":1,"280":1,"281":1,"284":1,"285":2,"287":5,"339":1,"341":1,"346":1,"406":1,"417":7,"420":2},"2":{"31":1,"32":1,"39":1,"42":1,"188":1,"202":1,"254":1,"262":1,"263":1,"339":1,"414":1,"420":1}}],["x",{"1":{"6":1,"9":5,"11":2,"21":2,"34":1,"39":1,"40":2,"42":2,"52":1,"59":3,"60":3,"61":13,"64":9,"67":13,"69":2,"77":3,"78":2,"80":3,"124":1,"149":2,"152":8,"154":3,"163":2,"171":2,"173":2,"182":4,"188":2,"198":2,"202":1,"215":3,"216":3,"217":1,"221":2,"240":1,"241":2,"243":9,"246":1,"262":2,"275":2,"278":4,"279":1,"280":1,"281":1,"282":3,"284":2,"289":3,"290":2,"299":2,"320":1,"323":1,"327":1,"339":1,"344":5,"345":5,"346":2,"352":1,"357":1,"368":5,"369":4,"374":2,"375":2,"376":4,"377":4},"2":{"9":1,"152":1,"208":1,"209":2,"241":2,"275":1,"368":1}}],["`",{"1":{"108":1}}],["<<",{"1":{"49":1,"241":2}}],["",{"1":{"201":1}}],["yacv",{"2":{"104":1}}],["yet",{"0":{"104":1},"1":{"104":2},"2":{"95":1}}],["yeicor",{"1":{"87":1,"95":1,"104":2}}],["y=2",{"1":{"188":3}}],["y=100",{"1":{"188":2}}],["y=1",{"1":{"188":1}}],["y=",{"1":{"60":2}}],["yx",{"1":{"149":2}}],["yxy",{"1":{"49":2}}],["yxz",{"1":{"49":2}}],["yz`",{"1":{"399":1}}],["yz``",{"1":{"31":3}}],["yzy",{"1":{"49":2}}],["yzx",{"1":{"49":2}}],["yz",{"1":{"26":1,"31":1,"42":1,"60":2,"61":2,"62":4,"74":2,"76":4,"80":7,"148":2,"149":4,"176":4,"179":2,"185":1,"222":1,"262":1,"278":2,"279":1,"280":10,"281":2,"282":2,"284":3,"286":1,"287":1,"288":2,"289":3,"290":1,"340":3,"341":1,"346":1,"395":2,"399":2,"409":1,"417":7,"420":3},"2":{"31":1,"399":1}}],["youtube",{"1":{"71":1,"94":1,"291":2}}],["yourself",{"0":{"249":1}}],["your",{"0":{"131":1},"1":{"21":1,"30":1,"39":1,"50":1,"51":1,"52":1,"53":1,"73":3,"81":6,"87":1,"91":2,"92":1,"99":1,"108":1,"127":1,"133":2,"157":1,"178":4,"222":1,"233":2,"234":1,"236":2,"249":1,"255":1,"261":2,"295":1,"336":1,"340":1,"347":1,"414":1}}],["you",{"1":{"21":2,"22":2,"54":1,"61":2,"73":1,"80":1,"108":2,"124":1,"127":1,"128":4,"129":8,"131":1,"133":2,"141":1,"143":2,"145":1,"152":2,"157":1,"161":1,"171":4,"172":1,"174":3,"175":3,"177":1,"178":7,"189":1,"196":3,"197":4,"232":1,"233":2,"234":3,"236":1,"237":2,"249":1,"257":3,"278":2,"303":1,"306":1,"310":1,"311":1,"329":1,"334":1,"335":1,"341":1,"346":2,"421":1}}],["y",{"1":{"6":2,"9":2,"11":2,"21":2,"34":2,"40":2,"42":1,"59":3,"61":1,"64":7,"67":4,"69":2,"76":4,"77":3,"78":4,"80":9,"81":10,"124":2,"148":3,"149":2,"150":3,"152":6,"161":2,"173":2,"179":1,"188":2,"198":2,"202":1,"215":3,"216":3,"217":1,"221":2,"222":1,"240":2,"241":2,"243":13,"246":1,"262":1,"278":3,"279":1,"280":2,"281":2,"282":2,"286":10,"289":1,"290":1,"323":1,"325":1,"327":1,"331":1,"339":1,"344":6,"345":6,"346":2,"350":1,"368":5,"369":4,"374":2,"375":2,"376":4,"377":4,"395":2,"398":2},"2":{"208":1,"209":2,"241":2,"331":1,"368":1}}],["zz3",{"1":{"287":2}}],["zz2",{"1":{"287":2}}],["zz",{"1":{"281":2,"287":2}}],["z`",{"1":{"241":3,"257":1}}],["z``",{"1":{"22":1,"241":1,"384":1}}],["z>",{"1":{"201":1}}],["zero",{"1":{"58":1,"257":1,"262":1}}],["zy",{"1":{"157":2,"182":2},"2":{"157":1}}],["zy``",{"1":{"157":1}}],["zyz",{"1":{"49":2}}],["zyx",{"1":{"49":2}}],["zx",{"1":{"417":7}}],["zxz",{"1":{"49":2}}],["zxy",{"1":{"49":2}}],["z=wing",{"1":{"395":1,"399":1}}],["z=80",{"1":{"209":2}}],["z=45",{"1":{"188":2}}],["z=3",{"1":{"188":3}}],["z=30",{"1":{"166":1}}],["z=0",{"1":{"173":1,"420":1}}],["z=180",{"1":{"67":1}}],["z=",{"1":{"51":1,"52":1,"420":1}}],["z=true",{"1":{"16":1}}],["z=false",{"1":{"16":1}}],["z",{"1":{"6":1,"9":5,"16":3,"21":3,"25":1,"34":1,"42":2,"52":1,"59":6,"61":2,"63":2,"69":3,"70":4,"72":2,"76":4,"78":2,"80":5,"110":1,"124":1,"143":2,"144":5,"146":1,"151":4,"152":3,"155":3,"156":2,"157":2,"158":1,"160":1,"161":1,"162":2,"163":2,"169":2,"170":1,"173":1,"177":7,"179":1,"182":7,"184":1,"188":2,"193":1,"202":3,"209":1,"215":3,"216":3,"217":1,"221":1,"241":3,"243":1,"246":1,"256":1,"257":2,"262":3,"267":1,"276":2,"278":4,"280":3,"282":2,"284":3,"285":1,"287":2,"289":3,"290":4,"317":1,"339":1,"350":1,"357":3,"368":5,"369":4,"382":2,"384":1,"385":1,"388":1,"389":2,"394":3},"2":{"9":1,"22":1,"208":1,"209":2,"241":2,"368":1,"384":1}}],["ultimately",{"1":{"182":1,"254":1,"262":1,"421":1}}],["url",{"1":{"129":1}}],["uuid1",{"1":{"108":1},"2":{"108":1}}],["uuid",{"1":{"108":4}}],["ui",{"1":{"98":2}}],["uki",{"1":{"85":1}}],["utilizing",{"1":{"419":1}}],["utilized",{"1":{"341":1}}],["utilizes",{"1":{"65":1}}],["utility",{"1":{"273":1}}],["utils",{"1":{"58":1}}],["u",{"1":{"62":10,"289":3}}],["unstable",{"1":{"333":1}}],["unqualified",{"2":{"312":1,"331":2,"333":1}}],["unqualified``",{"1":{"312":1,"331":1}}],["unwanted",{"1":{"296":1}}],["unreachable",{"1":{"276":1}}],["unordered",{"1":{"275":1}}],["unavailable",{"1":{"273":1}}],["unknowns",{"1":{"279":2,"295":2}}],["unknown",{"1":{"268":1,"295":1}}],["unnecessary",{"1":{"253":1}}],["unless",{"1":{"263":1,"278":1}}],["unlike",{"1":{"230":1,"272":1}}],["unlikely",{"1":{"31":1}}],["unlock",{"1":{"229":1,"233":2}}],["unexpectedly",{"1":{"158":1,"333":1}}],["unexpected",{"1":{"144":1}}],["unpredictable",{"1":{"144":1}}],["unpkg",{"1":{"124":1,"396":1,"420":1}}],["until=until",{"1":{"70":2,"171":2,"289":1}}],["until`",{"1":{"49":1,"171":1}}],["until",{"0":{"171":1},"1":{"44":1,"70":1,"91":1,"129":1,"167":1,"171":1,"198":1,"306":1},"2":{"44":1,"49":1,"171":1}}],["unfortunately",{"1":{"34":1,"252":1}}],["underneath",{"1":{"286":1}}],["underlying",{"1":{"209":2,"252":1}}],["understands",{"1":{"263":1}}],["understanding",{"0":{"200":1},"1":{"134":2,"206":1}}],["understand",{"1":{"133":2,"134":1,"135":1,"140":1,"141":1,"197":1,"203":1,"234":1}}],["underside",{"1":{"70":2}}],["under",{"1":{"31":1,"192":1,"206":1,"223":6,"278":3,"388":1}}],["uniform",{"1":{"398":1}}],["unintended",{"1":{"310":1}}],["unionizing",{"1":{"341":1}}],["union",{"1":{"75":3,"77":2,"199":3,"206":1,"230":1},"2":{"230":1}}],["uniquely",{"1":{"272":1}}],["unique",{"1":{"13":1,"19":1,"75":2,"184":1,"335":1}}],["unit=unit",{"1":{"243":1}}],["united",{"1":{"119":1}}],["unit`",{"1":{"49":1,"238":1}}],["units=false",{"1":{"243":1}}],["units",{"0":{"36":1},"1":{"36":4,"243":1}}],["unit",{"0":{"63":1},"1":{"12":1,"63":7,"67":1,"73":3,"109":4,"206":1,"367":2,"368":3,"369":5,"374":2,"375":2,"376":3,"377":3},"2":{"49":1}}],["usability",{"1":{"261":1}}],["usage",{"0":{"16":1,"22":1},"1":{"119":1,"255":2}}],["usually",{"1":{"138":2,"255":1,"310":1,"406":1,"415":1,"417":1,"421":1}}],["using",{"0":{"172":1,"174":1,"201":1,"235":1},"1":{"7":1,"19":1,"20":1,"25":1,"26":1,"27":1,"28":1,"31":1,"39":1,"51":1,"60":1,"61":3,"63":1,"66":2,"67":1,"70":1,"80":2,"87":1,"98":1,"100":2,"112":1,"121":1,"123":1,"128":1,"129":1,"143":2,"145":1,"147":1,"150":1,"153":2,"160":3,"161":1,"164":1,"172":1,"173":3,"178":1,"179":1,"188":3,"193":2,"194":1,"195":1,"210":1,"211":1,"222":1,"230":1,"232":1,"235":3,"236":1,"238":1,"245":4,"246":1,"248":1,"252":1,"255":1,"257":2,"258":1,"268":1,"272":1,"310":1,"326":1,"331":1,"342":1,"347":1,"348":1,"368":1,"369":1,"378":2,"379":3,"382":1,"387":1,"389":1,"415":1,"418":1,"419":2,"420":1}}],["useful",{"1":{"15":1,"19":1,"22":1,"52":1,"135":1,"141":1,"145":1,"146":1,"172":1,"177":1,"257":1,"276":2,"295":2,"306":1,"307":1,"327":1,"328":1,"342":1,"343":1,"404":1,"409":1,"413":2,"414":1,"415":1,"416":1,"417":2,"420":1}}],["uses",{"1":{"15":2,"34":1,"42":1,"64":2,"129":1,"152":2,"176":1,"245":1,"279":1,"295":1,"308":1,"332":1,"350":1,"422":1}}],["used",{"1":{"7":1,"14":1,"19":2,"23":1,"24":2,"25":2,"26":2,"30":1,"32":1,"33":1,"34":1,"36":1,"37":1,"38":2,"53":1,"57":1,"59":1,"61":1,"65":1,"74":1,"77":3,"78":2,"91":1,"97":1,"102":1,"110":2,"111":1,"112":1,"113":2,"119":2,"120":1,"121":2,"122":1,"123":3,"129":2,"133":4,"134":2,"135":2,"138":1,"140":2,"141":1,"143":2,"144":7,"146":1,"148":3,"149":1,"152":2,"155":1,"157":1,"158":1,"165":1,"167":2,"168":1,"169":2,"172":2,"177":1,"178":1,"181":1,"184":2,"192":1,"197":1,"198":2,"201":2,"202":3,"204":2,"206":2,"210":1,"211":1,"218":1,"221":1,"222":3,"238":2,"240":1,"241":1,"243":1,"255":2,"275":1,"276":3,"278":1,"286":3,"299":2,"304":1,"313":1,"318":1,"341":1,"344":1,"350":2,"352":2,"353":1,"354":1,"356":1,"357":2,"368":1,"376":1,"378":1,"420":1}}],["use",{"0":{"144":1,"261":1,"341":1},"1":{"3":1,"7":1,"11":1,"19":1,"25":1,"26":2,"31":2,"34":1,"36":1,"39":2,"50":1,"60":1,"71":1,"77":1,"80":3,"86":1,"90":1,"97":2,"108":1,"121":1,"129":4,"133":1,"135":5,"138":2,"140":2,"141":2,"143":2,"146":2,"147":1,"151":3,"156":2,"162":2,"163":1,"164":2,"169":2,"170":2,"171":1,"174":2,"177":1,"178":3,"192":1,"194":4,"197":1,"199":1,"206":1,"208":1,"211":1,"222":1,"223":1,"233":1,"238":1,"251":1,"258":1,"261":1,"278":1,"292":1,"295":1,"299":3,"308":1,"312":1,"315":1,"322":1,"324":1,"326":1,"341":1,"342":1,"344":1,"347":2,"348":1,"369":1,"371":1,"376":1,"381":1,"382":1,"386":1,"389":1,"406":1,"412":1,"416":1,"420":3}}],["userguide",{"1":{"128":1}}],["user",{"1":{"3":1,"4":1,"5":1,"6":1,"26":1,"39":1,"40":1,"42":1,"53":1,"54":1,"129":1,"133":1,"141":1,"190":1,"192":1,"195":1,"198":1,"202":2,"217":1,"254":1,"255":1,"262":2,"263":4}}],["users",{"1":{"1":1,"7":1,"31":1,"34":1,"99":1,"130":1,"133":1,"134":1,"138":7,"141":2,"197":2,"202":1,"203":1,"206":1,"222":1,"223":1,"229":1,"254":1,"262":1,"291":2,"358":1}}],["upstream",{"1":{"320":1}}],["updating",{"1":{"134":1}}],["updates",{"1":{"194":1,"230":1}}],["update",{"1":{"133":1}}],["upgraded",{"1":{"129":1}}],["upgrade",{"1":{"128":2,"129":1}}],["up``",{"1":{"110":3}}],["upe",{"1":{"82":1}}],["upn",{"1":{"82":1}}],["upwards",{"1":{"233":1,"358":1}}],["upward",{"1":{"80":2}}],["up=",{"1":{"67":1}}],["upon",{"1":{"28":1,"156":1,"255":1}}],["up",{"1":{"6":1,"20":1,"128":1,"133":3,"182":1,"196":1,"243":3,"245":2,"255":1,"256":1,"312":1,"345":1,"420":3},"2":{"110":2,"243":1}}],["1f",{"1":{"278":1,"279":1,"280":1,"290":1}}],["1e6",{"1":{"281":3,"282":3,"283":3,"284":3,"285":3,"286":3,"287":3,"288":3,"289":3,"290":3}}],["1e",{"1":{"68":1,"69":2,"70":1,"72":1,"78":1,"81":1,"278":1}}],["162",{"1":{"288":1}}],["16>`",{"1":{"238":1}}],["169",{"1":{"76":1}}],["168",{"1":{"76":2}}],["16",{"0":{"149":1},"1":{"60":6,"77":2,"80":3,"148":1,"283":6,"284":1,"288":5,"289":2,"290":1,"367":1}}],["167",{"1":{"26":1,"76":2,"222":1}}],["134",{"1":{"76":1}}],["13567",{"1":{"119":1}}],["135",{"1":{"76":1}}],["133",{"1":{"76":1,"285":2}}],["130",{"1":{"287":1}}],["1306",{"1":{"72":1}}],["130326",{"1":{"34":1,"78":2,"124":1}}],["1369",{"1":{"62":2}}],["13",{"0":{"146":1},"1":{"60":5,"65":1,"76":1,"77":1,"145":1,"179":1,"283":2,"286":1,"287":1,"289":1}}],["1d",{"0":{"218":1},"1":{"48":1,"49":3,"58":2,"124":1,"206":3,"218":1,"224":2,"233":1,"235":4,"238":2,"334":1}}],["115",{"1":{"281":3}}],["114",{"1":{"76":1}}],["112",{"1":{"76":1,"278":3}}],["11",{"0":{"144":1,"337":1,"369":1},"1":{"60":9,"63":1,"76":1,"80":1,"143":1,"283":1,"288":1}}],["1138",{"1":{"62":2}}],["113",{"1":{"26":1,"76":1,"222":1}}],["119",{"1":{"14":2}}],["14>`",{"1":{"238":1}}],["149",{"1":{"69":2}}],["14",{"0":{"147":1},"1":{"60":2,"63":2,"146":1,"179":4,"182":1,"283":2,"284":1,"288":6,"299":20}}],["145",{"1":{"26":1,"76":1,"222":1}}],["146",{"1":{"26":1,"76":2,"222":1}}],["179",{"1":{"76":1}}],["174",{"1":{"76":1}}],["170",{"1":{"67":1,"278":2}}],["175",{"1":{"65":2,"420":1}}],["17",{"0":{"150":1},"1":{"26":1,"60":3,"70":6,"76":1,"149":1,"222":1,"278":1,"282":2,"284":1,"289":1,"295":1,"420":1}}],["173",{"1":{"26":1,"76":1,"222":1}}],["12mm",{"1":{"182":1}}],["123",{"1":{"262":1}}],["1234",{"1":{"108":1}}],["123d",{"1":{"67":2}}],["126",{"1":{"76":1}}],["125",{"1":{"76":1,"243":1,"279":4}}],["127",{"1":{"76":1}}],["120°",{"1":{"363":1,"364":1}}],["120",{"1":{"60":1,"76":1}}],["128",{"1":{"26":1,"76":2,"109":1,"119":1,"222":1}}],["1294",{"1":{"279":2}}],["129",{"1":{"21":2}}],["12",{"0":{"145":1},"1":{"19":1,"36":1,"60":8,"65":3,"75":6,"76":2,"80":2,"81":2,"144":1,"149":2,"179":1,"182":6,"281":3,"284":1,"286":2,"289":1,"357":1}}],["122",{"1":{"14":2}}],["1x12",{"1":{"19":2,"360":3}}],["154",{"1":{"278":2}}],["15>`",{"1":{"238":1}}],["158",{"1":{"76":1}}],["151",{"1":{"76":1}}],["151134",{"1":{"59":1}}],["153",{"1":{"67":1}}],["1562",{"1":{"62":2}}],["15",{"0":{"148":1},"1":{"60":9,"61":2,"64":4,"70":2,"76":2,"80":2,"81":2,"147":1,"157":4,"159":2,"173":2,"179":1,"182":1,"243":1,"281":3,"282":2,"284":4,"289":1,"295":1,"357":2}}],["159",{"1":{"21":2}}],["157",{"1":{"14":1}}],["150",{"1":{"14":4}}],["186",{"1":{"76":1}}],["18",{"0":{"151":1},"1":{"26":1,"51":14,"60":9,"70":4,"76":1,"80":1,"150":1,"163":2,"222":1,"281":1,"283":2,"284":1}}],["1873",{"1":{"62":2}}],["187",{"1":{"26":1,"76":1,"222":1}}],["185",{"1":{"26":1,"76":1,"222":1}}],["188",{"1":{"26":4,"76":4,"222":4,"288":3}}],["180°",{"1":{"259":1}}],["180",{"1":{"14":2,"61":2,"77":1,"282":1,"290":2,"299":1,"357":1,"359":1}}],["181",{"1":{"14":2}}],["1960s",{"1":{"102":1}}],["1950s",{"1":{"102":1}}],["194",{"1":{"76":1}}],["197",{"1":{"76":1}}],["190",{"1":{"76":1,"288":2}}],["198",{"1":{"76":8}}],["1915",{"1":{"62":2}}],["19",{"0":{"152":1},"1":{"11":1,"60":7,"151":1,"299":2}}],["1``",{"1":{"10":2,"23":1,"28":1,"30":2,"148":1,"271":1,"298":1,"332":1}}],["1`",{"1":{"5":1}}],["1",{"0":{"142":1,"335":1,"349":1,"367":1,"380":1,"397":1,"404":1},"1":{"5":3,"6":1,"9":5,"11":2,"17":10,"19":1,"23":5,"25":7,"26":4,"28":10,"30":6,"31":16,"34":13,"36":1,"42":5,"49":4,"51":8,"52":4,"55":1,"58":1,"59":4,"60":26,"61":12,"62":39,"63":3,"64":6,"65":7,"66":3,"67":30,"68":14,"69":3,"70":8,"71":4,"72":4,"74":28,"75":57,"76":23,"77":7,"78":27,"80":24,"81":41,"109":4,"118":3,"124":15,"131":14,"143":2,"144":4,"145":3,"146":1,"147":11,"148":17,"149":1,"151":3,"152":7,"155":2,"157":2,"159":3,"160":1,"161":1,"162":2,"163":8,"165":6,"166":1,"167":2,"168":2,"169":2,"170":1,"172":2,"176":2,"177":3,"178":3,"179":1,"182":9,"184":4,"185":2,"186":1,"187":4,"188":18,"189":7,"194":1,"198":8,"202":3,"204":6,"206":34,"208":6,"209":20,"210":1,"211":1,"221":2,"222":4,"238":1,"240":4,"241":2,"243":17,"245":1,"251":7,"256":1,"262":8,"267":1,"270":4,"272":15,"273":4,"276":6,"278":11,"279":4,"280":9,"281":3,"282":6,"283":1,"284":3,"285":1,"286":9,"287":4,"288":1,"289":9,"290":12,"295":2,"298":4,"299":10,"304":4,"307":11,"314":6,"315":1,"316":1,"317":4,"320":2,"331":4,"332":4,"339":1,"344":3,"345":3,"346":2,"350":11,"353":1,"357":5,"359":3,"367":2,"368":4,"369":5,"374":1,"375":1,"376":2,"377":2,"382":2,"384":1,"385":1,"388":1,"389":2,"394":2,"395":5,"396":1,"397":1,"398":2,"399":1,"400":1,"408":1,"413":1,"415":1,"417":8,"420":12,"421":1,"422":1},"2":{"23":1}}],["10°",{"1":{"299":1}}],["107",{"1":{"287":1}}],["1020",{"1":{"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["1028",{"1":{"278":2}}],["1028g",{"1":{"278":1}}],["10g",{"1":{"278":1}}],["10x10x10",{"1":{"201":1}}],["10303",{"1":{"120":1}}],["105",{"1":{"34":1,"76":1,"78":2,"124":1}}],["1000",{"1":{"36":2,"290":2}}],["100",{"1":{"16":3,"19":1,"21":2,"80":1,"109":1,"110":1,"124":1,"156":2,"165":4,"176":2,"188":3,"230":2,"243":6,"278":1,"290":3,"367":1,"396":1,"420":1}}],["10",{"0":{"143":1,"290":1,"336":1,"368":1},"1":{"4":4,"19":4,"32":1,"34":3,"36":1,"60":8,"62":7,"64":6,"65":2,"66":1,"67":1,"68":4,"69":2,"71":1,"72":4,"74":4,"76":7,"78":6,"80":4,"124":3,"142":2,"143":1,"144":2,"145":3,"149":4,"151":2,"152":2,"153":2,"154":2,"155":2,"156":2,"157":2,"158":2,"159":2,"160":2,"161":2,"162":2,"164":2,"165":1,"167":2,"169":2,"170":4,"172":2,"174":2,"177":3,"179":2,"182":1,"184":2,"190":1,"195":6,"198":4,"199":4,"201":15,"208":1,"209":5,"211":1,"230":2,"256":1,"278":2,"282":1,"284":2,"286":4,"287":1,"290":1,"291":1,"299":1,"304":1,"357":1,"395":1,"397":1}}],["vtx2",{"1":{"152":6}}],["vtx2axis",{"1":{"152":4},"2":{"152":1}}],["vtx",{"1":{"152":6},"2":{"152":1}}],["vulnerable",{"1":{"138":1}}],["v=uhumminljic>`",{"1":{"94":1}}],["voneiden",{"1":{"93":2}}],["volumetric",{"1":{"421":1}}],["volumes",{"1":{"17":1}}],["volume",{"1":{"17":7,"33":1,"34":1,"38":1,"49":1,"68":1,"69":16,"70":1,"72":1,"78":2,"81":1,"124":1,"192":1,"206":1,"241":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"421":2}}],["vice",{"1":{"251":1,"354":1}}],["vital",{"1":{"206":1}}],["virtual",{"1":{"135":1,"245":1}}],["video",{"1":{"94":1,"135":1}}],["viable",{"1":{"252":1}}],["via",{"1":{"61":1,"104":1,"148":1,"175":1,"209":3,"272":1,"290":1,"331":1}}],["visit",{"1":{"291":1}}],["visible",{"1":{"53":1,"67":2,"76":4,"110":5,"243":19,"245":1,"304":1,"318":1,"331":1}}],["visibility",{"1":{"53":1}}],["vis",{"1":{"243":12}}],["visualize",{"1":{"181":1,"246":1,"257":1,"337":1}}],["visualizes",{"1":{"93":1}}],["visualizing",{"1":{"139":1,"335":1}}],["visualization",{"1":{"117":1}}],["visualizations",{"1":{"117":1}}],["visually",{"0":{"404":1},"1":{"65":1,"303":1,"344":1}}],["visual",{"1":{"53":1,"94":1,"299":1,"412":1}}],["viewing",{"1":{"420":1}}],["views",{"1":{"243":1,"245":1,"246":1,"248":1,"249":1,"335":1},"2":{"249":1}}],["viewed",{"1":{"187":1,"246":1,"379":1}}],["viewer>",{"1":{"124":1,"396":1,"420":1}}],["viewer>`",{"1":{"94":1,"104":1,"130":1,"181":1,"299":1}}],["viewer",{"0":{"104":1},"1":{"93":1,"94":2,"104":3,"124":3,"130":1,"181":1,"187":1,"255":1,"299":1,"347":2,"369":1,"379":1,"396":3,"420":3}}],["viewers",{"0":{"88":1},"1":{"369":1}}],["viewer``",{"1":{"51":1,"95":1}}],["viewport``",{"1":{"110":1}}],["viewport`",{"1":{"110":1,"245":1}}],["viewport",{"1":{"67":2,"76":1,"110":1,"243":9,"245":1},"2":{"67":1,"76":1,"110":3,"243":3,"245":1}}],["view",{"1":{"42":1,"81":1,"110":2,"138":1,"157":1,"178":2,"243":7,"246":3,"268":1,"335":1},"2":{"243":1}}],["vslot",{"0":{"83":1},"1":{"83":2}}],["vsc",{"1":{"53":1}}],["vscode`",{"1":{"244":1}}],["vscode``",{"1":{"98":1,"379":1}}],["vscode",{"0":{"94":1},"1":{"16":1,"17":1,"34":1,"60":1,"61":1,"63":1,"65":2,"66":1,"68":2,"69":2,"70":2,"72":2,"74":2,"75":1,"76":1,"78":2,"80":1,"81":2,"94":4,"124":1,"130":2,"178":1,"179":1,"181":2,"182":1,"184":2,"243":1,"276":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"295":1,"299":2,"346":1,"347":1,"349":1,"367":1,"380":1,"381":1,"382":1,"385":1,"388":1,"389":1,"395":1,"397":1,"420":1},"2":{"379":1}}],["vs",{"0":{"19":1,"39":1,"98":1,"297":1},"1":{"94":1,"331":1}}],["ve",{"1":{"341":1,"373":1,"377":1,"378":2,"419":1}}],["vent",{"1":{"80":1}}],["vents",{"1":{"80":1},"2":{"80":1}}],["vectorlike`",{"1":{"293":1}}],["vectorlike",{"1":{"243":6},"2":{"49":1,"271":1,"293":1}}],["vector`",{"1":{"49":2,"147":1}}],["vector",{"1":{"28":1,"31":2,"49":7,"55":1,"59":3,"62":4,"67":6,"75":1,"81":8,"123":5,"124":1,"147":1,"148":1,"204":3,"267":2,"278":1,"279":4,"287":1,"295":3,"317":1,"350":1},"2":{"31":1,"49":1,"55":1,"59":1,"62":1,"67":1,"75":1,"81":1,"147":1,"267":1,"278":1,"279":1,"287":1,"295":1,"350":1}}],["vectorized",{"1":{"11":1,"174":1}}],["verify",{"1":{"333":1}}],["versa",{"1":{"251":1,"354":1}}],["versatility",{"1":{"117":1,"140":1}}],["versatile",{"1":{"111":1,"113":1,"123":1,"206":1}}],["versioned",{"1":{"133":1}}],["versions",{"1":{"129":1}}],["version=dev>`",{"1":{"104":1}}],["version",{"1":{"19":1,"39":1,"59":1,"70":2,"128":1,"129":2,"141":6,"278":1}}],["vertex`",{"1":{"49":2,"206":1,"238":1,"293":1}}],["vertex",{"0":{"152":1},"1":{"49":3,"58":1,"75":4,"109":2,"152":4,"199":3,"206":17,"218":1,"238":3,"239":1,"241":1,"259":1,"295":2,"368":2},"2":{"49":1,"58":1,"206":1,"238":1,"239":1,"270":1,"271":1,"293":1,"295":1}}],["vertically",{"1":{"158":1,"369":1}}],["vertical",{"1":{"34":2,"49":1,"78":4,"124":2,"202":1,"262":2,"276":3,"278":1,"281":1,"282":1,"368":1,"374":1},"2":{"202":1,"368":1}}],["vertices`",{"1":{"49":3,"238":1,"266":1}}],["vertices",{"1":{"6":2,"7":1,"46":1,"59":15,"65":2,"67":10,"68":2,"75":21,"76":2,"80":7,"104":1,"112":1,"135":1,"149":2,"152":7,"179":1,"182":3,"190":1,"199":1,"206":4,"233":1,"238":1,"239":1,"240":2,"241":3,"242":1,"243":1,"253":1,"262":2,"272":3,"274":1,"275":4,"276":1,"278":6,"282":1,"286":1,"289":1,"295":1,"344":1,"368":3,"369":1,"420":1,"421":1},"2":{"4":1,"6":1,"7":1,"49":1,"59":1,"65":1,"67":1,"68":1,"75":1,"76":1,"80":1,"143":1,"149":1,"152":1,"179":1,"182":1,"190":1,"238":1,"239":1,"240":1,"241":1,"243":1,"262":1,"266":1,"272":1,"275":1,"278":1,"282":1,"286":1,"289":1,"368":1,"369":1}}],["very",{"1":{"19":1,"53":1,"147":1,"158":1,"160":1,"198":1,"299":1}}],["v",{"1":{"6":4,"59":8,"62":14,"83":2,"240":4,"243":2,"279":2,"295":2}}],["vary",{"1":{"214":1}}],["variation",{"1":{"304":1}}],["variations",{"1":{"139":1,"336":1}}],["variables",{"0":{"195":1},"1":{"7":1,"28":1,"53":1,"172":1,"258":2}}],["variable",{"1":{"3":1,"17":1,"147":1,"152":2,"154":1,"169":2,"178":1,"190":1,"191":1,"195":1,"340":1}}],["various",{"1":{"111":1,"112":1,"113":1,"117":1,"120":1,"123":1,"174":1,"206":3}}],["varies",{"1":{"102":1}}],["vast",{"1":{"140":1}}],["vase",{"0":{"81":1},"1":{"73":3,"80":1,"81":21}}],["value=",{"1":{"108":1}}],["value=blue",{"1":{"108":1}}],["valueerror",{"1":{"75":1},"2":{"75":1,"306":1}}],["value",{"1":{"31":1,"110":1,"182":1,"183":1,"202":1,"221":2,"241":2,"257":1,"259":1,"262":1,"299":1,"310":1,"329":1,"345":1,"363":1,"373":1,"394":1},"2":{"299":1,"345":1}}],["values",{"1":{"5":2,"31":5,"37":1,"40":1,"48":1,"182":1,"210":1,"221":2,"223":1,"241":2,"268":1,"271":1,"295":1,"354":1,"365":1,"368":1,"406":1}}],["valid`",{"1":{"259":1}}],["valid",{"1":{"1":1,"37":1,"62":2,"139":1,"189":1,"241":1,"272":1,"306":3,"311":1,"312":3,"330":1},"2":{"259":1}}],["0°",{"1":{"354":1}}],["04",{"0":{"284":1},"1":{"209":1,"284":1,"291":1}}],["0d",{"1":{"206":1,"238":1}}],["0inch",{"1":{"74":2}}],["0x99a3b9",{"1":{"395":1,"401":1}}],["0x7f94b9592170",{"1":{"206":1}}],["0x7f94b958eeb0",{"1":{"206":1}}],["0x7f94b958eab0",{"1":{"206":1}}],["0x7f94b958ea70",{"1":{"206":1}}],["0x7f94b958ed70",{"1":{"206":1}}],["0x7f94b958ebb0",{"1":{"206":1}}],["0x7f94b958e7b0",{"1":{"206":1}}],["0x7f94b958e770",{"1":{"206":1}}],["0x7f94b958e8b0",{"1":{"206":1}}],["0x7f94b958e630",{"1":{"206":1}}],["0x7f94b958e330",{"1":{"206":1}}],["0x7f94b958e130",{"1":{"206":1}}],["0x7f94b958d670",{"1":{"206":1}}],["0x7f94b958d3b0",{"1":{"206":1}}],["0x7f94b95862f0",{"1":{"206":1}}],["0x7f94b9583db0",{"1":{"206":1}}],["0x7f94b9583770",{"1":{"206":1}}],["0x7f94b9583730",{"1":{"206":1}}],["0x7f94b9583e70",{"1":{"206":3}}],["0x7f94b9583030",{"1":{"206":1}}],["0x7f94b9583a30",{"1":{"206":1}}],["0x7f94b9583bb0",{"1":{"206":2}}],["0x7f94b9583470",{"1":{"206":1}}],["0x7f94b95838b0",{"1":{"206":1}}],["0x7f94b95836b0",{"1":{"206":1}}],["0x7f94b95835f0",{"1":{"206":1}}],["0x7f94c55430f0",{"1":{"206":1}}],["0x7fc9292c3f40",{"1":{"14":2}}],["0x7fc9292c3f70",{"1":{"14":2}}],["0x7fc8ee235310",{"1":{"14":1}}],["0x7fc8ee235760",{"1":{"14":2}}],["0x7fc8ee228460",{"1":{"14":2}}],["0x7fc8ee2188b0",{"1":{"14":2}}],["0x165b3e730f0",{"1":{"131":1}}],["0x165b35a3570",{"1":{"131":1}}],["0x165eb21ee70",{"1":{"131":1}}],["0x165e88218f0",{"1":{"131":1}}],["0x165e8821570",{"1":{"131":1}}],["0x165e77957f0",{"1":{"131":1}}],["0x165e75379f0",{"1":{"131":1}}],["0x165eab056f0",{"1":{"131":1}}],["0x4683ce",{"1":{"80":1}}],["0x4c6377",{"1":{"63":1}}],["099983",{"1":{"417":8}}],["0999996",{"1":{"417":12}}],["09g",{"1":{"282":1}}],["09",{"0":{"289":1},"1":{"60":1,"282":2,"289":1,"291":1}}],["0881",{"1":{"62":2}}],["08",{"0":{"288":1},"1":{"60":1,"285":2,"288":1,"291":1}}],["0771",{"1":{"62":4}}],["07",{"0":{"287":1},"1":{"60":3,"208":1,"287":1,"291":1}}],["06`",{"1":{"238":1}}],["0692",{"1":{"62":2}}],["06",{"0":{"280":1,"286":1},"1":{"60":1,"209":1,"279":1,"280":1,"286":1,"288":2,"291":4}}],["05",{"0":{"285":1},"1":{"60":1,"62":2,"65":2,"67":2,"209":1,"243":1,"276":1,"285":1,"291":1}}],["0380",{"1":{"76":1}}],["0325",{"1":{"62":2}}],["03",{"0":{"283":1},"1":{"59":1,"60":2,"62":1,"209":1,"283":1,"291":1}}],["025",{"1":{"65":2}}],["0271",{"1":{"62":2}}],["02",{"0":{"278":2,"282":1},"1":{"59":1,"62":1,"64":1,"66":1,"81":2,"209":1,"278":2,"280":1,"282":1,"286":2,"290":2,"291":7}}],["0187",{"1":{"62":2}}],["01",{"0":{"281":2,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1},"1":{"59":1,"60":1,"62":1,"64":1,"65":2,"67":1,"73":6,"81":1,"208":1,"281":2,"282":2,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"291":11}}],["001",{"1":{"230":1}}],["00159",{"1":{"76":1}}],["002",{"1":{"62":4}}],["003",{"1":{"62":2}}],["0094",{"1":{"62":2}}],["00000000000001",{"1":{"295":2}}],["000000000000036",{"1":{"204":1}}],["00000000000002",{"1":{"204":1}}],["0000",{"1":{"62":4}}],["00",{"1":{"51":39,"52":9,"198":32,"204":6,"284":1}}],["0``",{"1":{"28":1}}],["0`",{"1":{"5":1,"10":3}}],["0",{"1":{"4":1,"5":5,"6":2,"9":1,"10":1,"11":1,"14":31,"21":17,"23":9,"25":7,"26":2,"28":24,"30":5,"31":6,"32":4,"34":24,"37":2,"42":9,"49":10,"51":29,"52":6,"59":6,"60":12,"61":25,"62":137,"63":1,"65":34,"66":1,"67":72,"68":22,"69":10,"70":26,"71":7,"72":8,"74":34,"75":24,"76":49,"77":20,"78":54,"80":30,"81":29,"108":3,"109":12,"124":24,"128":1,"131":21,"142":6,"143":3,"144":6,"145":13,"147":7,"148":14,"149":7,"150":2,"151":6,"152":16,"153":8,"154":8,"155":8,"156":14,"157":8,"158":9,"160":8,"161":7,"162":4,"163":29,"164":6,"165":28,"166":6,"167":6,"168":6,"169":10,"170":18,"171":2,"172":26,"173":7,"174":8,"175":4,"176":40,"177":6,"179":11,"182":7,"184":9,"185":1,"187":7,"188":13,"198":48,"201":5,"202":1,"204":12,"206":124,"208":3,"209":70,"210":2,"222":3,"224":7,"230":3,"240":3,"241":3,"243":36,"256":4,"262":2,"267":2,"268":1,"276":2,"278":21,"279":9,"280":16,"281":8,"282":8,"283":7,"284":4,"285":2,"286":7,"287":7,"288":5,"289":22,"290":8,"292":1,"295":2,"296":1,"298":3,"299":12,"304":4,"307":17,"311":2,"314":2,"317":3,"319":4,"320":3,"327":1,"331":5,"332":2,"339":3,"340":9,"341":3,"345":3,"346":4,"350":12,"352":3,"353":7,"354":2,"357":7,"358":2,"359":8,"360":6,"367":2,"368":3,"369":3,"374":1,"375":1,"376":1,"377":1,"395":16,"397":4,"398":7,"399":5,"409":1,"417":156,"420":16}}],["5954",{"1":{"62":2}}],["53",{"1":{"60":1,"76":1}}],["55",{"1":{"60":1,"145":3,"279":4,"295":2}}],["550",{"1":{"19":1}}],["51",{"1":{"60":1,"70":1}}],["51938",{"1":{"19":1}}],["5835",{"1":{"62":2}}],["58",{"1":{"60":2}}],["56",{"1":{"60":1,"278":2}}],["5``",{"1":{"28":1,"30":1}}],["57",{"1":{"26":1,"60":1,"63":1,"76":1,"222":1,"285":2,"299":1}}],["526",{"1":{"278":1}}],["5235",{"1":{"62":2}}],["52",{"1":{"26":1,"60":2,"76":1,"109":1,"222":1,"278":3,"287":2}}],["54",{"1":{"16":3,"21":1,"60":3}}],["50vh",{"1":{"124":1,"396":1,"420":1}}],["500",{"1":{"66":1}}],["5071",{"1":{"62":2}}],["50",{"1":{"14":4,"42":1,"60":1,"71":1,"76":1,"81":4,"108":2,"110":1,"145":2,"156":2,"159":2,"171":2,"179":2,"182":2,"198":16,"204":2,"279":2,"281":3,"290":1,"295":1,"299":2,"336":1,"346":1}}],["5",{"0":{"173":1,"341":1,"359":1,"373":1,"388":1,"401":1},"1":{"4":2,"19":1,"28":3,"30":4,"31":3,"34":1,"59":1,"60":4,"61":8,"62":4,"63":3,"64":8,"65":4,"67":19,"68":6,"69":6,"70":11,"71":2,"72":5,"74":2,"75":1,"76":15,"77":6,"78":2,"80":14,"81":12,"108":2,"124":1,"131":12,"144":1,"151":2,"152":2,"157":2,"166":2,"168":2,"172":3,"173":2,"175":2,"178":1,"179":2,"182":1,"185":1,"187":4,"193":2,"206":22,"209":2,"211":3,"230":4,"241":2,"243":5,"245":1,"256":1,"272":14,"273":6,"278":2,"280":14,"281":1,"283":2,"284":2,"287":2,"289":2,"299":3,"307":2,"314":4,"315":1,"317":1,"336":2,"346":2,"350":4,"357":1,"358":1,"367":1,"395":1,"397":1,"408":1,"413":1,"417":6,"420":6}}],["4b",{"0":{"387":1}}],["4a",{"0":{"358":1,"386":1}}],["4>`",{"1":{"238":1}}],["47",{"1":{"60":1,"63":1,"70":2,"76":1}}],["469",{"1":{"69":2}}],["46",{"1":{"60":6,"290":3}}],["414",{"1":{"287":1}}],["41",{"1":{"60":3,"62":4,"76":1}}],["4865",{"1":{"62":2}}],["48",{"1":{"60":2,"76":1,"282":2}}],["42sol",{"1":{"73":1}}],["42",{"1":{"59":1,"60":1,"76":1,"94":1,"130":1,"181":1,"281":2,"282":2,"286":1,"299":1}}],["44",{"1":{"51":14,"60":4,"286":1}}],["43",{"1":{"51":14,"60":7,"282":3}}],["45",{"1":{"42":1,"60":7,"61":2,"81":1,"173":2,"188":3,"210":1,"262":1,"285":2,"286":1,"287":1,"289":4,"317":1}}],["49",{"1":{"26":1,"34":1,"48":2,"60":1,"76":1,"78":2,"124":1,"222":1,"282":1}}],["400026",{"1":{"417":8}}],["40s",{"1":{"184":1}}],["40",{"1":{"11":1,"14":1,"34":1,"37":1,"42":4,"60":1,"62":8,"70":2,"76":2,"78":2,"81":2,"124":1,"145":2,"146":2,"147":2,"148":2,"165":4,"182":1,"204":2,"209":7,"278":4,"282":3,"288":9,"290":1,"350":2,"357":1,"359":1,"420":1}}],["4",{"0":{"172":1,"340":1,"357":1,"372":1,"385":1,"400":1},"1":{"4":3,"11":5,"28":1,"31":1,"36":1,"51":3,"60":2,"61":2,"62":2,"63":1,"65":4,"70":10,"71":1,"74":2,"75":6,"76":4,"80":5,"143":2,"144":4,"146":2,"149":2,"151":2,"156":8,"161":2,"162":2,"164":1,"165":2,"166":2,"167":2,"168":2,"169":2,"178":1,"179":1,"182":1,"189":1,"204":3,"209":10,"211":1,"218":1,"230":6,"245":1,"275":2,"278":1,"279":2,"280":6,"281":1,"282":1,"284":2,"285":2,"286":1,"287":1,"295":2,"299":1,"304":1,"315":1,"357":2,"367":2,"395":1,"396":1,"397":1,"408":1,"413":1,"417":48,"420":2}}],["lc1",{"1":{"282":4}}],["lb",{"1":{"280":1}}],["lbs",{"1":{"280":2}}],["lbrace`",{"1":{"9":2,"10":3}}],["lh",{"1":{"279":3,"295":1}}],["l8",{"1":{"279":2,"290":1,"295":1}}],["l8y",{"1":{"279":1,"295":1}}],["l8x",{"1":{"279":1,"295":1}}],["luckily",{"1":{"253":1}}],["ln2",{"1":{"170":4}}],["ln29",{"1":{"163":4}}],["ln``",{"1":{"147":2}}],["ln",{"1":{"145":1,"147":3,"148":6,"157":1,"163":2,"165":3,"170":4,"172":1,"176":6},"2":{"147":1}}],["l7",{"1":{"62":5,"74":4,"290":2}}],["lshift",{"1":{"58":1}}],["lt",{"1":{"58":1}}],["l4",{"1":{"30":1,"31":1,"62":9,"65":2,"74":3,"81":11,"145":3,"148":9,"172":1,"182":2,"279":1,"290":1,"299":3,"331":1,"350":2,"420":2},"2":{"148":1,"420":1}}],["l09",{"1":{"60":2}}],["l08",{"1":{"60":2}}],["l07",{"1":{"60":2}}],["l06",{"1":{"60":2}}],["l05",{"1":{"60":2}}],["l04",{"1":{"60":2}}],["l03",{"1":{"60":2}}],["l02",{"1":{"60":2}}],["l01",{"1":{"60":2}}],["l00",{"1":{"60":3}}],["l0",{"1":{"26":2,"76":3,"165":1,"222":2}}],["l3",{"1":{"25":1,"30":3,"31":3,"62":7,"65":2,"71":1,"74":3,"81":7,"145":4,"147":3,"148":8,"163":3,"172":1,"243":4,"278":1,"279":2,"281":1,"290":3,"299":3,"307":1,"331":1,"350":2,"420":7},"2":{"30":1,"147":1,"420":1}}],["l2",{"1":{"25":2,"28":3,"30":2,"31":2,"62":7,"65":7,"67":11,"71":1,"74":3,"81":7,"145":4,"147":7,"148":8,"157":3,"163":7,"172":1,"243":4,"278":2,"279":2,"281":2,"290":4,"298":1,"299":2,"307":2,"317":1,"331":3,"332":1,"350":2,"420":7},"2":{"28":1,"30":1,"331":1}}],["l2``",{"1":{"9":1}}],["lego",{"0":{"366":1},"1":{"366":2,"367":5,"368":6,"369":14,"370":2,"371":3,"372":3,"373":2,"374":4,"375":3,"376":4,"377":3,"422":1},"2":{"370":1}}],["legal",{"1":{"49":1}}],["lesson",{"1":{"417":1}}],["less",{"1":{"134":2,"230":1,"236":2,"253":1,"310":1,"415":1}}],["led",{"1":{"117":1}}],["ledger",{"1":{"49":1}}],["len",{"1":{"59":1,"69":1,"271":1,"276":2}}],["lengthwise",{"1":{"368":1,"369":1,"374":1,"375":1,"376":1,"377":1}}],["length``",{"1":{"271":1}}],["length+2",{"1":{"230":3}}],["lengths",{"1":{"220":1,"286":1,"294":1,"295":1,"398":1,"399":1}}],["length=block",{"1":{"368":1,"369":1}}],["length=c1",{"1":{"307":2}}],["length=c",{"1":{"299":1}}],["length=left",{"1":{"290":1}}],["length=65",{"1":{"278":1}}],["length=12",{"1":{"356":2}}],["length=1",{"1":{"256":1,"317":1}}],["length=20",{"1":{"179":1}}],["length=a",{"1":{"151":1}}],["length=4",{"1":{"144":1,"177":2}}],["length=hookx",{"1":{"74":2}}],["length=topx",{"1":{"74":4}}],["lengthmode",{"2":{"49":1}}],["lengthmode`",{"1":{"49":1}}],["length",{"1":{"24":1,"28":3,"30":3,"31":2,"32":2,"37":1,"49":2,"59":1,"61":2,"64":2,"67":12,"69":8,"75":1,"76":7,"77":11,"139":1,"142":4,"143":3,"144":6,"149":11,"151":4,"152":2,"153":4,"154":4,"155":4,"156":6,"158":12,"160":4,"161":4,"164":4,"169":4,"170":6,"172":10,"177":4,"218":2,"219":1,"220":1,"230":2,"241":1,"243":2,"256":3,"265":1,"272":1,"273":1,"278":1,"280":2,"281":1,"282":1,"290":2,"292":1,"296":1,"311":1,"319":1,"320":2,"336":1,"340":6,"341":2,"345":1,"346":3,"350":7,"352":1,"353":1,"367":2,"368":4,"369":4,"372":1,"373":1,"374":2,"375":3,"376":3,"377":3},"2":{"28":1,"77":1,"271":1,"350":1}}],["leftover",{"1":{"405":1}}],["leftovers",{"0":{"405":1},"1":{"404":1,"408":1,"410":1,"413":1},"2":{"405":1,"408":1,"410":1,"412":1}}],["left",{"1":{"49":2,"67":6,"221":1,"257":2,"272":1,"290":3,"304":1,"312":1,"331":2,"340":3,"341":1,"346":1,"420":11}}],["lets",{"1":{"267":1}}],["lettering",{"1":{"119":1}}],["letter",{"1":{"49":1}}],["let",{"1":{"42":1,"48":1,"256":1,"303":1,"306":1,"357":1,"382":1}}],["learn",{"1":{"140":1,"178":1}}],["learning",{"1":{"80":1,"140":2}}],["leading",{"1":{"395":16,"396":1,"397":9,"398":4,"399":3,"400":3}}],["lead",{"1":{"134":1,"229":1}}],["leaving",{"1":{"70":2,"78":1,"368":1,"369":1,"375":1,"376":1,"377":1}}],["leave",{"1":{"61":1,"257":1,"375":1}}],["leaves",{"0":{"356":1},"1":{"350":2,"353":1,"354":1,"356":1},"2":{"20":1}}],["least",{"1":{"49":1,"275":1,"367":1}}],["leaf``",{"1":{"20":1}}],["leaf",{"0":{"351":1,"352":1},"1":{"20":2,"62":15,"350":9,"351":1,"352":5,"353":7,"354":1,"355":1,"357":2,"359":1,"362":3,"363":2,"364":1},"2":{"20":1,"362":1}}],["leveraging",{"1":{"93":1,"230":1,"237":1}}],["leverages",{"1":{"334":1}}],["leverage",{"1":{"11":1,"233":1,"310":1}}],["levels",{"1":{"140":1}}],["levelname",{"1":{"51":1}}],["level=logging",{"1":{"51":1}}],["level",{"1":{"17":1,"95":1,"140":4,"417":1,"421":2}}],["ll",{"1":{"12":1,"13":1,"234":1,"334":1,"335":1,"339":2,"345":1,"367":1,"368":4,"369":1,"370":1,"371":3,"381":1,"382":2,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"392":1,"393":1,"394":1,"420":6}}],["l19",{"1":{"60":1}}],["l18",{"1":{"60":2}}],["l17",{"1":{"60":2}}],["l16",{"1":{"60":2}}],["l15",{"1":{"60":2}}],["l14",{"1":{"60":2}}],["l13",{"1":{"60":2}}],["l12",{"1":{"60":2}}],["l11",{"1":{"60":2}}],["l10",{"1":{"60":2}}],["l1",{"1":{"25":3,"28":13,"30":4,"31":4,"62":5,"65":7,"67":18,"71":2,"74":5,"81":7,"145":5,"147":3,"148":8,"157":7,"163":5,"165":1,"172":1,"243":4,"278":4,"279":4,"280":3,"281":2,"282":1,"288":3,"289":3,"290":3,"298":3,"299":2,"307":2,"317":1,"331":3,"332":1,"350":4,"420":9},"2":{"9":1,"28":1,"31":1,"298":1,"332":1,"420":1}}],["l^",{"1":{"9":1}}],["l`",{"1":{"9":6}}],["l",{"1":{"9":17,"69":6,"163":6,"176":3,"198":2,"286":1},"2":{"299":1}}],["law",{"1":{"278":1}}],["language>`",{"1":{"255":1}}],["language",{"0":{"140":1},"1":{"140":7,"255":1,"278":1}}],["languages",{"1":{"133":3,"140":1}}],["land",{"1":{"9":2}}],["laser",{"1":{"124":1}}],["lastly",{"1":{"144":2}}],["last``",{"1":{"143":1,"171":1,"272":3}}],["last",{"0":{"4":1,"143":1},"1":{"4":3,"34":1,"49":2,"67":2,"81":1,"143":3,"144":5,"146":1,"152":1,"158":1,"160":1,"161":1,"163":2,"169":1,"170":1,"182":2,"193":1,"199":2,"241":1,"270":5,"272":12,"275":1,"280":1,"344":1,"345":1,"350":1,"361":1,"365":1,"384":1,"394":1,"395":1,"397":1},"2":{"143":1,"171":1,"272":1}}],["launchplatform",{"1":{"90":1,"91":1}}],["laptop",{"1":{"66":1}}],["largest",{"0":{"393":1},"1":{"392":1}}],["large",{"1":{"66":1,"99":1,"100":1,"135":4,"138":3,"140":3,"176":1,"236":1,"310":1,"405":2,"416":1}}],["larger",{"1":{"19":1,"62":2,"138":2,"240":1,"255":2}}],["layers",{"1":{"113":1,"119":2,"123":2,"243":1}}],["layer=",{"1":{"76":2,"110":2,"243":5}}],["layer=str",{"1":{"67":1}}],["layer",{"1":{"54":1,"67":2,"76":2,"110":2,"128":1,"243":3,"245":1},"2":{"67":1,"76":1,"110":1,"243":1}}],["layout",{"1":{"15":1,"18":1}}],["latch",{"1":{"182":15}}],["later",{"1":{"61":1,"80":1,"134":1,"146":1,"162":2,"172":1,"299":1,"336":1,"339":1,"371":1,"422":1}}],["latest",{"1":{"20":1,"84":1,"97":2,"124":2,"128":2,"129":3,"178":1,"251":1}}],["lathe",{"3":{"34":1,"38":1,"49":1,"60":1,"71":1,"78":1,"81":1,"124":1,"147":1,"157":1,"171":1,"179":1,"182":1,"238":1,"239":1,"250":1,"282":1,"290":1,"342":1}}],["labeled",{"1":{"299":3}}],["label=",{"1":{"14":1,"17":3,"109":4,"184":3,"352":1,"353":1,"354":1}}],["label",{"1":{"13":5,"61":14,"71":4,"108":2,"181":1,"243":1,"352":1},"2":{"13":1,"184":1}}],["labels",{"0":{"13":1},"1":{"13":2,"61":2,"65":1,"178":1,"184":1,"245":1,"249":1}}],["lazy",{"1":{"11":1}}],["lambda",{"1":{"6":1,"230":2,"240":3,"267":2,"272":1,"273":1},"2":{"271":1}}],["light",{"0":{"290":1},"1":{"262":1,"290":1,"291":1}}],["lightweight",{"1":{"91":1}}],["lies",{"1":{"312":1,"329":1}}],["lie",{"1":{"147":1,"324":1,"329":1,"406":1}}],["licenses",{"1":{"278":1}}],["license",{"1":{"138":2,"278":9}}],["licensed",{"1":{"138":1,"278":1}}],["licensing",{"1":{"138":2}}],["libraries",{"0":{"89":1,"96":1},"1":{"89":1,"140":4,"255":1}}],["library",{"0":{"91":1},"1":{"65":1,"83":1,"87":2,"90":1,"91":4,"93":1,"255":2},"2":{"91":1}}],["limiting",{"1":{"306":1}}],["limits",{"1":{"179":1,"182":3,"307":1,"353":1}}],["limit",{"1":{"131":1,"306":2,"354":1}}],["limited",{"1":{"69":1,"138":1,"202":1,"255":2,"310":1}}],["limitations",{"1":{"13":1,"111":1,"122":1,"236":1,"278":1},"2":{"13":1}}],["little",{"1":{"62":2,"182":1}}],["literal",{"1":{"54":1,"75":3,"76":5}}],["live",{"1":{"61":1,"255":1}}],["links",{"1":{"133":1,"261":1}}],["link",{"1":{"73":44,"92":1,"202":1,"264":8,"265":6,"266":12,"291":26}}],["link>`",{"1":{"40":1}}],["linux",{"1":{"66":1,"129":1,"140":1}}],["line3``",{"1":{"172":1}}],["line3",{"1":{"172":1}}],["line2",{"1":{"172":2}}],["line1",{"1":{"172":1},"2":{"172":1}}],["linetype`",{"1":{"119":1}}],["linetype",{"0":{"119":1},"2":{"119":1}}],["lineno",{"1":{"51":1}}],["line`",{"1":{"49":1,"157":1,"218":1}}],["line``",{"1":{"23":1,"194":2}}],["linearjoint",{"1":{"182":2,"184":1},"2":{"180":1,"181":1,"182":1}}],["linearjoint`",{"1":{"180":1,"181":1,"182":1}}],["linear",{"0":{"182":1},"1":{"36":1,"83":1,"182":1,"276":1,"306":1,"353":1,"354":1}}],["lines``",{"1":{"406":1,"408":1,"410":1,"414":1}}],["lines",{"0":{"172":1},"1":{"34":1,"48":1,"62":1,"65":1,"67":12,"78":2,"113":1,"124":2,"128":1,"148":1,"172":4,"176":1,"178":2,"182":1,"218":1,"219":1,"223":1,"238":2,"243":12,"299":1,"304":1,"306":1,"307":1,"310":1,"321":3,"323":3,"325":3,"334":1,"340":1,"344":1,"371":1,"406":1,"410":2,"420":1},"2":{"340":1,"406":1,"408":1,"410":1,"414":1}}],["line",{"0":{"147":1},"1":{"4":1,"5":1,"23":3,"25":1,"26":3,"28":6,"29":1,"30":7,"31":4,"34":2,"47":1,"48":1,"49":2,"62":2,"65":4,"67":30,"68":10,"73":1,"74":4,"76":4,"78":1,"81":3,"90":1,"91":1,"110":3,"113":1,"119":10,"124":1,"131":1,"141":2,"145":6,"147":5,"148":13,"157":2,"163":5,"165":1,"170":1,"172":11,"176":1,"178":1,"191":3,"218":14,"219":3,"222":2,"225":1,"238":1,"241":1,"243":3,"278":11,"279":4,"281":2,"282":4,"286":4,"289":2,"290":5,"295":2,"298":3,"299":3,"307":2,"324":1,"329":6,"331":2,"332":2,"340":2,"344":1,"345":1,"350":4,"362":1,"369":1,"420":4},"2":{"23":2,"25":1,"26":2,"28":1,"30":1,"31":1,"48":1,"49":1,"62":1,"65":1,"67":1,"74":1,"76":1,"81":1,"145":1,"147":1,"148":1,"157":1,"163":1,"172":1,"218":1,"222":1,"225":1,"278":1,"279":2,"281":1,"286":1,"289":1,"290":2,"295":1,"298":1,"299":1,"307":1,"332":1,"350":1,"420":2}}],["lid",{"0":{"359":1,"364":1},"1":{"13":2,"14":3,"76":7,"348":1,"350":1,"352":1,"356":1,"359":6,"364":4},"2":{"364":1}}],["listing",{"0":{"395":1}}],["listed",{"1":{"276":1,"352":1},"2":{"276":1}}],["listen",{"1":{"92":1}}],["list",{"0":{"393":1},"1":{"11":1,"26":1,"66":1,"69":1,"144":1,"146":1,"162":1,"167":1,"174":2,"175":1,"177":2,"178":1,"240":1,"241":1,"267":2,"268":5,"269":1,"275":3,"345":2,"368":2,"378":2,"384":2,"393":2,"414":3,"420":1}}],["lists",{"0":{"6":1,"174":1},"1":{"6":1,"110":1,"124":1,"139":1,"177":1,"243":1}}],["likelihood",{"1":{"236":1}}],["likely",{"1":{"128":1,"134":1,"178":1,"253":1,"259":1,"262":1,"408":1,"414":1,"415":1}}],["likewise",{"1":{"190":1}}],["like",{"1":{"11":1,"26":1,"34":1,"36":2,"38":1,"42":1,"53":1,"78":1,"80":1,"111":1,"112":1,"122":1,"133":3,"137":2,"141":6,"158":1,"175":1,"180":1,"183":1,"192":1,"195":1,"197":1,"200":1,"201":1,"204":1,"206":5,"230":3,"231":1,"233":1,"234":1,"236":1,"250":3,"255":3,"256":1,"261":1,"268":1,"306":1,"345":1,"354":1,"359":1,"363":1,"374":1,"378":1,"388":2,"390":1,"394":1,"417":1,"421":1}}],["l6",{"1":{"5":5,"62":9,"74":3,"290":1,"299":1},"2":{"5":1}}],["l5",{"1":{"5":5,"62":11,"74":3,"81":9,"148":4,"290":1,"299":2,"350":2},"2":{"5":1}}],["load",{"1":{"245":1,"416":1}}],["loading",{"1":{"117":1}}],["long``",{"1":{"315":1}}],["long",{"1":{"230":1,"255":1,"270":1,"307":1,"315":1,"403":1},"2":{"315":1}}],["longer",{"1":{"22":1,"66":1,"377":1}}],["longest",{"1":{"20":1,"320":1}}],["lot",{"1":{"139":2,"140":1}}],["lots",{"1":{"11":1}}],["loss",{"1":{"123":1,"141":1}}],["lowest",{"1":{"334":1,"345":2}}],["lower",{"1":{"229":1,"231":1,"233":1,"234":1,"237":1}}],["low",{"1":{"59":4,"95":1,"140":1}}],["logical",{"1":{"339":1,"346":1}}],["logic",{"1":{"124":1,"318":1}}],["logos",{"1":{"123":1}}],["logo",{"0":{"67":1},"1":{"61":1,"67":21,"73":3},"2":{"67":1}}],["logs",{"1":{"51":2,"99":1}}],["logger",{"1":{"51":3}}],["logging",{"0":{"50":1,"51":1},"1":{"0":1,"51":5}}],["log",{"1":{"51":4},"2":{"51":1}}],["lofting",{"1":{"72":1,"229":1,"235":1,"236":1}}],["loft",{"0":{"72":1,"158":1},"1":{"71":1,"72":3,"73":3,"158":4,"239":1,"285":2},"2":{"49":1,"72":1,"158":1,"190":1,"238":1,"239":1,"252":1,"285":1}}],["loft`",{"1":{"49":1,"158":1,"238":1,"252":1}}],["looks",{"1":{"363":1,"374":1,"376":1,"388":1}}],["lookup",{"1":{"75":2}}],["look",{"1":{"67":1,"133":2,"243":1,"338":1,"350":1,"404":1},"2":{"110":2}}],["looking",{"1":{"39":1,"243":3,"246":1,"344":1,"391":1}}],["looped",{"1":{"17":1}}],["loop",{"0":{"167":1,"168":1},"1":{"11":1,"167":2,"206":1,"401":1}}],["loops",{"1":{"7":1,"144":1,"174":1,"175":1,"421":1}}],["looping",{"1":{"7":1,"162":1}}],["locus",{"1":{"315":2}}],["lock",{"1":{"28":1}}],["locally",{"1":{"90":1,"91":1},"2":{"91":1}}],["locals",{"1":{"81":2},"2":{"81":1}}],["local``",{"1":{"39":1,"262":1}}],["localized",{"1":{"31":2}}],["local",{"0":{"39":1},"1":{"19":2,"31":2,"39":4,"42":2,"61":4,"76":1,"188":1,"198":1,"202":2,"209":2,"244":1,"262":1,"263":1,"299":1,"304":1,"306":1,"307":1,"310":1,"329":1,"345":2},"2":{"39":2,"262":1}}],["locating",{"0":{"40":1,"152":1,"162":1},"1":{"146":1}}],["location=",{"1":{"184":1}}],["location=path",{"1":{"184":2}}],["location=location",{"1":{"80":2,"179":2,"182":1,"299":1,"352":1,"353":2,"357":1,"359":1}}],["locationencoder",{"1":{"55":1},"2":{"55":1}}],["locationlist",{"1":{"51":2}}],["location``",{"1":{"184":1,"352":1}}],["location`",{"1":{"49":7,"184":1,"204":2,"217":1,"306":1,"347":1,"352":1,"358":2}}],["locations`",{"1":{"40":1,"49":1,"146":1,"152":2,"173":1,"174":1,"211":1}}],["locations",{"0":{"9":1,"45":1,"166":1,"198":1,"201":1},"1":{"9":2,"11":1,"19":2,"31":1,"34":1,"40":5,"42":1,"45":1,"60":2,"61":1,"63":2,"64":2,"66":1,"67":4,"69":10,"70":1,"76":7,"77":3,"78":1,"80":3,"124":2,"146":1,"152":1,"157":1,"162":1,"166":1,"168":1,"171":1,"173":2,"174":3,"175":3,"179":2,"182":2,"184":2,"185":1,"189":1,"198":6,"201":1,"204":1,"211":3,"224":2,"262":2,"278":1,"279":2,"280":4,"281":4,"282":2,"283":6,"284":3,"286":3,"287":1,"288":4,"289":4,"345":4,"346":1,"350":5,"354":2,"357":2,"359":1,"368":1,"369":2,"376":1,"414":1},"2":{"34":1,"40":1,"49":1,"60":1,"63":1,"64":1,"67":1,"69":1,"70":1,"76":1,"78":1,"80":1,"124":1,"146":1,"152":1,"157":1,"162":1,"168":1,"171":1,"173":1,"174":1,"175":1,"179":1,"182":1,"189":1,"198":1,"201":1,"211":1,"218":1,"224":1,"238":1,"262":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"286":1,"287":1,"288":1,"289":1,"345":1,"346":1,"350":1,"357":1,"359":1,"368":1,"369":1}}],["location",{"0":{"9":1,"204":1,"207":1},"1":{"0":1,"9":4,"14":11,"19":1,"40":1,"49":3,"52":1,"55":1,"61":5,"66":1,"68":3,"70":1,"76":1,"77":4,"78":2,"108":1,"110":1,"144":1,"146":1,"175":1,"182":1,"184":5,"188":8,"189":2,"198":11,"201":1,"202":2,"204":12,"208":11,"209":32,"210":3,"211":2,"212":1,"213":4,"243":1,"286":1,"345":2,"353":1,"354":3,"358":1,"360":1,"369":1,"374":2,"376":1},"2":{"9":1,"14":1,"49":2,"55":1,"61":2,"70":1,"76":1,"77":1,"80":1,"108":1,"144":1,"179":1,"182":1,"184":3,"188":2,"189":1,"198":2,"201":1,"204":3,"208":2,"209":3,"211":1,"217":1,"286":1,"299":1,"306":1,"345":1,"347":1,"352":2,"353":1,"357":1,"358":1,"359":1,"360":1}}],["locate`",{"1":{"204":1}}],["located`",{"1":{"204":1}}],["located",{"1":{"24":1,"33":1,"38":1,"188":1,"213":1,"221":1,"262":1,"345":2},"2":{"204":1,"213":1}}],["locate",{"1":{"9":2,"19":2,"61":2,"144":2,"169":1,"208":2,"213":1,"277":1,"347":1,"382":1},"2":{"19":1,"61":1,"204":1,"208":1,"213":1}}],["locs",{"1":{"19":4,"66":2,"168":2,"198":2}}],["loc",{"1":{"11":10,"19":4,"61":3,"64":2,"65":2,"76":1,"77":2,"144":2,"149":2,"156":2,"168":6,"174":2,"175":2,"208":3,"209":25,"350":2},"2":{"209":1}}],["hybrid",{"1":{"310":1}}],["hyperbolic",{"1":{"218":2}}],["hyperboliccenterarc`",{"1":{"49":1,"218":1,"306":1,"307":1,"310":1}}],["hyperboliccenterarc",{"1":{"225":1,"307":1},"2":{"10":1,"49":1,"218":1,"225":1,"306":1,"307":1,"310":1}}],["hyperbola",{"1":{"49":1,"241":1,"307":1}}],["h4",{"1":{"284":4}}],["h3",{"1":{"284":2}}],["h2",{"1":{"278":1,"284":2}}],["h1",{"1":{"278":2,"284":2,"307":1}}],["hub",{"0":{"287":1},"1":{"287":1,"291":1}}],["hundreds",{"1":{"261":1}}],["huge",{"1":{"261":1}}],["human",{"1":{"113":1,"413":1}}],["hulls",{"1":{"421":1}}],["hull",{"1":{"63":1,"75":3,"179":1,"233":1,"235":2,"238":1,"239":1,"279":3},"2":{"26":1,"49":1,"63":1,"179":1,"238":1,"239":1,"279":1,"310":1}}],["hull`",{"1":{"26":1,"49":1,"238":1,"310":1}}],["http",{"1":{"278":1}}],["https",{"1":{"59":1,"70":1,"124":1,"128":1,"396":1,"420":1}}],["html>`",{"1":{"84":1,"128":1,"178":1,"251":1}}],["html",{"1":{"70":1,"97":2,"124":1,"133":1,"396":1,"420":1}}],["h",{"1":{"63":2,"163":3,"176":18,"243":2}}],["hierarchy",{"1":{"421":1}}],["hierarchical",{"1":{"80":1,"206":1}}],["history",{"1":{"139":1,"141":1}}],["hint",{"1":{"201":1}}],["hints",{"0":{"414":1},"1":{"124":1}}],["hinges",{"1":{"365":1}}],["hinged",{"1":{"348":1}}],["hinge",{"0":{"350":1,"351":1,"353":1,"356":1,"362":1,"363":2,"364":1,"365":1},"1":{"13":4,"14":10,"180":1,"181":1,"183":1,"347":1,"350":18,"351":2,"352":1,"353":4,"355":1,"356":6,"357":7,"359":2,"360":1,"362":4,"363":7,"364":2,"365":2},"2":{"350":1,"356":1,"362":2,"364":1}}],["hidden",{"1":{"67":1,"76":5,"110":6,"243":12,"245":1,"256":1,"264":1,"265":1,"266":1}}],["hide",{"1":{"34":1}}],["higher",{"1":{"134":1,"256":1,"310":1,"417":1,"421":1}}],["highest",{"1":{"80":1,"177":1,"331":1,"345":1}}],["highly",{"1":{"75":1,"120":1,"128":1,"157":1}}],["highlighted",{"1":{"42":1,"182":1}}],["high",{"1":{"27":1,"61":1,"140":3,"230":1,"310":1,"329":1}}],["host",{"1":{"291":1}}],["hot",{"1":{"104":1}}],["hookx",{"1":{"74":2}}],["hookd",{"1":{"74":2}}],["hooks",{"1":{"74":1}}],["hook",{"0":{"74":1},"1":{"72":1,"73":3,"74":5}}],["hour",{"1":{"65":6,"198":1}}],["housing",{"1":{"63":3}}],["house",{"1":{"42":1}}],["how",{"0":{"194":1,"245":1},"1":{"34":1,"42":3,"53":1,"59":1,"60":1,"80":1,"91":1,"134":2,"178":1,"179":1,"181":1,"182":2,"184":2,"192":1,"194":1,"196":1,"206":1,"221":1,"223":1,"234":1,"248":1,"263":1,"303":2,"304":1,"310":1,"318":1,"354":1,"357":1,"364":1,"373":1,"377":1,"417":1}}],["however",{"1":{"19":2,"36":1,"50":1,"129":1,"184":1,"190":1,"192":1,"197":1,"201":1,"202":1,"233":1,"241":1,"263":2,"267":1}}],["horizontal",{"1":{"28":1,"49":1,"279":1,"290":1,"295":1,"374":2}}],["hold",{"1":{"206":1,"376":1}}],["holds",{"1":{"10":1,"17":1}}],["hollowed",{"1":{"78":1,"373":1}}],["hollow",{"0":{"376":1},"1":{"34":1,"42":1,"70":2,"78":2,"81":2,"124":1,"368":1,"369":1,"373":1,"376":2,"377":1},"3":{"34":1,"42":1,"49":1,"52":1,"61":1,"62":1,"71":1,"72":1,"76":1,"78":1,"80":1,"81":1,"124":1,"149":1,"152":1,"154":1,"158":1,"159":1,"160":1,"161":1,"163":1,"182":1,"238":1,"239":1,"241":1,"243":1,"278":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"287":1,"290":1,"310":1,"313":1,"314":1,"340":1,"341":1,"346":1,"357":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"406":1,"417":1,"419":1,"420":1}}],["hole1",{"1":{"350":1}}],["hole0",{"1":{"350":1}}],["hole2",{"1":{"180":1,"350":1,"365":1}}],["hole`",{"1":{"49":1,"143":2,"220":1}}],["hole``",{"1":{"37":1}}],["holes",{"0":{"64":1,"66":1},"1":{"11":5,"61":4,"64":1,"65":1,"66":8,"73":4,"76":2,"84":1,"135":1,"146":1,"156":2,"162":2,"240":2,"256":1,"345":4,"350":2,"354":1,"420":1},"2":{"66":1}}],["hole",{"0":{"143":1,"153":1,"385":1,"387":1,"388":1},"1":{"32":3,"37":3,"51":1,"63":1,"66":8,"76":3,"143":2,"144":2,"153":5,"162":2,"179":1,"182":7,"220":6,"227":1,"256":4,"265":3,"278":1,"279":2,"299":1,"336":1,"345":14,"346":4,"354":11,"357":1,"359":1,"385":1,"387":2,"388":1,"391":1,"414":1},"2":{"10":1,"37":1,"49":1,"63":1,"143":1,"144":1,"162":1,"179":1,"182":1,"192":1,"220":1,"227":1,"256":1,"278":1,"279":1,"345":1,"346":1,"357":1,"359":1}}],["hanger",{"0":{"278":1},"1":{"278":6,"290":1,"291":3}}],["hands",{"1":{"420":1,"421":1}}],["handy",{"1":{"299":1}}],["handling",{"1":{"135":3}}],["handle",{"0":{"68":1},"1":{"34":11,"66":1,"68":22,"73":3,"78":22,"124":11,"135":1,"182":1,"230":1},"2":{"34":2}}],["hand",{"1":{"76":2,"140":1,"141":1,"250":1,"312":1,"334":1,"339":2}}],["happy",{"1":{"233":1}}],["happen",{"1":{"262":1}}],["happens",{"1":{"189":1,"272":1,"412":1}}],["happening",{"1":{"42":1}}],["harness",{"1":{"233":1,"237":1}}],["hardest",{"1":{"61":1}}],["halves",{"1":{"61":1,"161":1}}],["halfway",{"1":{"155":1}}],["half",{"1":{"60":4,"61":9,"69":8,"71":1,"80":1,"161":1,"176":1,"290":1,"350":2,"397":1,"415":1,"420":6},"3":{"49":1,"59":1,"61":1,"74":1,"80":1,"157":1,"161":1,"179":1,"182":1,"238":1,"239":1,"259":1,"281":1,"282":1,"287":1,"289":1,"408":1,"409":1,"413":1}}],["hash",{"1":{"58":1}}],["has",{"1":{"17":1,"20":1,"30":1,"53":2,"76":1,"80":2,"86":1,"104":1,"108":1,"130":1,"131":1,"138":1,"140":4,"181":1,"182":2,"189":2,"202":3,"204":1,"212":1,"221":1,"223":1,"236":1,"257":1,"260":1,"263":1,"267":1,"268":1,"270":1,"276":1,"295":1,"342":1,"343":1,"345":2,"352":1,"354":1,"374":1,"377":1,"385":1,"393":1,"410":1,"412":1,"416":1,"420":1}}],["having",{"1":{"1":1,"42":1,"129":1,"139":2,"147":1,"189":1,"254":1,"263":1,"290":1,"358":1}}],["have",{"1":{"1":1,"5":1,"6":2,"10":1,"12":1,"13":1,"20":1,"25":1,"34":2,"36":2,"53":1,"61":1,"91":1,"117":1,"123":1,"127":1,"134":1,"138":7,"141":1,"143":1,"145":1,"171":1,"180":1,"181":2,"188":1,"192":2,"194":1,"195":1,"196":1,"204":3,"206":1,"217":1,"222":1,"240":1,"250":1,"252":1,"257":1,"262":1,"270":1,"272":1,"276":2,"344":1,"350":1,"353":1,"354":1,"361":1,"371":1,"378":1,"379":1,"420":1}}],["hence",{"1":{"185":1}}],["hein",{"1":{"102":1}}],["height=3",{"1":{"381":1,"382":1,"385":1,"388":1,"389":1}}],["height=ridge",{"1":{"368":1,"369":1,"374":1,"375":1,"376":1,"377":1}}],["height=block",{"1":{"368":2,"369":2,"372":1,"373":1,"374":2,"375":2,"376":2,"377":2}}],["height=pip",{"1":{"369":1}}],["height=pin",{"1":{"350":1}}],["height=playingcard",{"1":{"76":2}}],["height=10",{"1":{"146":2}}],["height=suit",{"1":{"76":1}}],["height=length",{"1":{"37":1,"350":1}}],["height=wall",{"1":{"34":1,"78":2,"124":1,"368":1,"369":1}}],["height=thickness",{"1":{"32":1,"153":2,"170":4}}],["height",{"1":{"3":1,"6":1,"7":2,"28":2,"62":8,"64":2,"67":28,"76":13,"77":4,"124":1,"190":2,"218":1,"219":7,"220":3,"222":1,"240":1,"243":1,"290":1,"336":1,"340":3,"341":1,"346":2,"367":5,"368":4,"369":3,"377":2,"396":1,"420":1},"2":{"20":1,"77":1,"222":1}}],["heavily",{"1":{"231":1,"234":1,"412":1}}],["head",{"1":{"219":3,"246":1,"350":2,"354":1,"360":2}}],["heads",{"1":{"104":1}}],["headlight",{"1":{"80":1}}],["headlights",{"1":{"80":1},"2":{"80":1}}],["headtype",{"2":{"49":1}}],["headtype`",{"1":{"49":1}}],["hearts",{"1":{"76":7}}],["heart",{"0":{"420":1},"1":{"76":6,"407":1,"419":3,"420":22,"421":1},"2":{"76":1}}],["heat",{"0":{"69":1},"1":{"68":1,"69":18,"73":3}}],["hexagon",{"0":{"386":1,"387":1},"1":{"166":1,"386":1,"391":1}}],["hexagonal",{"1":{"66":2,"211":1,"385":1,"387":1,"388":1}}],["hex",{"1":{"40":1,"66":2}}],["hexlocations`",{"1":{"40":1,"49":1,"69":1,"211":1}}],["hexlocations",{"1":{"19":2,"45":1,"66":2,"69":2},"2":{"19":1,"40":1,"49":1,"66":1,"69":1,"211":1}}],["hello",{"1":{"108":1,"169":5}}],["helical",{"1":{"84":1,"259":1}}],["helix`",{"1":{"49":1,"218":1}}],["helix",{"1":{"218":2,"225":1,"259":1},"2":{"10":1,"49":1,"218":1,"225":1}}],["helping",{"1":{"346":1}}],["helps",{"1":{"87":1,"134":3,"236":1,"406":1,"417":1,"420":1}}],["help",{"1":{"74":2,"119":1,"124":1,"178":1,"181":1,"192":1,"197":1,"199":1,"203":1,"234":1,"246":1,"415":1,"422":1}}],["helpful",{"1":{"42":1,"411":1}}],["helper",{"1":{"15":1,"122":1,"208":1,"243":1,"245":1,"299":1,"306":1,"307":1}}],["here",{"0":{"252":1},"1":{"6":1,"13":1,"14":1,"25":1,"26":1,"28":2,"30":2,"31":1,"42":1,"51":2,"53":2,"60":1,"61":1,"73":1,"76":1,"81":1,"127":1,"148":1,"150":1,"151":1,"152":1,"157":1,"165":1,"166":1,"170":2,"178":1,"179":1,"182":1,"189":1,"190":1,"193":1,"199":2,"206":1,"221":1,"222":2,"238":1,"240":2,"241":1,"256":1,"257":1,"262":2,"263":2,"275":1,"304":2,"340":1,"345":1,"346":1,"352":1,"354":1,"358":1,"360":1,"362":1,"363":1,"365":1,"366":1,"367":1,"368":1,"369":1,"373":1,"374":1,"376":1,"382":2,"389":1,"395":1,"400":1,"408":1,"415":1,"420":1}}],["=``",{"1":{"151":1}}],["=`",{"1":{"9":2,"10":3}}],["============",{"1":{"123":1}}],["==============================",{"1":{"48":3}}],["========",{"1":{"48":3}}],["======",{"1":{"48":3}}],["==",{"1":{"6":2,"48":9,"49":3,"68":2,"76":6,"240":2,"243":1,"267":1,"271":1,"272":1,"273":1,"350":1}}],["=",{"1":{"3":1,"4":1,"5":2,"6":2,"7":1,"9":4,"10":18,"11":8,"13":5,"14":2,"16":6,"17":5,"19":8,"25":3,"26":6,"28":6,"30":4,"31":4,"32":2,"34":4,"36":6,"37":1,"39":1,"42":2,"49":2,"51":1,"52":1,"59":9,"60":28,"61":21,"62":52,"63":4,"64":9,"65":14,"66":8,"67":36,"68":10,"69":34,"70":11,"71":4,"72":12,"74":45,"75":19,"76":59,"77":24,"78":15,"80":8,"81":20,"108":8,"109":6,"110":3,"124":4,"142":3,"143":8,"144":11,"145":12,"146":6,"147":11,"148":15,"149":10,"150":4,"151":9,"152":15,"153":6,"154":6,"155":4,"156":7,"157":9,"158":5,"159":9,"160":6,"161":6,"162":8,"163":16,"164":4,"165":9,"166":4,"167":4,"168":4,"169":8,"170":9,"171":5,"172":9,"173":4,"174":4,"175":5,"176":7,"177":5,"179":5,"180":2,"182":4,"183":1,"184":8,"185":1,"187":5,"190":1,"192":5,"193":1,"198":1,"204":4,"208":8,"209":18,"210":1,"213":2,"215":2,"216":2,"217":2,"222":8,"224":2,"230":10,"238":1,"240":3,"243":30,"251":4,"256":5,"272":1,"273":10,"276":17,"278":17,"279":20,"280":10,"281":12,"282":9,"283":7,"284":15,"285":7,"286":16,"287":15,"288":8,"289":12,"290":24,"292":2,"295":9,"298":2,"299":13,"304":4,"307":6,"314":2,"317":2,"319":2,"331":6,"332":2,"336":7,"344":2,"346":8,"350":7,"354":1,"356":2,"357":2,"358":1,"359":1,"360":2,"367":13,"368":1,"369":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"395":19,"397":7,"398":4,"399":2,"400":4,"401":2,"409":4,"410":2,"417":27,"420":16}}],["nps=",{"1":{"184":1}}],["n",{"1":{"163":3,"410":1}}],["nicer",{"0":{"127":1}}],["nuts",{"1":{"84":1}}],["nubs",{"1":{"60":2}}],["nullhandler",{"1":{"51":1},"2":{"51":1}}],["numpy",{"1":{"140":1}}],["number=1",{"1":{"243":1}}],["number=",{"1":{"108":1,"243":1}}],["numbers",{"0":{"189":1},"1":{"99":1,"189":1,"194":1,"200":1,"202":1,"354":1}}],["numberdisplay",{"2":{"49":1}}],["numberdisplay`",{"1":{"49":1}}],["number",{"1":{"20":2,"66":1,"75":2,"135":2,"138":1,"140":2,"174":1,"176":1,"189":1,"219":1,"230":1,"236":1,"335":1,"365":1,"369":1,"404":1}}],["numeric",{"1":{"5":1,"306":1,"329":1,"330":1}}],["naca",{"1":{"218":1,"395":1,"396":1,"399":2}}],["navigate",{"1":{"133":1}}],["naming",{"1":{"119":2,"255":1,"294":1,"378":1}}],["namespace",{"1":{"255":2}}],["names",{"1":{"178":1,"255":1,"371":1,"378":1}}],["names=",{"1":{"34":1,"72":2,"78":2,"124":1}}],["named",{"1":{"75":1,"102":1,"299":1}}],["name=",{"1":{"39":2,"67":6,"68":6,"81":4,"108":1,"208":4,"209":17,"347":2}}],["name",{"1":{"26":1,"51":2,"73":3,"81":4,"108":1,"278":1,"370":1}}],["national",{"1":{"119":1}}],["native",{"1":{"26":1}}],["natural",{"1":{"124":1,"189":1,"250":1,"306":1,"339":1}}],["naturally",{"1":{"12":1,"61":2,"295":1,"406":1}}],["nature",{"1":{"99":1,"111":1}}],["noisy",{"1":{"405":1,"410":1,"412":1}}],["noindex",{"1":{"56":6,"57":1,"106":4,"114":1,"115":1,"182":1,"184":4}}],["nodemixin",{"2":{"20":1}}],["node",{"1":{"20":7},"2":{"20":1}}],["nodes",{"0":{"20":1},"1":{"20":7}}],["none",{"1":{"49":1,"67":3,"75":4,"77":1,"109":1,"129":1,"179":1,"180":2,"182":3,"183":1,"184":5,"272":1,"283":1}}],["none``",{"1":{"10":3}}],["non",{"1":{"18":1,"61":1,"62":1,"78":2,"129":1,"139":2,"171":1,"253":1,"419":1,"420":4,"421":1}}],["no",{"1":{"13":1,"15":1,"18":1,"20":1,"22":1,"36":1,"91":1,"124":2,"184":1,"188":1,"189":1,"197":1,"272":2,"303":1,"306":1,"312":1,"331":1,"333":1,"338":1,"342":1,"354":1,"368":1,"377":1,"402":1,"412":1,"420":1,"421":1}}],["nor",{"1":{"10":1,"272":1}}],["normally",{"1":{"190":1}}],["normalized",{"1":{"147":1}}],["normal",{"1":{"7":1,"25":1,"34":1,"42":1,"49":2,"61":2,"144":1,"149":1,"156":1,"189":1,"192":1,"202":1,"267":4,"304":1,"313":1,"398":1,"420":1},"2":{"42":1,"267":1}}],["now",{"1":{"3":1,"14":1,"28":1,"92":1,"133":1,"222":1,"354":1,"356":1,"361":1,"364":2,"368":2,"373":1,"377":1,"387":1,"420":2}}],["notch",{"1":{"357":1}}],["notably",{"1":{"166":1,"278":1}}],["notice",{"1":{"42":1,"234":1}}],["notes",{"1":{"187":1,"299":1}}],["note",{"0":{"22":1},"1":{"20":1,"25":1,"26":1,"30":1,"34":1,"42":1,"58":2,"59":1,"62":2,"73":1,"81":1,"108":1,"124":2,"129":1,"130":1,"144":2,"152":2,"160":1,"169":3,"172":2,"177":1,"178":1,"179":1,"181":1,"182":1,"184":3,"185":1,"188":3,"189":1,"192":1,"198":2,"208":1,"209":2,"211":1,"217":1,"218":1,"221":1,"238":2,"240":1,"272":1,"338":1,"339":1,"347":1,"350":1,"352":1,"353":1,"357":1,"358":1,"362":1,"364":1,"368":1,"369":1,"371":2,"374":1,"376":1,"377":1,"379":1,"388":1,"394":1,"395":1,"399":1,"403":1,"420":5,"421":1}}],["not",{"0":{"263":1},"1":{"2":1,"10":2,"17":1,"24":1,"25":2,"31":2,"37":1,"38":1,"39":2,"42":1,"49":1,"61":1,"67":1,"71":2,"75":1,"91":1,"129":1,"134":2,"135":1,"138":2,"141":1,"144":1,"158":1,"171":1,"172":1,"179":1,"181":1,"183":1,"184":1,"185":1,"188":3,"189":1,"190":1,"191":1,"192":1,"198":1,"201":1,"202":1,"209":1,"218":1,"238":1,"252":1,"254":1,"255":2,"258":1,"262":3,"263":1,"271":1,"272":4,"278":1,"281":1,"290":1,"307":1,"310":2,"311":1,"312":1,"345":1,"350":3,"359":1,"368":2,"371":1,"378":1,"405":1,"406":1,"408":1,"409":1,"410":2,"413":1,"415":2,"417":1,"420":1}}],["never",{"1":{"378":1}}],["nearest",{"1":{"320":1,"345":1}}],["nearby",{"1":{"299":1}}],["near",{"1":{"257":1,"276":1,"417":1}}],["neatly",{"1":{"74":1}}],["nema",{"1":{"243":1,"248":1}}],["nema23",{"1":{"243":1}}],["necessarily",{"1":{"192":1,"254":1,"406":1}}],["necessary",{"1":{"141":1,"172":1,"253":1,"258":1,"273":1,"341":1,"420":1}}],["neck",{"1":{"163":2}}],["necktopf",{"1":{"163":2}}],["net",{"1":{"134":1}}],["nething",{"0":{"92":1},"1":{"92":2}}],["networks",{"1":{"310":1}}],["network",{"1":{"61":3,"402":1,"403":1}}],["negate",{"1":{"184":1}}],["negativex",{"1":{"290":1}}],["negative",{"1":{"144":3,"149":1,"151":1,"154":1,"156":1,"345":1,"354":1,"373":1}}],["neg",{"1":{"55":4,"58":1}}],["next``",{"1":{"171":1}}],["next",{"0":{"418":1},"1":{"49":1,"70":4,"92":1,"171":2,"222":1,"235":1,"276":1,"289":1,"341":1,"345":1,"363":1,"382":1,"384":1},"2":{"171":1}}],["nesting",{"0":{"166":1},"1":{"40":1}}],["nested",{"0":{"254":1},"1":{"17":1,"166":1,"179":1,"198":1,"254":2,"266":3}}],["neither",{"1":{"10":1,"272":1}}],["ne",{"1":{"10":1,"55":1}}],["neutral",{"1":{"9":1,"10":1,"120":1}}],["needlessly",{"1":{"253":1}}],["needed",{"1":{"185":1,"188":1,"191":1,"336":1,"337":1,"341":1},"2":{"188":1}}],["needs",{"1":{"10":1,"12":1,"42":1,"144":1,"145":1,"336":1,"345":1,"349":1,"367":1,"368":1,"373":1,"375":1,"377":1,"380":1,"389":1,"400":1,"405":1,"415":2}}],["need",{"1":{"2":1,"17":1,"22":1,"31":2,"74":1,"108":1,"129":1,"133":1,"134":1,"140":3,"172":1,"174":1,"178":1,"181":1,"190":1,"195":1,"230":1,"267":1,"279":1,"290":1,"295":1,"335":2,"339":1,"343":1,"344":3,"345":1,"374":1}}],["new``",{"1":{"272":6,"273":1}}],["new",{"0":{"273":1},"1":{"2":2,"5":2,"20":1,"39":1,"49":1,"54":2,"59":1,"66":1,"67":1,"71":1,"73":1,"81":1,"98":1,"134":1,"155":1,"191":1,"192":1,"194":4,"197":2,"200":1,"201":1,"203":1,"210":1,"222":1,"233":2,"238":1,"268":1,"270":1,"272":10,"273":4,"286":1,"289":1,"303":1,"308":2,"345":2,"369":2,"373":1},"2":{"272":1,"273":2}}],["f3",{"1":{"284":2}}],["f2",{"1":{"284":2}}],["f1",{"1":{"284":2}}],["fdm",{"1":{"61":1}}],["f",{"1":{"52":1,"60":4,"61":2,"66":1,"72":1,"75":1,"76":1,"77":1,"81":2,"109":6,"189":2,"190":1,"240":2,"243":1,"267":2,"271":2,"278":3,"279":2,"280":2,"281":2,"282":2,"283":2,"284":2,"285":2,"286":2,"287":2,"288":2,"289":5,"290":2}}],["ft",{"1":{"36":1,"49":1,"77":5,"184":2,"395":2,"397":2}}],["frustratingly",{"1":{"258":1}}],["friendly",{"1":{"141":1}}],["frowned",{"1":{"255":1}}],["frontend",{"1":{"95":1}}],["front",{"1":{"80":6,"243":2,"246":1,"335":1,"339":2,"345":1,"420":1}}],["fromisoformat",{"1":{"243":1},"2":{"243":1}}],["from",{"0":{"129":1,"150":1,"234":1,"236":1,"252":1,"383":1,"415":1},"1":{"4":1,"5":3,"16":2,"17":2,"20":2,"23":1,"25":1,"26":1,"28":1,"30":1,"31":1,"32":1,"34":2,"37":1,"39":1,"42":4,"53":2,"60":2,"61":5,"62":2,"63":2,"65":4,"66":4,"68":4,"69":4,"70":4,"71":2,"72":6,"74":4,"75":9,"76":4,"77":1,"78":4,"80":4,"81":6,"86":1,"94":1,"97":1,"102":1,"110":1,"121":1,"124":2,"127":1,"129":3,"131":1,"133":2,"134":1,"139":1,"141":1,"144":2,"147":3,"151":2,"152":2,"153":2,"154":1,"158":1,"167":1,"172":2,"176":1,"178":3,"179":3,"180":1,"182":3,"184":4,"187":1,"190":2,"192":2,"193":1,"194":1,"195":1,"197":1,"199":1,"202":1,"204":1,"218":1,"223":1,"233":1,"235":1,"236":1,"238":15,"242":1,"243":5,"246":2,"250":2,"251":3,"254":2,"256":3,"258":1,"263":1,"264":2,"268":2,"271":1,"272":3,"274":1,"275":3,"276":6,"278":4,"279":3,"280":2,"281":2,"282":2,"283":2,"284":2,"285":2,"286":2,"287":2,"288":2,"289":3,"290":4,"294":1,"295":3,"303":2,"304":1,"306":3,"307":2,"310":1,"313":1,"317":1,"319":1,"329":1,"330":1,"331":1,"335":1,"340":2,"344":1,"345":3,"346":2,"349":2,"354":1,"364":1,"367":2,"368":2,"369":1,"373":2,"375":1,"378":1,"380":2,"381":2,"382":2,"383":2,"385":2,"387":1,"388":3,"389":2,"393":1,"395":4,"396":1,"397":3,"398":1,"399":1,"403":1,"408":1,"409":1,"410":2,"412":1,"413":1,"415":3,"419":2,"420":7,"421":5},"2":{"62":1,"178":1,"255":1,"367":1,"420":1,"421":2}}],["freedom",{"1":{"184":1,"310":1,"358":1},"2":{"310":1}}],["free",{"1":{"117":1,"138":2,"140":1,"291":1}}],["freecad",{"0":{"93":1},"1":{"93":3,"124":1}}],["freeform",{"1":{"61":4,"135":2,"410":1,"412":1,"421":2}}],["frequently",{"1":{"55":1,"191":1,"202":1}}],["frenet",{"1":{"49":1}}],["fragility",{"1":{"310":1}}],["fragments",{"1":{"122":1,"408":1,"412":1}}],["framing",{"1":{"77":1}}],["framework",{"1":{"97":1,"101":1,"124":1,"206":2}}],["frameworks",{"1":{"91":1,"140":1}}],["frame",{"1":{"61":2,"419":1,"420":3}}],["frames",{"1":{"61":1,"310":1}}],["framemethod",{"2":{"49":1}}],["framemethod`",{"1":{"49":1}}],["fraction",{"1":{"49":1,"395":3,"397":1,"399":3}}],["fractional",{"1":{"28":1}}],["feed",{"1":{"295":1}}],["feel",{"1":{"133":2,"291":1}}],["fe",{"1":{"278":2}}],["fetches",{"1":{"129":1}}],["feature",{"1":{"108":1,"111":1,"117":1,"135":1,"147":1,"164":1,"268":1,"269":1,"270":2,"272":1,"274":1,"277":1,"406":1},"2":{"269":1}}],["featured",{"1":{"95":1}}],["features",{"0":{"40":1,"160":1,"162":1,"341":1,"342":1},"1":{"4":1,"5":2,"40":1,"42":3,"62":1,"65":1,"71":1,"98":3,"104":1,"111":1,"135":2,"141":1,"147":1,"174":1,"202":1,"230":3,"232":1,"233":4,"256":1,"258":1,"267":1,"268":1,"269":1,"272":5,"275":1,"276":2,"277":1,"310":1,"335":1,"336":1,"338":1,"340":1,"342":3,"345":2,"378":4,"382":1,"404":1,"411":1,"414":2},"2":{"98":1}}],["fender",{"1":{"80":8}}],["fenders",{"1":{"80":1}}],["fewer",{"1":{"138":1,"148":1}}],["few",{"1":{"25":1,"124":1,"160":1,"404":1,"406":1}}],["fairness",{"1":{"304":1}}],["fairing",{"1":{"303":1}}],["fail",{"1":{"253":1}}],["failure",{"1":{"250":1}}],["failing",{"1":{"236":1}}],["fails",{"1":{"74":1,"129":1,"252":1}}],["fall",{"1":{"271":1}}],["false",{"1":{"70":2,"230":1,"241":1,"256":1}}],["faq",{"0":{"260":1}}],["fade",{"1":{"179":1}}],["families",{"1":{"315":1,"316":1}}],["familiar",{"1":{"163":1,"234":1}}],["family",{"1":{"310":1}}],["famous",{"1":{"163":1}}],["fanf2",{"1":{"102":1}}],["faster",{"1":{"236":1,"258":1,"412":1,"415":1}}],["fasteners",{"1":{"146":1,"261":1,"350":1}}],["fastener",{"0":{"354":1},"1":{"84":1},"3":{"10":1,"11":1,"32":1,"37":1,"49":1,"51":1,"60":1,"61":1,"63":1,"64":1,"65":1,"66":1,"73":1,"76":1,"84":1,"135":1,"143":1,"144":1,"146":1,"153":1,"156":1,"162":1,"179":1,"180":1,"182":1,"192":1,"220":1,"227":1,"240":1,"256":1,"258":1,"265":1,"278":1,"279":1,"280":1,"281":1,"283":1,"287":1,"289":1,"299":1,"336":1,"345":1,"346":1,"350":1,"354":1,"357":1,"359":1,"365":1,"385":1,"387":1,"388":1,"391":1,"414":1,"420":1}}],["fast",{"0":{"66":1},"1":{"65":1,"66":1,"73":3}}],["fact",{"1":{"262":1,"290":1}}],["factors",{"1":{"303":1}}],["factor",{"1":{"36":1,"243":4},"2":{"243":1}}],["facilitating",{"1":{"113":1,"117":1,"120":1}}],["facilitate",{"1":{"42":1}}],["facets",{"1":{"121":1}}],["faceted",{"1":{"59":1}}],["face``",{"1":{"53":1,"263":1,"299":1}}],["face`",{"1":{"26":1,"49":1,"58":1,"172":2,"206":1,"238":2,"299":1,"419":1,"420":1,"421":1}}],["face",{"0":{"65":1,"144":1,"384":1},"1":{"26":2,"34":3,"39":6,"42":9,"58":1,"59":1,"60":3,"61":7,"62":5,"64":1,"65":14,"66":7,"70":2,"71":1,"73":3,"75":8,"76":5,"78":2,"80":1,"81":2,"124":1,"131":7,"144":3,"145":2,"146":2,"148":2,"150":1,"151":1,"152":1,"154":1,"157":2,"161":1,"162":4,"163":2,"165":3,"169":4,"171":1,"172":5,"176":2,"184":1,"206":3,"208":6,"209":17,"222":1,"235":2,"238":3,"239":2,"241":1,"256":4,"263":2,"267":1,"276":10,"279":1,"280":1,"281":1,"286":1,"288":1,"289":1,"290":2,"299":2,"339":1,"340":6,"341":1,"345":13,"346":1,"350":1,"365":1,"369":1,"382":2,"384":1,"395":2,"396":1,"400":2,"403":1,"417":12,"418":1,"419":1,"420":6,"421":7},"2":{"19":1,"26":1,"34":1,"39":1,"42":1,"49":1,"53":1,"58":1,"59":1,"60":2,"61":1,"62":2,"65":1,"66":1,"71":1,"75":2,"76":1,"78":1,"80":1,"81":1,"124":1,"145":1,"148":1,"157":1,"163":1,"165":1,"169":1,"172":1,"176":1,"190":1,"206":1,"222":1,"238":2,"239":2,"262":1,"263":1,"270":1,"279":1,"280":1,"281":1,"286":1,"288":1,"289":1,"290":1,"299":2,"340":1,"341":1,"346":1,"350":1,"395":1,"400":1,"419":1,"420":2,"421":1}}],["faces``",{"1":{"190":3}}],["faces`",{"1":{"49":2,"238":1,"266":1}}],["faces",{"0":{"150":1,"151":1,"162":1,"383":1},"1":{"4":2,"6":1,"7":1,"32":1,"34":1,"39":1,"42":2,"46":1,"60":9,"61":5,"62":10,"63":4,"67":2,"68":3,"70":2,"72":2,"75":15,"76":4,"78":2,"80":1,"81":6,"104":1,"110":1,"112":1,"124":1,"135":1,"144":2,"146":2,"147":3,"150":2,"151":2,"152":2,"154":2,"156":2,"158":7,"159":2,"160":4,"161":4,"162":5,"163":4,"167":5,"168":1,"169":3,"170":2,"172":1,"182":4,"190":3,"193":1,"202":7,"206":5,"231":1,"236":1,"238":3,"239":1,"240":3,"241":8,"242":1,"253":1,"256":1,"267":2,"268":4,"272":3,"274":1,"276":12,"280":1,"281":1,"285":1,"287":1,"289":1,"345":10,"346":2,"350":2,"357":1,"369":1,"371":1,"382":2,"383":3,"384":1,"385":1,"388":1,"389":1,"390":1,"394":1,"402":1,"404":1,"406":1,"410":2,"417":9,"420":7,"421":7},"2":{"4":1,"6":1,"7":1,"34":1,"42":1,"49":1,"60":2,"61":2,"62":1,"63":1,"70":1,"72":1,"76":1,"78":1,"80":1,"81":1,"124":1,"143":1,"144":1,"146":1,"150":1,"151":1,"152":1,"154":1,"156":1,"158":1,"160":1,"161":1,"162":1,"163":1,"167":1,"168":1,"169":1,"170":1,"182":1,"190":1,"193":1,"202":1,"238":1,"239":1,"240":1,"241":1,"256":1,"266":1,"267":1,"268":1,"272":1,"276":1,"280":1,"281":1,"285":1,"287":1,"289":1,"345":1,"346":1,"350":1,"357":1,"369":1,"382":1,"383":1,"385":1,"388":1,"389":1,"417":1}}],["farthest",{"1":{"150":1,"154":1,"345":1}}],["far",{"1":{"31":1,"233":1,"368":1}}],["flips",{"1":{"420":1}}],["flipped",{"1":{"182":1,"204":1}}],["flexibility",{"0":{"336":1},"1":{"135":1,"141":2,"214":1,"230":2,"236":1,"336":1}}],["flexible",{"1":{"102":1,"123":1,"139":1,"141":1,"194":1,"234":1,"267":1}}],["flanges",{"1":{"84":1,"184":2}}],["flange",{"1":{"84":1,"184":10}}],["flanged",{"0":{"287":1},"1":{"63":7,"287":1,"291":1}}],["flag",{"0":{"62":1},"1":{"62":10,"63":1,"73":3,"184":1}}],["flattened",{"1":{"74":1}}],["flat",{"1":{"42":1,"61":2,"78":1,"82":1}}],["flow",{"1":{"7":1}}],["floats",{"1":{"201":1}}],["float",{"1":{"5":1,"28":1,"49":3,"67":3,"75":2,"76":9,"77":16,"180":2,"182":3,"183":1,"184":4,"199":1,"201":1,"208":2,"222":2,"243":2,"279":1,"295":1,"350":10}}],["fluent",{"1":{"7":2,"191":1,"240":1}}],["fix",{"1":{"352":1}}],["fixes",{"1":{"141":1}}],["fixed",{"0":{"325":1,"327":1},"1":{"134":2,"181":1,"184":1,"310":1,"312":1,"315":3,"316":2,"324":1,"328":1,"347":1,"353":1,"357":1}}],["figure",{"1":{"267":1,"268":1,"272":5,"273":2,"275":1,"276":1,"291":1,"298":1,"299":2,"304":1,"307":1,"312":1,"314":1,"317":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"331":1,"332":1}}],["five",{"1":{"75":3,"351":1}}],["field",{"1":{"62":40,"252":1}}],["finite",{"1":{"135":1,"421":2}}],["finishes=",{"1":{"179":1}}],["finished",{"1":{"33":1,"369":1}}],["finish",{"1":{"34":1,"78":2,"124":1,"355":1}}],["finding",{"1":{"48":1,"134":2,"147":1,"202":1}}],["find",{"1":{"34":1,"70":2,"73":1,"78":2,"80":1,"124":1,"133":1,"250":1,"273":1,"289":1,"382":1},"2":{"34":1,"78":1,"124":1,"289":1}}],["finds",{"1":{"28":1,"415":1}}],["finalize",{"1":{"315":1}}],["finally",{"1":{"31":1,"42":1,"268":1,"275":1,"368":1,"373":1,"419":1,"420":1}}],["final",{"1":{"4":1,"30":1,"61":1,"66":1,"176":1,"193":1,"194":2,"196":1,"222":1,"299":1,"340":1,"345":1,"369":1,"389":1,"396":1,"401":1,"406":1,"413":1,"415":1,"417":2,"421":1}}],["first=false",{"1":{"290":1}}],["firstly",{"1":{"152":1,"177":1}}],["first",{"1":{"23":1,"32":1,"37":1,"49":1,"67":1,"77":1,"81":1,"110":1,"144":1,"150":1,"151":1,"154":1,"155":1,"161":1,"164":2,"202":2,"241":1,"251":1,"256":2,"268":1,"275":1,"295":1,"303":2,"306":1,"310":1,"311":1,"331":1,"345":2,"352":1,"372":1,"373":1,"374":1,"383":1,"420":1}}],["fitment",{"1":{"345":1}}],["fit",{"0":{"337":1},"1":{"21":1,"61":1,"69":1,"337":1},"3":{"34":1,"42":1,"49":1,"52":1,"61":1,"62":1,"71":1,"72":1,"76":1,"78":1,"80":1,"81":1,"124":1,"149":1,"152":1,"154":1,"158":1,"159":1,"160":1,"161":1,"163":1,"182":1,"238":1,"239":1,"241":1,"243":1,"278":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"287":1,"290":1,"310":1,"313":1,"314":1,"337":1,"340":1,"341":1,"346":1,"357":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"406":1,"417":1,"419":1,"420":1}}],["fill",{"1":{"67":1,"110":2,"262":2,"421":1}}],["filled",{"1":{"34":1,"37":2,"42":1,"78":2,"124":1,"371":1}}],["filleting",{"1":{"80":2,"81":2,"344":1}}],["filleted",{"0":{"417":1},"1":{"49":1,"69":1,"182":1,"218":1,"278":1,"344":2,"417":1}}],["fillet`",{"1":{"49":2,"143":2,"177":1,"199":1,"238":1,"250":1,"389":1}}],["filletpolyline`",{"1":{"49":1,"218":1}}],["filletpolyline",{"1":{"218":1,"225":1,"314":1,"340":2,"341":1,"346":1},"2":{"10":1,"49":1,"218":1,"225":1,"314":1,"340":1,"341":1,"346":1}}],["fillet",{"0":{"389":1},"1":{"4":1,"7":3,"34":3,"42":1,"63":1,"65":2,"68":2,"69":19,"70":4,"71":2,"76":2,"78":8,"80":16,"81":4,"124":3,"143":2,"144":4,"149":2,"151":2,"163":2,"177":2,"182":7,"190":1,"199":6,"230":8,"239":1,"253":1,"272":4,"273":2,"278":8,"281":2,"282":2,"284":5,"286":2,"287":1,"289":3,"290":1,"336":1,"340":1,"344":7,"346":3,"350":1,"389":4,"414":1,"417":3},"2":{"4":1,"7":1,"34":1,"42":1,"49":1,"63":1,"65":1,"68":1,"69":1,"70":1,"71":1,"76":1,"78":1,"80":1,"81":1,"124":1,"143":1,"144":1,"149":1,"151":1,"163":1,"177":1,"182":1,"190":1,"199":1,"230":1,"238":1,"239":1,"250":1,"272":1,"273":1,"278":1,"281":1,"282":1,"284":1,"286":1,"287":1,"289":1,"290":1,"340":1,"344":1,"346":1,"350":1,"389":1,"417":1}}],["fillets",{"0":{"177":1,"253":1,"344":1},"1":{"4":1,"65":1,"81":1,"135":1,"230":4,"232":1,"233":1,"253":2,"404":1,"417":1},"2":{"81":1}}],["files",{"1":{"99":1,"112":1,"113":2,"120":1,"121":1,"123":2,"140":1,"415":1,"416":1}}],["filename",{"1":{"51":1}}],["filename=",{"1":{"51":1}}],["file",{"0":{"116":1},"1":{"19":3,"26":2,"51":1,"67":1,"76":1,"110":1,"111":2,"112":1,"113":1,"120":1,"121":3,"123":3,"178":3,"189":2,"243":1,"248":1,"278":1,"369":1,"408":1,"416":1}}],["filtered",{"1":{"267":2,"274":1,"344":1}}],["filtering",{"0":{"240":1},"1":{"54":1,"230":1,"233":1,"241":1,"242":1,"267":1,"312":1,"331":1}}],["filter",{"0":{"267":1,"391":1},"1":{"6":2,"34":1,"42":2,"49":2,"59":1,"63":1,"69":2,"70":4,"72":2,"78":2,"81":5,"124":1,"144":2,"151":2,"177":2,"182":1,"230":2,"240":3,"241":5,"256":1,"266":15,"267":3,"269":1,"271":2,"272":1,"273":1,"278":3,"280":3,"281":1,"282":1,"284":1,"287":1,"289":3,"290":2,"344":3,"346":1,"350":2,"389":1,"391":2,"392":1,"393":1,"394":1,"395":1,"400":1,"417":8},"2":{"6":2,"34":1,"42":2,"49":2,"59":1,"63":1,"69":1,"70":1,"72":1,"78":1,"81":2,"124":1,"144":1,"151":1,"177":1,"182":1,"230":1,"240":2,"241":1,"256":1,"266":2,"267":1,"272":1,"273":1,"278":1,"280":1,"281":1,"282":1,"284":1,"287":1,"289":1,"290":1,"344":1,"346":1,"350":1,"389":1,"391":1,"392":1,"393":1,"394":1,"395":1,"400":1,"417":1}}],["filters",{"1":{"6":1,"240":3,"266":1,"267":1,"344":1}}],["focal",{"1":{"218":1}}],["focuses",{"1":{"421":1}}],["focus",{"1":{"140":1,"350":1,"357":1}}],["foundation",{"1":{"204":1,"233":1,"236":1,"310":1,"340":1}}],["found",{"1":{"76":1,"102":1,"134":1,"135":1,"179":1,"181":1,"187":2,"188":1,"404":1}}],["four",{"1":{"76":1,"198":1,"204":1,"256":1,"374":1}}],["folder",{"1":{"73":1}}],["follow",{"1":{"344":1,"367":1}}],["followed",{"1":{"36":1,"123":1,"199":1,"331":1}}],["follows",{"1":{"14":1,"28":3,"39":2,"52":1,"128":1,"181":1,"182":1,"184":2,"192":1,"195":1,"199":1,"201":1,"204":1,"242":1,"251":2,"262":1,"294":1,"295":1,"336":1,"340":2,"347":1,"350":1,"362":1,"371":1,"372":1,"375":1,"376":1,"420":1},"2":{"251":1,"262":1,"347":1}}],["following",{"1":{"4":1,"5":1,"10":1,"20":1,"23":1,"27":1,"30":1,"32":1,"36":1,"37":1,"40":1,"42":1,"43":1,"47":1,"50":1,"51":1,"53":1,"54":1,"55":1,"89":1,"92":1,"119":1,"128":2,"129":5,"137":1,"181":1,"184":1,"194":1,"197":1,"202":1,"203":1,"206":1,"208":1,"211":1,"212":1,"218":1,"221":1,"224":1,"238":2,"241":1,"244":1,"260":1,"263":1,"271":1,"299":3,"318":1,"334":1,"335":1,"344":1,"362":1,"372":1,"379":1,"389":1,"420":1}}],["fontht",{"1":{"169":4}}],["fontsz",{"1":{"169":2}}],["fontstyle`",{"1":{"49":1}}],["fontstyle",{"1":{"44":1},"2":{"44":1,"49":1}}],["font",{"1":{"61":1,"65":4,"67":34,"71":1,"76":2,"169":4,"219":1,"243":1}}],["forth",{"1":{"182":1}}],["fork",{"0":{"86":1},"1":{"86":2}}],["forward",{"1":{"80":2,"246":1}}],["forming",{"1":{"206":1}}],["forms",{"1":{"188":2,"236":1,"302":1}}],["formal",{"1":{"187":1,"206":1}}],["format",{"1":{"108":1,"111":3,"112":3,"113":3,"117":2,"120":2,"121":3,"123":5,"133":1,"141":1}}],["format=",{"1":{"51":1}}],["formats",{"0":{"116":1},"1":{"36":2,"111":1,"124":1,"133":3,"178":2}}],["formerly",{"1":{"94":1}}],["former",{"0":{"67":1},"1":{"67":1,"73":1}}],["formed",{"1":{"239":1,"278":4,"403":1},"2":{"49":1,"238":1,"239":1,"278":1}}],["formed`",{"1":{"49":1,"238":1}}],["form",{"1":{"66":1,"75":1,"172":1,"201":1,"206":1,"235":2,"290":1,"341":1,"401":1,"417":1,"421":1}}],["forced",{"1":{"34":1}}],["forcing",{"1":{"7":1}}],["for",{"0":{"144":1,"167":1,"168":1,"207":1,"233":1,"336":1,"341":1,"345":1,"391":1,"402":1},"1":{"1":1,"3":2,"4":1,"9":2,"10":8,"11":5,"15":2,"17":2,"19":5,"22":3,"23":1,"24":1,"25":1,"26":2,"28":1,"31":3,"32":1,"33":1,"34":5,"37":1,"38":2,"39":2,"40":1,"42":6,"48":2,"49":4,"59":3,"60":5,"61":8,"62":4,"63":1,"64":5,"65":2,"66":3,"68":7,"69":2,"70":2,"72":2,"74":1,"75":24,"76":1,"77":5,"78":6,"80":3,"81":4,"85":1,"90":3,"91":2,"92":1,"93":1,"94":1,"95":2,"97":1,"99":3,"100":1,"102":1,"104":2,"108":3,"109":1,"111":2,"112":2,"113":2,"117":1,"118":1,"119":4,"120":2,"121":1,"122":1,"123":6,"124":9,"129":1,"130":1,"133":4,"134":3,"135":6,"138":4,"139":2,"140":7,"141":5,"143":1,"144":1,"146":4,"147":3,"149":2,"152":1,"155":1,"156":1,"159":1,"162":3,"164":1,"167":4,"168":3,"169":1,"170":2,"172":1,"174":2,"175":3,"178":2,"180":1,"181":1,"182":1,"189":1,"191":2,"192":2,"194":3,"195":1,"197":1,"198":3,"201":2,"202":1,"204":3,"206":9,"208":1,"210":1,"211":1,"212":1,"214":1,"219":2,"221":1,"224":1,"230":8,"233":3,"235":1,"236":3,"238":2,"241":2,"243":3,"244":2,"248":1,"250":1,"252":1,"253":1,"254":1,"255":3,"256":1,"257":2,"258":2,"262":2,"272":3,"275":1,"276":4,"277":2,"278":1,"279":2,"289":1,"290":1,"291":1,"293":1,"294":1,"295":4,"299":2,"303":2,"307":1,"310":6,"311":2,"312":3,"313":2,"314":1,"315":2,"325":1,"326":1,"327":1,"328":1,"329":2,"331":2,"334":1,"337":2,"338":2,"339":1,"340":2,"341":2,"342":1,"343":1,"344":1,"345":3,"346":1,"350":3,"351":1,"354":2,"355":1,"357":1,"374":2,"377":1,"382":1,"391":2,"395":2,"397":1,"398":2,"403":1,"406":1,"414":1,"415":1,"416":1,"418":1,"420":3,"421":2}}],["furthest",{"1":{"275":1}}],["furthermore",{"1":{"144":1}}],["further",{"1":{"4":1,"13":1,"28":1,"69":1,"178":1,"191":1,"269":1,"277":1,"343":1,"377":1,"405":1}}],["future",{"1":{"255":2}}],["fusing",{"1":{"187":1}}],["fusion",{"1":{"137":1,"250":1}}],["fused",{"1":{"11":1}}],["fuse",{"1":{"10":1,"223":1},"2":{"10":1,"11":1}}],["fundamentals",{"1":{"420":1,"421":1}}],["fundamentally",{"1":{"231":1}}],["fundamental",{"1":{"112":1,"206":2,"234":1,"421":1}}],["funcname",{"1":{"51":1}}],["func",{"1":{"26":1,"34":3,"38":2,"39":1,"49":35,"110":1,"122":1,"238":33,"250":3,"252":2,"266":1,"388":1,"389":1,"408":1,"413":1,"415":2,"419":1,"420":1}}],["functional",{"1":{"98":1,"124":1,"139":1}}],["functionality",{"0":{"23":1,"32":1,"37":1},"1":{"2":1,"6":1,"7":1,"34":1,"58":1,"89":1,"133":1,"134":1,"180":1,"222":1,"233":1,"299":1,"337":1,"345":1}}],["function",{"0":{"168":1},"1":{"15":3,"18":1,"26":1,"108":1,"168":4,"184":1,"198":1,"208":1,"210":1,"243":1,"245":1,"257":2,"267":1,"341":2,"344":1,"419":1,"420":1}}],["functions",{"1":{"11":1,"17":1,"56":1,"91":2,"118":1,"238":2}}],["fully",{"1":{"6":1,"28":1,"30":1,"95":1,"124":1,"183":1,"233":1,"258":1,"299":1,"354":2}}],["full",{"1":{"6":1,"49":1,"53":1,"122":1,"229":1,"233":1,"238":1,"239":1,"257":1,"280":2,"299":1,"395":1,"409":3,"420":1,"421":1},"2":{"49":1,"238":1,"239":1,"280":1}}],["m5",{"1":{"286":1}}],["m4",{"1":{"286":3}}],["m3",{"1":{"286":2}}],["m2",{"1":{"286":3,"304":3}}],["my",{"1":{"191":6,"250":1,"369":1}}],["mypy",{"1":{"124":1}}],["myapp",{"1":{"51":1}}],["mr",{"0":{"91":1},"2":{"90":1,"91":1}}],["mx",{"1":{"70":2}}],["mc",{"1":{"49":1}}],["m",{"1":{"36":1,"49":1,"128":3,"129":3}}],["mm^3",{"1":{"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["mm``",{"1":{"36":1}}],["mm",{"1":{"34":14,"36":5,"49":1,"59":4,"60":3,"69":10,"70":44,"71":2,"74":4,"76":2,"78":28,"109":1,"124":14,"180":1,"230":8,"243":6,"278":1,"336":7,"345":2,"346":8,"350":3,"356":4,"357":4,"359":2,"365":1},"2":{"36":1}}],["music",{"1":{"197":1}}],["muse",{"1":{"71":1}}],["must",{"1":{"61":1,"62":2,"75":1,"108":1,"147":1,"182":1,"184":1,"189":1,"199":1,"202":1,"211":1,"263":1,"307":1,"312":3,"322":1,"324":1,"325":1,"353":1,"367":1,"392":1,"420":1}}],["multimodal",{"1":{"100":1}}],["multi",{"0":{"72":1},"1":{"71":1,"73":2,"111":1,"252":1,"312":1}}],["multisection",{"1":{"68":1}}],["multisection=true",{"1":{"68":2}}],["multiplication",{"1":{"156":1}}],["multiplies",{"1":{"36":1}}],["multiple",{"0":{"311":1,"312":1},"1":{"42":2,"108":1,"133":6,"140":2,"141":2,"162":1,"173":2,"174":1,"177":1,"178":1,"192":2,"201":1,"206":1,"218":1,"219":1,"220":1,"235":1,"259":1,"276":1,"307":1,"311":1,"330":1,"341":1,"343":1,"374":2}}],["multiply`",{"1":{"49":2}}],["multiply",{"1":{"9":1,"49":1},"2":{"49":1}}],["mul",{"1":{"55":3}}],["much",{"1":{"26":1,"172":1,"198":1,"250":1,"255":1,"354":1,"359":1,"390":1,"405":1,"416":1,"417":1}}],["mix",{"1":{"212":1,"241":1,"271":1}}],["mixed",{"1":{"197":1,"330":1}}],["mixin3d",{"1":{"58":1},"2":{"58":1}}],["mixin3d`",{"1":{"58":1}}],["mixin2d",{"1":{"58":1},"2":{"58":1}}],["mixin1d`",{"1":{"58":1}}],["mixin1d",{"1":{"49":3,"58":1,"147":2,"184":1},"2":{"58":1}}],["mismatches",{"1":{"420":1}}],["mistake",{"1":{"189":1}}],["missing",{"1":{"61":1,"402":1}}],["mimic",{"1":{"78":1}}],["millimeters",{"1":{"36":1},"2":{"36":1}}],["midfaces",{"1":{"162":2}}],["midpoint",{"1":{"80":1}}],["middle",{"1":{"276":1,"352":1}}],["midd",{"1":{"74":2}}],["midx",{"1":{"74":4}}],["mid",{"1":{"28":1}}],["mirrors",{"1":{"340":1}}],["mirroring",{"0":{"148":1,"149":1,"150":1},"1":{"420":1}}],["mirrored",{"1":{"61":2,"308":1,"340":2}}],["mirror`",{"1":{"49":3,"176":1,"238":1,"308":1,"310":1}}],["mirror",{"1":{"26":1,"60":3,"61":4,"62":4,"67":2,"69":2,"76":5,"80":2,"148":3,"149":7,"150":2,"163":2,"176":2,"222":1,"238":1,"239":1,"278":3,"280":1,"281":2,"286":1,"288":2,"289":1,"290":2,"310":1,"340":3,"341":3,"346":2,"420":7},"2":{"26":1,"49":1,"60":1,"61":1,"62":1,"67":1,"69":1,"76":1,"80":1,"148":1,"149":1,"150":1,"163":1,"176":1,"222":1,"238":1,"239":1,"278":1,"280":1,"281":1,"286":1,"288":1,"289":1,"290":1,"308":1,"310":1,"340":1,"341":1,"346":1,"420":1}}],["might",{"1":{"26":1,"42":1,"50":1,"129":1,"137":1,"171":1,"192":1,"195":1,"197":1,"235":1,"256":1,"267":1}}],["minkowski",{"1":{"233":1}}],["minor",{"1":{"219":1,"220":1,"224":1}}],["minimum",{"1":{"353":1,"363":1}}],["minimal",{"1":{"121":1,"124":1,"221":1}}],["minimizes",{"1":{"339":1}}],["minimize",{"1":{"18":1}}],["minimized",{"1":{"15":1}}],["minute",{"1":{"65":8,"198":1}}],["mindset",{"1":{"233":1,"413":1}}],["mind",{"1":{"31":1,"261":1,"343":1,"347":1}}],["min",{"1":{"16":3,"49":1,"60":1,"62":5,"67":11,"75":1,"76":7,"77":5,"80":4,"124":1,"149":4,"169":2,"179":5,"182":1,"221":3,"230":4,"243":1,"262":1,"272":1,"278":1,"280":4,"282":2,"284":3,"286":2,"288":3,"289":1,"290":3,"350":8,"357":1,"359":2,"368":1,"369":2,"396":1,"417":6,"420":1},"2":{"221":1}}],["m6",{"1":{"13":2,"14":2,"19":2,"180":1,"347":2,"360":5,"365":1}}],["m1",{"1":{"11":1,"286":3,"304":3}}],["mechanical",{"1":{"404":1,"411":1}}],["mechanism",{"1":{"141":1}}],["meet",{"1":{"279":1,"295":1,"303":1,"304":1,"306":1}}],["meeting",{"1":{"75":1}}],["merged",{"1":{"141":1}}],["merge",{"1":{"141":1,"420":1}}],["merging",{"1":{"141":1}}],["measured",{"1":{"276":1}}],["measures",{"1":{"276":1}}],["measurement",{"1":{"104":1,"243":1}}],["meaning",{"1":{"238":1,"339":1,"345":1,"420":1}}],["means",{"1":{"11":1,"134":2,"135":1,"140":3,"141":1,"174":1,"250":1}}],["melior",{"1":{"102":1}}],["memory",{"1":{"52":1}}],["members",{"1":{"29":1,"35":1,"41":1,"55":6,"58":6,"139":1,"179":1,"180":1,"182":1,"183":1,"184":1,"268":1}}],["meshes",{"1":{"117":1,"416":1}}],["mesher`",{"1":{"108":1,"109":1,"408":1,"416":1}}],["mesher",{"1":{"59":1,"108":4,"109":1,"276":5,"409":1},"2":{"59":1,"108":1,"109":1,"276":1,"408":1,"409":1,"416":1}}],["mesh",{"0":{"108":1,"109":1,"409":1},"1":{"109":2,"122":1,"135":9,"276":10,"405":2,"408":2,"409":7,"410":6,"411":1,"412":2,"413":1,"415":3}}],["meshtype",{"2":{"49":1}}],["meshtype`",{"1":{"49":1}}],["message",{"1":{"51":1}}],["metal",{"1":{"238":1,"278":3}}],["metadata",{"1":{"108":2,"120":1},"2":{"108":1}}],["meta",{"1":{"49":1,"108":2},"2":{"108":1}}],["metaphor",{"1":{"42":1}}],["meth",{"1":{"12":1,"14":1,"18":1,"25":1,"26":2,"39":1,"49":28,"110":1,"143":2,"144":2,"147":5,"152":2,"156":1,"158":1,"159":2,"160":2,"164":2,"167":1,"171":1,"172":2,"176":1,"177":3,"183":1,"184":3,"199":1,"204":4,"206":1,"240":1,"257":3,"259":1,"266":10,"403":1,"418":1,"419":1,"420":3,"421":6}}],["methodology",{"1":{"230":1}}],["method",{"1":{"7":1,"14":1,"39":1,"49":5,"66":1,"110":1,"130":1,"147":2,"149":1,"156":1,"179":1,"180":1,"182":2,"183":1,"184":8,"206":1,"222":2,"236":1,"240":1,"241":1,"245":1,"268":2,"271":1,"273":1,"347":1,"368":1,"369":1,"384":1,"394":1,"420":2}}],["methods",{"0":{"46":1,"212":1,"213":1},"1":{"4":1,"56":1,"118":1,"177":1,"204":1,"212":2,"214":3,"217":1,"230":1,"236":1,"240":1,"242":3,"267":1,"269":2,"270":1,"271":1,"272":1,"274":3,"275":1,"277":1,"378":2,"394":1,"419":1,"420":1,"421":2}}],["mentioned",{"1":{"26":1,"108":1}}],["mark",{"1":{"357":1}}],["marked",{"1":{"238":1}}],["margins",{"1":{"314":1}}],["magnitude",{"1":{"304":1}}],["maintains",{"1":{"194":1}}],["maintain",{"1":{"135":1,"147":1,"184":1,"310":1,"419":1}}],["maintainability",{"1":{"134":2,"230":1,"237":1,"255":1}}],["maintainable",{"1":{"124":1,"310":1}}],["maintaining",{"1":{"98":1,"134":1,"196":1}}],["maintained",{"1":{"34":1,"138":1,"200":1}}],["main",{"1":{"78":1,"80":1,"141":1,"151":2,"152":2,"214":1,"278":1,"311":1,"417":1}}],["mainp",{"1":{"74":9}}],["maind",{"1":{"74":6}}],["mapping",{"1":{"111":1}}],["maple",{"1":{"62":15}}],["mapsto",{"1":{"9":4,"10":3}}],["matched",{"1":{"410":1}}],["matches",{"1":{"61":1,"304":1}}],["match",{"1":{"133":2,"291":1,"303":2,"313":1}}],["material=",{"1":{"184":1}}],["materials",{"1":{"117":1}}],["material",{"1":{"81":2,"111":1,"331":1,"345":1}}],["matmul",{"1":{"58":2}}],["matrix",{"1":{"55":1},"2":{"55":1}}],["mathematics",{"1":{"206":1}}],["mathematically",{"1":{"187":1,"188":1}}],["mathematical",{"1":{"123":1,"135":2,"197":1,"230":1}}],["mathematician",{"1":{"102":1}}],["math",{"1":{"9":27,"10":37,"72":2,"75":1,"147":1,"279":2,"289":1,"290":1,"295":2}}],["major",{"1":{"54":1,"66":4,"179":1,"219":1,"220":1,"224":1}}],["made",{"1":{"54":1,"141":4,"165":1}}],["mass=",{"1":{"278":3,"279":2,"280":2,"281":2,"282":2,"283":2,"284":2,"285":2,"286":2,"287":2,"288":2,"289":2,"290":2}}],["mass",{"1":{"48":1,"49":1,"135":1,"278":8,"279":7,"280":7,"281":7,"282":8,"283":7,"284":7,"285":7,"286":7,"287":7,"288":7,"289":7,"290":7,"291":1},"2":{"282":1}}],["may",{"1":{"39":1,"58":1,"119":1,"138":10,"181":1,"194":1,"197":1,"222":1,"250":3,"252":3,"258":2,"259":2,"262":1,"274":1,"278":2,"303":1,"304":1,"312":1,"320":1,"347":1,"353":1,"405":1,"406":1,"412":1,"414":3}}],["makebox",{"1":{"251":1},"2":{"251":1}}],["makerrepo>`",{"1":{"91":1}}],["makerrepo",{"0":{"90":1,"91":1},"1":{"90":5,"91":6},"2":{"90":1,"91":1}}],["maker",{"0":{"71":1},"1":{"70":1,"71":6,"73":3}}],["makes",{"1":{"48":1,"61":1,"99":2,"111":1,"112":1,"133":2,"134":1,"135":2,"139":2,"140":4,"141":3,"143":2,"206":1,"299":1,"354":1}}],["make",{"1":{"26":3,"28":1,"34":1,"42":1,"49":3,"59":1,"60":1,"61":3,"62":4,"63":1,"65":2,"71":2,"75":1,"76":4,"78":2,"80":1,"81":2,"92":1,"108":2,"113":1,"124":1,"131":1,"133":1,"134":1,"138":1,"140":1,"145":2,"147":1,"148":2,"157":2,"158":1,"163":2,"165":2,"172":4,"176":2,"179":1,"182":1,"208":2,"222":1,"233":1,"235":2,"238":3,"239":3,"251":1,"257":1,"258":1,"261":1,"263":1,"278":4,"279":2,"280":1,"281":1,"286":1,"288":1,"289":1,"290":2,"299":1,"310":1,"336":1,"338":1,"340":2,"341":1,"346":1,"350":1,"387":1,"395":1,"400":1,"401":1,"403":1,"406":1,"415":1,"418":1,"419":1,"420":6,"421":6},"2":{"26":2,"34":1,"42":1,"49":3,"59":1,"60":1,"61":1,"62":2,"63":1,"65":1,"71":1,"75":1,"76":1,"78":1,"80":1,"81":1,"108":2,"124":1,"131":1,"145":1,"148":1,"157":1,"163":1,"165":1,"172":1,"176":1,"179":1,"208":1,"222":1,"238":3,"239":3,"251":1,"263":1,"278":1,"279":2,"280":1,"281":1,"286":1,"288":1,"289":1,"290":1,"299":1,"310":1,"340":1,"341":1,"346":1,"350":1,"395":1,"400":1,"403":1,"418":1,"419":1,"420":5,"421":6}}],["making",{"1":{"20":1,"81":1,"112":1,"117":1,"119":1,"120":1,"123":2,"133":1,"134":1,"140":1,"141":1,"206":2,"230":4,"232":1,"236":1,"255":1,"339":1}}],["manifold",{"1":{"421":2}}],["manipulating",{"1":{"206":1,"236":1}}],["manipulation",{"0":{"212":1},"1":{"204":1,"212":1,"214":1,"421":1}}],["manipulate",{"1":{"135":1}}],["managing",{"1":{"204":1,"206":1}}],["manageable",{"1":{"230":1}}],["management",{"1":{"133":3,"139":1,"236":1}}],["manage",{"1":{"90":1,"139":1,"236":1}}],["manager",{"0":{"7":1},"1":{"7":1,"23":2,"24":1,"26":2,"32":2,"33":1,"37":2,"38":1,"97":1}}],["manner",{"1":{"111":1,"181":1,"206":1}}],["manual",{"1":{"122":1,"133":1,"134":1,"230":1,"405":1,"410":1,"412":1,"415":2}}],["manually",{"1":{"39":1,"133":1,"139":1,"230":1,"263":1,"307":1,"310":1,"405":1,"412":1}}],["manufacturers",{"1":{"119":1}}],["manufacturing",{"1":{"111":3,"120":2,"124":1,"139":1,"314":1,"337":1}}],["many",{"1":{"19":1,"40":1,"52":1,"53":1,"61":1,"140":3,"181":1,"250":1,"255":1,"257":1,"299":1,"331":1,"333":2,"411":1,"412":2}}],["maximum",{"1":{"75":1,"353":1}}],["max",{"1":{"16":3,"49":1,"59":1,"67":2,"75":1,"76":3,"77":2,"110":3,"169":2,"241":1,"243":2,"271":1,"272":1,"286":1,"289":1,"357":1},"2":{"221":1}}],["maxdepth",{"1":{"0":1,"47":1,"126":1,"264":1,"265":1,"266":1,"421":1,"422":1}}],["machine",{"1":{"140":2}}],["machining",{"1":{"124":1}}],["macos",{"1":{"129":1}}],["mac",{"1":{"11":1,"140":1}}],["motor",{"1":{"245":1,"247":1,"248":1}}],["motion",{"1":{"181":1,"182":1,"183":1,"347":1,"354":1}}],["moving",{"0":{"173":1,"214":1,"231":1},"1":{"126":1,"214":1,"250":1,"337":1}}],["move`",{"1":{"204":1}}],["movement",{"0":{"213":1},"1":{"182":1,"184":1,"210":1,"354":1}}],["moves",{"1":{"144":1,"180":1,"182":1,"235":1}}],["moved`",{"1":{"12":1,"204":1}}],["moved",{"1":{"9":2,"61":1,"76":1,"182":1,"188":3,"189":2,"213":1,"262":1,"358":2},"2":{"9":1,"12":1,"61":1,"76":1,"188":1,"189":1,"204":1,"213":1,"358":1}}],["move",{"1":{"9":1,"42":1,"62":3,"108":1,"152":1,"173":1,"182":1,"189":1,"213":5,"214":1,"217":1,"339":1,"347":1,"354":2,"358":1,"359":1,"362":1},"2":{"62":1,"108":1,"204":1,"213":1}}],["mount",{"1":{"70":2,"80":1}}],["mold",{"1":{"63":1}}],["monitoring",{"1":{"53":1}}],["monkey",{"1":{"2":2,"124":1}}],["modular",{"1":{"236":1}}],["modularity",{"1":{"196":1,"230":1,"237":1}}],["modules",{"1":{"90":1,"140":2}}],["module",{"1":{"18":1,"19":1,"29":1,"35":1,"41":1,"44":1,"55":1,"56":1,"57":1,"58":1,"105":2,"106":1,"124":1,"181":1,"225":1,"226":1,"227":1,"396":1,"420":1}}],["mod",{"1":{"58":2}}],["modifies",{"1":{"196":1}}],["modified",{"1":{"19":1,"76":1,"138":2,"139":1,"143":2,"200":1,"250":1,"269":1,"344":1}}],["modifiable",{"1":{"138":1}}],["modifications",{"1":{"232":1,"237":1,"258":1,"336":1}}],["modification",{"1":{"135":1}}],["modifying",{"1":{"135":1,"140":1,"189":2,"272":1}}],["modify",{"1":{"31":1,"59":1,"138":1,"139":1,"167":1,"168":1,"189":1,"210":1,"249":1,"272":1,"358":1}}],["mode=lengthmode",{"1":{"278":1,"281":1,"282":1}}],["mode=mode",{"1":{"4":2,"16":3,"32":1,"37":1,"42":2,"51":4,"59":2,"60":1,"62":1,"64":3,"65":3,"67":1,"69":2,"70":5,"71":2,"74":2,"75":1,"76":15,"77":1,"80":6,"144":1,"149":2,"151":1,"152":1,"153":1,"156":1,"161":1,"162":1,"164":1,"167":1,"168":1,"169":1,"170":3,"173":2,"174":1,"175":1,"179":3,"182":2,"193":1,"222":1,"224":2,"278":2,"279":1,"280":4,"281":3,"282":2,"283":2,"284":5,"285":1,"286":6,"287":5,"288":4,"289":3,"290":1,"299":4,"307":1,"331":2,"345":3,"346":1,"350":2,"357":1,"368":3,"369":3,"373":1,"374":1,"375":2,"376":3,"377":3,"385":1,"388":2,"389":2,"420":1}}],["modern",{"1":{"102":1,"104":1,"111":1,"123":1,"124":1,"230":1,"237":1}}],["mode`",{"1":{"49":1,"153":1,"162":1,"167":1}}],["modelling",{"0":{"135":1}}],["modelled",{"1":{"76":1,"124":1,"396":1}}],["models",{"0":{"139":1},"1":{"87":1,"91":1,"97":1,"98":1,"99":2,"100":1,"104":2,"111":1,"112":2,"113":1,"117":1,"121":1,"124":3,"135":2,"139":1,"189":1,"200":2,"229":1,"230":2,"231":1,"233":1,"234":1,"236":4},"2":{"87":1,"104":1}}],["modeling`",{"1":{"420":1}}],["modeling",{"0":{"421":1},"1":{"66":2,"80":1,"92":1,"112":1,"124":3,"135":5,"163":1,"194":1,"204":1,"206":5,"230":1,"231":1,"234":1,"237":1,"310":2,"400":1,"401":1,"415":1,"419":1,"420":5,"421":6,"422":1},"2":{"124":1}}],["model",{"0":{"232":1},"1":{"49":1,"59":4,"60":1,"61":2,"65":2,"69":1,"78":1,"80":1,"102":1,"104":1,"109":3,"120":1,"121":2,"124":3,"135":4,"139":2,"189":1,"193":1,"197":1,"206":7,"230":2,"232":1,"235":1,"249":1,"310":2,"335":1,"354":1,"360":1,"396":3,"397":1,"406":1,"409":1,"413":1,"415":3,"417":3,"420":4,"421":1}}],["modes",{"0":{"192":1},"1":{"37":1,"73":1,"194":3},"2":{"37":1}}],["mode",{"0":{"11":1,"186":1,"197":1,"207":1,"210":1,"211":1,"223":1,"273":1,"292":1,"296":1,"297":1},"1":{"37":1,"44":1,"59":1,"60":1,"61":1,"62":2,"63":1,"64":4,"65":2,"66":1,"67":3,"68":2,"69":2,"70":2,"71":1,"72":2,"74":2,"75":8,"76":16,"77":8,"78":2,"80":2,"81":4,"122":1,"124":1,"128":3,"142":2,"143":3,"144":3,"145":2,"146":2,"147":2,"148":2,"149":2,"150":2,"151":2,"152":2,"153":2,"154":2,"155":2,"156":2,"157":2,"158":2,"159":2,"160":2,"161":2,"162":2,"163":2,"164":2,"165":2,"166":2,"167":2,"168":2,"169":2,"170":2,"171":2,"172":2,"173":2,"174":2,"175":2,"176":2,"177":2,"178":4,"186":1,"189":6,"192":1,"194":1,"196":2,"210":2,"211":2,"214":3,"218":1,"222":3,"224":2,"230":2,"238":1,"273":3,"278":2,"281":1,"311":1,"319":2,"333":1,"406":1,"408":1,"410":1},"2":{"32":1,"37":1,"44":1,"49":1,"75":1,"77":1,"153":1,"162":1,"167":1,"192":2,"222":1,"223":2,"299":1,"373":1,"387":1,"388":1}}],["mostly",{"1":{"411":1}}],["most",{"1":{"12":1,"48":1,"61":1,"73":1,"97":1,"98":1,"130":1,"141":1,"143":2,"178":1,"191":1,"192":1,"196":1,"202":1,"235":1,"255":1,"258":1,"272":1,"310":1,"320":1,"331":1,"361":1,"409":1,"411":1,"413":1,"414":1,"421":1}}],["more",{"0":{"235":1},"1":{"7":1,"11":1,"12":1,"28":1,"31":1,"36":1,"42":1,"61":1,"62":1,"64":1,"78":1,"81":2,"91":1,"98":1,"102":1,"108":1,"111":1,"117":1,"133":1,"134":1,"135":4,"138":3,"139":3,"140":1,"141":5,"147":1,"172":1,"174":1,"181":1,"198":1,"209":1,"231":1,"234":1,"236":2,"249":1,"250":3,"259":1,"273":1,"310":1,"312":1,"330":1,"343":2,"344":1,"353":1,"389":1,"405":1,"412":1,"414":1,"415":1,"416":1,"417":1,"420":1,"421":1}}],["our",{"1":{"341":1,"342":1,"345":1}}],["outcomes",{"1":{"229":1}}],["outlet",{"1":{"184":8}}],["outline",{"1":{"5":1,"26":1,"62":6,"65":2,"71":1,"81":5,"102":1,"214":1,"230":1,"235":1,"278":1,"420":2}}],["outwards",{"1":{"159":1,"160":1}}],["outputs",{"1":{"312":1,"410":1}}],["output",{"0":{"411":1,"412":1},"1":{"133":2,"189":1,"257":1,"315":1,"404":1,"408":1,"417":3}}],["outset",{"1":{"76":1,"238":1}}],["outside``",{"1":{"312":1,"331":2}}],["outside",{"1":{"6":1,"49":1,"60":1,"61":2,"69":1,"71":1,"182":1,"233":1,"240":1,"243":1,"312":1,"331":2,"353":1,"372":1,"420":2},"2":{"312":1,"331":2}}],["out",{"1":{"34":2,"42":1,"70":2,"78":5,"95":1,"124":2,"151":2,"198":1,"270":2,"272":1,"278":1,"343":1,"373":1}}],["outer``",{"1":{"362":1}}],["outer",{"1":{"13":2,"14":3,"61":2,"66":1,"80":2,"179":1,"180":1,"230":1,"290":2,"331":1,"350":3,"353":3,"356":1,"357":1,"362":3,"363":4,"364":1,"365":1,"367":1,"368":1,"369":1,"376":1,"377":1,"421":1},"2":{"80":1,"362":1}}],["omitting",{"1":{"311":1}}],["omitted",{"1":{"178":1,"188":1}}],["ot",{"1":{"290":1}}],["ot=40",{"1":{"290":1}}],["other=edge",{"1":{"420":1}}],["other=l3",{"1":{"290":1}}],["other=l2",{"1":{"71":1}}],["other=c",{"1":{"289":1}}],["others",{"1":{"97":1,"141":1,"294":1,"295":1,"345":1}}],["other",{"0":{"31":1,"42":1},"1":{"7":1,"25":1,"30":1,"31":1,"37":1,"42":1,"49":2,"57":1,"60":1,"74":1,"91":1,"111":2,"117":1,"123":1,"124":1,"133":3,"134":1,"135":1,"137":1,"138":1,"139":1,"140":1,"141":1,"147":1,"158":1,"178":1,"179":1,"180":1,"181":1,"182":2,"183":1,"184":5,"206":1,"218":4,"219":1,"241":1,"249":1,"250":1,"255":2,"258":1,"262":1,"263":1,"310":2,"312":1,"345":3,"347":1,"353":2,"367":1,"379":1,"420":3,"421":1},"2":{"347":1}}],["otherwise",{"1":{"4":1,"26":2,"221":1,"230":1,"261":1}}],["ow",{"1":{"163":3}}],["owned",{"1":{"138":1}}],["ownership",{"1":{"138":2}}],["own",{"1":{"19":1,"51":1,"77":1,"249":1,"414":1}}],["os",{"1":{"71":1}}],["oval",{"1":{"63":6}}],["oversized",{"1":{"286":1}}],["overcome",{"1":{"111":1}}],["overhead",{"1":{"98":1,"310":1}}],["overhang",{"1":{"74":2}}],["overview",{"0":{"73":1,"246":1,"270":1,"271":1,"315":1,"316":1,"396":1,"408":1},"1":{"178":1,"420":1,"421":1}}],["over",{"0":{"17":1,"132":1},"1":{"17":2,"19":1,"137":1,"140":1,"141":4,"162":1,"174":1,"196":1,"255":1,"257":1,"319":1,"320":1,"367":1,"421":1}}],["overlapping",{"1":{"15":1,"18":1,"194":1,"257":1}}],["overlap",{"1":{"15":1,"18":1,"257":1}}],["overall",{"1":{"11":2,"134":1,"219":1,"240":2,"340":1,"396":1}}],["obsolete",{"1":{"378":1}}],["observing",{"1":{"290":1}}],["obtain",{"1":{"194":1,"278":1}}],["ob3``",{"1":{"174":1}}],["obj3",{"1":{"174":1}}],["obj2",{"1":{"174":2}}],["obj1",{"1":{"174":2}}],["objs",{"1":{"149":2}}],["obj``",{"1":{"124":1,"144":2,"173":2}}],["obj=playing",{"1":{"76":1}}],["obj=diamond",{"1":{"76":1}}],["obj=heart",{"1":{"76":1}}],["obj=spade",{"1":{"76":1}}],["obj=club",{"1":{"76":1,"222":1}}],["obj",{"1":{"62":4,"143":2,"167":4,"168":2,"240":2},"2":{"124":1,"174":1}}],["object``",{"1":{"347":1}}],["object",{"0":{"48":1,"57":1,"161":1,"187":1,"256":1},"1":{"3":1,"9":2,"10":3,"12":2,"14":1,"15":3,"19":4,"20":1,"23":5,"26":1,"27":1,"31":1,"32":5,"37":5,"39":2,"42":1,"48":1,"49":3,"51":3,"58":1,"59":1,"64":1,"66":1,"67":6,"68":8,"74":2,"75":3,"76":4,"77":5,"81":10,"135":2,"139":1,"144":2,"161":1,"162":2,"168":1,"173":2,"178":5,"185":1,"186":1,"188":3,"189":6,"190":2,"191":3,"192":8,"194":7,"195":1,"196":1,"199":1,"200":1,"201":2,"204":6,"206":1,"208":4,"209":21,"210":1,"211":2,"214":1,"217":2,"222":8,"223":9,"235":6,"238":2,"241":1,"243":3,"246":2,"252":1,"253":1,"256":2,"261":1,"263":2,"272":3,"273":3,"274":1,"275":1,"278":2,"279":1,"280":1,"281":2,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"291":13,"293":1,"295":2,"298":1,"299":1,"306":5,"307":1,"315":2,"316":2,"340":1,"341":1,"347":2,"350":1,"357":1,"358":1,"362":1,"367":1,"369":6,"371":1,"372":2,"373":3,"377":1,"379":2,"381":1,"384":1,"385":1,"386":1,"419":2,"420":3,"421":1},"2":{"39":1,"51":1,"64":1,"67":1,"68":1,"76":1,"81":1,"178":1,"191":1,"192":1,"208":1,"209":1,"281":1,"347":1,"369":2}}],["objects",{"0":{"3":1,"4":1,"10":1,"55":1,"58":1,"149":1,"190":1,"201":1,"214":1,"218":1,"219":1,"220":1,"222":1,"224":1,"257":1,"293":1},"1":{"2":1,"4":2,"5":1,"7":1,"9":2,"10":3,"11":4,"13":2,"15":3,"18":3,"20":1,"21":2,"22":1,"23":1,"24":2,"25":2,"26":2,"28":1,"32":1,"33":2,"34":1,"37":2,"38":2,"49":5,"53":1,"54":1,"55":1,"56":1,"57":1,"58":2,"76":1,"77":4,"78":2,"108":1,"118":1,"121":1,"126":2,"146":1,"149":1,"173":1,"174":1,"178":2,"181":3,"186":1,"187":1,"189":2,"190":2,"191":7,"192":3,"195":1,"196":1,"197":1,"198":3,"199":2,"201":5,"202":2,"204":1,"206":5,"210":1,"211":6,"214":2,"218":4,"221":1,"222":4,"223":2,"224":4,"225":2,"226":1,"227":1,"228":1,"229":1,"233":1,"234":1,"235":2,"237":1,"238":5,"242":2,"243":1,"250":3,"251":2,"257":3,"259":1,"260":1,"261":1,"263":1,"268":1,"269":2,"270":2,"271":2,"272":4,"273":1,"274":2,"277":2,"293":1,"310":1,"315":3,"316":1,"330":1,"347":1,"350":1,"352":1,"358":1,"360":1,"361":1,"371":1,"374":1,"376":1,"379":1,"394":1,"402":1,"420":2,"421":1},"2":{"394":1}}],["obvious",{"1":{"61":1,"198":1,"411":1,"412":1,"414":1}}],["occ",{"0":{"163":1},"1":{"163":2}}],["occur",{"1":{"144":1}}],["occurrences",{"1":{"78":1}}],["occurrence",{"1":{"78":2}}],["occt",{"1":{"54":1,"61":2,"280":1,"331":6}}],["octahedron",{"1":{"75":3},"2":{"75":1}}],["ocp>`",{"1":{"87":1,"251":1}}],["ocp",{"0":{"93":1,"94":1,"95":1},"1":{"16":1,"17":1,"34":1,"60":1,"61":1,"63":1,"65":2,"66":1,"68":2,"69":2,"70":2,"72":2,"74":2,"75":1,"76":1,"78":2,"80":1,"81":2,"93":2,"94":3,"95":1,"104":1,"124":1,"128":2,"130":1,"178":1,"179":1,"181":1,"182":1,"184":2,"243":1,"255":1,"276":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"295":1,"299":1,"346":1,"347":1,"349":1,"367":1,"380":1,"381":1,"382":1,"385":1,"388":1,"389":1,"395":1,"397":1,"420":1},"2":{"98":1,"128":1,"379":1}}],["older",{"1":{"19":1,"129":1}}],["o=",{"1":{"14":11,"51":6,"52":1,"198":8,"204":1}}],["on=some",{"1":{"328":1}}],["on=axis",{"1":{"324":1}}],["on``",{"0":{"324":1,"328":1}}],["onshape",{"1":{"137":1}}],["only",{"1":{"17":1,"19":1,"58":1,"61":1,"80":1,"110":1,"157":2,"179":1,"181":1,"184":1,"189":1,"194":1,"201":1,"202":1,"258":1,"268":1,"272":6,"299":3,"310":1,"319":1,"333":1,"335":1,"343":1,"344":1,"402":1,"404":1,"412":1,"420":1}}],["once",{"1":{"11":2,"12":1,"42":2,"123":1,"128":1,"141":1,"174":1,"184":1,"189":1,"235":1,"257":1,"350":1,"362":1,"372":1,"376":1,"402":2,"403":1,"410":1,"414":1,"416":1}}],["on",{"0":{"31":1,"42":1,"147":1,"151":1,"152":1,"162":1,"189":1,"257":1,"382":1},"1":{"11":1,"19":1,"20":2,"21":1,"23":1,"28":1,"31":4,"32":1,"34":3,"37":2,"39":4,"40":1,"42":7,"53":3,"54":1,"61":2,"62":2,"65":1,"66":1,"70":2,"71":3,"77":1,"78":2,"80":7,"81":3,"84":1,"86":1,"87":1,"91":1,"108":1,"124":3,"129":1,"135":1,"138":3,"139":1,"140":5,"141":2,"144":3,"147":1,"148":1,"156":2,"157":1,"163":1,"168":1,"169":5,"172":1,"177":1,"178":1,"181":2,"186":2,"188":10,"189":3,"194":1,"198":2,"199":1,"200":1,"201":3,"202":5,"208":2,"209":2,"214":1,"221":2,"230":1,"231":1,"234":2,"236":3,"243":3,"244":1,"246":2,"250":2,"254":1,"255":1,"257":1,"262":11,"263":4,"267":3,"268":1,"275":1,"276":1,"278":1,"291":2,"299":1,"302":1,"304":2,"308":1,"312":1,"315":2,"324":2,"328":1,"329":2,"331":4,"339":2,"344":1,"345":6,"353":2,"357":1,"368":2,"369":6,"374":1,"375":1,"376":1,"377":1,"381":1,"382":3,"384":1,"394":1,"399":1,"406":1,"408":1,"409":2,"410":1,"414":2,"417":2,"420":3,"421":5,"422":1},"2":{"246":1,"324":1,"328":1}}],["onto",{"1":{"9":2,"60":3,"61":6,"62":3,"70":2,"146":1,"188":1,"245":1}}],["ones",{"1":{"233":1,"422":1}}],["one",{"0":{"323":1,"325":1,"327":1,"328":1},"1":{"7":1,"11":2,"12":2,"13":1,"14":1,"19":1,"24":1,"25":1,"26":1,"31":3,"34":1,"36":1,"39":3,"40":1,"42":3,"48":2,"50":1,"51":1,"53":1,"58":1,"67":7,"75":2,"80":1,"110":1,"127":1,"129":2,"137":1,"155":1,"157":2,"173":2,"176":1,"183":1,"184":3,"190":2,"191":1,"192":1,"194":1,"195":1,"197":1,"198":1,"199":1,"201":3,"202":4,"206":1,"210":1,"219":1,"222":1,"256":1,"258":1,"259":2,"261":1,"262":2,"267":1,"273":1,"279":1,"289":2,"295":3,"299":1,"304":1,"310":1,"312":1,"315":2,"316":2,"321":1,"322":1,"323":1,"324":1,"325":2,"326":1,"327":1,"328":1,"330":1,"335":2,"343":1,"345":2,"350":1,"354":2,"365":1,"369":1,"374":2,"379":1,"394":1,"395":1,"405":1,"406":3,"409":1,"414":3,"415":2,"417":1,"420":2,"421":1},"2":{"173":1}}],["o",{"1":{"9":2,"290":1},"2":{"9":1}}],["official",{"1":{"255":1}}],["offs",{"1":{"159":4}}],["offset=",{"1":{"243":2}}],["offset=1",{"1":{"243":2}}],["offsets",{"1":{"61":1,"160":1,"417":3}}],["offset`",{"1":{"49":3,"159":2,"160":2,"238":1,"310":1,"313":1,"314":1,"419":1,"420":1}}],["offset",{"0":{"154":1,"159":1,"160":1,"313":1,"314":1,"373":1},"1":{"34":3,"42":1,"49":1,"52":1,"62":4,"71":1,"72":2,"76":4,"78":8,"80":3,"81":3,"124":3,"149":9,"152":2,"154":3,"158":3,"159":10,"160":4,"161":3,"163":4,"182":2,"239":1,"241":1,"243":1,"278":1,"280":3,"281":1,"282":1,"283":3,"284":2,"285":4,"287":7,"290":2,"314":2,"340":5,"341":1,"346":1,"357":1,"368":2,"369":2,"373":3,"374":2,"375":2,"376":2,"377":2,"406":2,"417":21,"420":1},"2":{"34":1,"42":1,"49":1,"52":1,"62":1,"71":1,"72":1,"76":1,"78":1,"80":1,"81":1,"124":1,"149":1,"154":1,"158":1,"159":1,"160":1,"161":1,"163":1,"182":1,"238":1,"239":1,"278":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"287":1,"290":1,"310":1,"313":1,"314":1,"340":1,"341":1,"346":1,"357":1,"368":1,"369":1,"373":2,"374":1,"375":1,"376":1,"377":1,"406":1,"417":1,"419":1,"420":1}}],["offer",{"1":{"141":1,"212":1,"230":1}}],["offers",{"1":{"124":1,"233":1,"235":1,"236":1,"291":1}}],["offline",{"1":{"124":1,"141":1}}],["off",{"1":{"42":1,"81":1,"182":1,"238":1,"262":1,"299":1,"344":1,"355":1,"381":1,"420":2}}],["often",{"1":{"42":2,"61":1,"134":2,"135":1,"199":2,"201":1,"206":2,"231":1,"243":1,"250":1,"255":2,"262":1,"277":1,"306":1,"307":1,"311":2,"330":1,"338":1,"340":1,"404":1,"405":1,"406":2,"408":1,"411":1,"414":1,"415":1,"417":1,"420":1}}],["of",{"0":{"19":1,"126":1,"128":1,"155":1,"263":1,"382":1,"411":1,"412":1},"1":{"2":1,"4":3,"5":4,"6":1,"7":4,"9":1,"10":4,"11":2,"12":3,"13":3,"14":3,"17":2,"19":10,"20":7,"22":2,"23":2,"24":3,"25":4,"26":4,"27":2,"28":6,"30":7,"31":6,"32":2,"33":2,"34":4,"37":3,"38":2,"39":2,"40":4,"42":7,"47":1,"48":2,"49":2,"50":1,"51":1,"52":2,"53":3,"54":2,"55":1,"57":1,"59":2,"60":2,"61":11,"62":4,"63":1,"65":1,"66":5,"67":1,"69":5,"70":4,"71":4,"72":1,"73":4,"74":1,"75":6,"77":6,"78":10,"80":9,"81":10,"83":1,"84":1,"86":1,"93":1,"98":1,"99":2,"100":1,"101":2,"102":2,"104":1,"110":10,"111":1,"112":1,"117":4,"119":4,"120":2,"121":4,"123":4,"124":3,"129":3,"133":4,"134":9,"135":12,"137":2,"138":6,"139":10,"140":11,"141":5,"143":3,"144":5,"145":1,"146":1,"148":1,"152":3,"155":1,"156":1,"157":3,"160":1,"161":1,"162":3,"166":1,"167":1,"168":2,"169":3,"170":2,"174":2,"176":2,"177":3,"178":4,"179":1,"180":1,"181":2,"182":4,"183":2,"184":10,"186":1,"187":2,"188":5,"189":3,"190":2,"191":3,"193":1,"194":3,"195":3,"196":1,"197":1,"198":4,"199":5,"200":3,"201":5,"202":9,"204":12,"206":22,"208":2,"209":5,"211":1,"212":2,"213":2,"214":1,"218":1,"219":1,"221":1,"222":12,"229":2,"230":4,"233":5,"235":2,"236":3,"238":4,"240":6,"242":3,"243":4,"245":1,"246":1,"248":2,"253":2,"255":3,"257":3,"258":4,"259":3,"260":1,"261":4,"262":7,"263":4,"267":1,"268":5,"269":3,"270":3,"272":5,"274":3,"275":1,"276":3,"277":3,"278":3,"279":4,"290":1,"291":4,"295":6,"298":1,"299":4,"302":1,"307":1,"310":6,"312":3,"319":1,"325":1,"329":2,"331":2,"334":1,"335":4,"336":2,"337":1,"338":4,"339":4,"340":16,"341":1,"342":1,"344":4,"345":16,"347":2,"348":1,"350":6,"352":2,"353":4,"354":8,"357":3,"358":1,"359":1,"360":1,"361":1,"362":2,"365":2,"367":2,"368":21,"369":14,"371":4,"372":4,"373":5,"374":9,"375":3,"376":7,"377":5,"378":1,"381":1,"382":3,"383":3,"384":3,"386":1,"389":1,"390":1,"391":3,"392":1,"393":1,"395":1,"400":1,"403":1,"404":2,"405":3,"406":1,"407":1,"408":1,"409":3,"410":2,"411":1,"414":6,"415":4,"416":1,"417":2,"419":2,"420":22,"421":12,"422":1},"2":{"40":1,"62":1,"420":1,"421":1}}],["op",{"1":{"290":6}}],["op=sqrt",{"1":{"290":1}}],["opt",{"1":{"290":2}}],["opts",{"1":{"256":1}}],["optionally",{"1":{"246":1}}],["optional",{"1":{"61":2,"75":3,"77":7,"217":1,"243":1,"257":1,"293":1,"303":1,"350":1,"371":1,"374":1}}],["option",{"1":{"31":1,"127":1,"272":1}}],["options=",{"1":{"76":1,"209":2}}],["options=dict",{"1":{"68":2}}],["options",{"1":{"1":1,"40":1,"99":1,"137":1,"139":1,"243":6,"367":1}}],["optimization>`",{"1":{"87":1}}],["optimization",{"1":{"87":1}}],["optimized",{"1":{"6":1}}],["optimal",{"1":{"15":1}}],["opposite",{"1":{"61":1,"294":3,"331":1}}],["opposed",{"1":{"31":1,"191":1,"217":1}}],["operand",{"1":{"49":7,"241":7},"2":{"241":1}}],["operate",{"1":{"177":1}}],["operates",{"1":{"172":1,"421":1}}],["operating",{"1":{"140":1,"199":1}}],["operational",{"1":{"233":2}}],["operation",{"0":{"4":1,"199":1},"1":{"3":1,"4":2,"10":4,"25":3,"34":1,"39":1,"48":1,"53":2,"61":1,"63":1,"66":1,"78":3,"110":1,"143":1,"144":1,"164":1,"172":2,"189":3,"190":2,"192":1,"194":2,"195":1,"196":1,"199":2,"214":1,"233":1,"238":2,"252":2,"272":7,"273":2,"277":1,"278":2,"340":2,"342":1,"344":1,"345":1,"373":1,"377":1,"389":1,"393":1},"2":{"10":1,"25":1,"144":1}}],["operations",{"0":{"238":1},"1":{"2":1,"6":1,"7":2,"9":1,"10":1,"11":2,"19":1,"23":1,"25":2,"26":1,"31":1,"32":1,"34":1,"37":1,"38":1,"49":1,"78":5,"124":1,"126":1,"135":2,"147":1,"160":1,"172":1,"174":1,"184":1,"189":1,"191":1,"192":1,"195":1,"198":1,"202":2,"204":2,"206":3,"210":1,"230":1,"231":1,"232":1,"233":1,"235":1,"236":5,"238":5,"239":22,"240":1,"242":1,"250":3,"253":1,"277":1,"310":2,"342":1,"344":1,"345":2,"349":1,"350":1,"367":1,"380":1,"421":2}}],["operator",{"0":{"28":1,"30":1},"1":{"5":2,"28":1,"30":2,"31":1,"49":7,"124":1,"147":2,"148":1,"153":1,"156":1,"184":1,"188":1,"201":1,"204":2,"224":1,"241":1,"271":1}}],["operators",{"0":{"5":1,"269":1},"1":{"5":1,"25":1,"31":1,"49":7,"223":1,"241":1,"267":1,"268":1,"269":1,"271":1,"273":2,"275":1,"308":1}}],["openvmp",{"1":{"100":2}}],["opentelemetry",{"1":{"99":1}}],["open",{"0":{"138":1},"1":{"78":1,"94":1,"99":1,"111":1,"124":1,"131":1,"137":2,"138":12,"140":2,"141":2,"189":1,"206":1,"243":1,"331":1,"364":1},"2":{"189":1}}],["opening",{"1":{"61":8,"163":1},"2":{"61":1}}],["openings=box",{"1":{"357":1}}],["openings=necktopf",{"1":{"163":2}}],["openings=vase",{"1":{"81":2}}],["openings=topf",{"1":{"160":2}}],["openings=top",{"1":{"72":2}}],["openings=tea",{"1":{"34":1,"78":2,"124":1}}],["openings",{"1":{"34":1,"78":2,"124":1,"163":1,"420":1},"2":{"160":1}}],["opencascade",{"1":{"19":1,"54":1,"128":1,"163":1,"251":1,"252":1,"369":1},"2":{"54":1}}],["openscad",{"0":{"234":1},"1":{"97":1,"126":1,"135":1,"137":1,"229":1,"230":7,"231":1,"233":2,"234":2,"250":1}}],["opens",{"1":{"6":1}}],["orthographic",{"1":{"248":1}}],["organic",{"1":{"135":1,"421":1}}],["organizes",{"1":{"344":1}}],["organize",{"1":{"268":1}}],["organized",{"1":{"108":1,"178":1,"236":1}}],["organizations",{"1":{"138":1}}],["organization",{"1":{"119":3,"417":1}}],["organizing",{"1":{"74":1,"206":2}}],["org",{"1":{"87":1,"100":3,"129":1,"163":1,"255":1,"278":1,"339":1},"2":{"163":1}}],["orient",{"1":{"201":1,"263":1}}],["orientated",{"1":{"182":1,"202":1}}],["orientations",{"0":{"335":1},"1":{"335":1}}],["orientation",{"0":{"215":1,"325":1},"1":{"110":1,"181":1,"182":1,"184":1,"201":2,"204":4,"210":1,"212":1,"214":1,"215":7,"240":1,"312":1,"316":1,"317":1,"331":3,"340":1,"352":2,"357":2,"358":1,"359":1},"2":{"181":1,"204":1,"316":1,"331":1,"340":1}}],["oriented",{"1":{"39":1,"312":1,"421":1}}],["origins",{"1":{"399":1}}],["originates",{"1":{"299":1}}],["original",{"1":{"15":1,"19":4,"26":1,"154":1,"257":1,"340":1,"359":1,"410":1,"414":1,"417":1},"2":{"19":1}}],["origin``",{"1":{"110":1}}],["origin=path",{"1":{"184":1}}],["origin=ex21",{"1":{"155":2}}],["origin=display",{"1":{"42":1}}],["origin=",{"1":{"34":1,"69":2,"70":1,"72":2,"74":4,"78":2,"110":1,"124":1,"357":1}}],["origin=l1",{"1":{"25":1}}],["origin",{"0":{"339":1},"1":{"9":1,"52":1,"75":1,"80":2,"110":1,"155":1,"201":1,"241":2,"243":7,"245":1,"257":1,"287":2,"299":3,"339":5,"345":1,"415":1},"2":{"80":1,"110":1,"243":2,"299":1}}],["ordinal",{"1":{"25":1,"31":1}}],["ordering",{"1":{"320":1}}],["order",{"1":{"13":1,"178":1,"299":1,"310":1,"378":1,"422":1}}],["or",{"1":{"2":1,"4":1,"5":2,"6":1,"7":1,"11":1,"12":2,"14":1,"24":1,"26":2,"28":1,"31":2,"36":1,"38":1,"42":1,"58":2,"74":1,"75":2,"77":1,"81":1,"90":1,"91":2,"102":1,"110":1,"123":1,"124":1,"137":2,"138":3,"139":2,"141":1,"144":6,"147":1,"149":1,"159":1,"160":2,"161":1,"171":2,"173":2,"174":1,"175":1,"177":1,"178":3,"179":1,"181":1,"182":1,"184":1,"188":3,"189":3,"192":5,"194":4,"195":2,"197":2,"198":2,"199":4,"200":1,"202":1,"204":2,"206":4,"209":1,"210":2,"219":2,"221":2,"222":2,"223":1,"224":1,"229":1,"230":3,"232":3,"233":2,"236":1,"238":4,"240":2,"241":1,"242":1,"245":1,"246":1,"248":1,"250":2,"253":3,"254":2,"255":2,"257":1,"259":1,"261":1,"267":1,"269":3,"272":2,"273":3,"274":4,"276":2,"277":1,"278":3,"290":1,"294":1,"306":3,"307":2,"308":1,"310":2,"313":1,"316":1,"324":1,"325":2,"329":3,"330":1,"336":1,"337":1,"338":1,"339":2,"340":2,"341":2,"342":2,"343":3,"344":3,"345":3,"346":1,"347":2,"350":2,"351":1,"352":1,"353":1,"354":1,"358":1,"369":2,"371":1,"378":1,"379":1,"384":1,"402":1,"405":3,"406":2,"410":2,"411":2,"412":2,"414":3,"415":1,"421":7}}],["c2",{"1":{"303":2,"304":2,"331":4},"2":{"303":1,"304":1}}],["c2c",{"1":{"74":4}}],["c=60",{"1":{"295":1}}],["c16",{"1":{"417":1}}],["c15",{"1":{"417":1}}],["c14",{"1":{"417":1}}],["c13",{"1":{"417":1}}],["c10",{"1":{"417":1}}],["c1",{"1":{"286":2,"303":2,"307":2,"331":4},"2":{"303":1}}],["c66",{"1":{"279":3,"295":1}}],["c30",{"1":{"279":2,"295":1}}],["certainly",{"1":{"259":1,"263":1}}],["certain",{"1":{"252":1,"260":1}}],["centred",{"1":{"255":1}}],["centric",{"1":{"230":1}}],["central",{"1":{"71":1,"235":1,"385":1,"392":1,"419":1,"420":1}}],["center=",{"1":{"327":1}}],["center=false",{"1":{"230":2}}],["centerline",{"1":{"61":2}}],["centers",{"0":{"48":1},"1":{"48":1,"63":2,"279":1,"289":2,"295":1,"299":1,"374":1,"376":1}}],["centerof`",{"1":{"48":2,"49":1}}],["centerof",{"1":{"44":1,"48":3},"2":{"44":1,"48":1,"49":1}}],["centered",{"1":{"32":1,"61":2,"80":1,"187":1,"188":2,"201":2,"221":1,"290":1,"368":1,"382":1}}],["centerarc`",{"1":{"49":1,"218":1,"306":1,"307":1,"310":1}}],["centerarc",{"1":{"61":1,"65":4,"225":1,"282":1,"299":1,"304":1,"317":1,"331":2},"2":{"10":1,"49":1,"61":1,"65":1,"218":1,"225":1,"282":1,"299":1,"304":1,"306":1,"307":1,"310":1,"317":1,"331":1}}],["center",{"0":{"155":1},"1":{"0":1,"16":9,"19":1,"23":1,"25":1,"26":1,"28":1,"30":1,"31":1,"32":2,"34":2,"37":1,"42":2,"48":4,"49":2,"53":1,"59":8,"60":1,"61":32,"62":19,"63":1,"64":2,"65":2,"66":1,"67":6,"68":9,"69":1,"70":1,"71":1,"72":1,"74":1,"75":2,"76":12,"77":9,"78":1,"80":4,"81":3,"110":1,"119":1,"131":8,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":2,"153":4,"154":1,"155":3,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":5,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"179":4,"182":1,"188":1,"202":1,"206":30,"218":7,"219":4,"221":1,"222":4,"225":1,"230":1,"243":5,"247":1,"256":1,"267":1,"268":1,"272":9,"273":2,"275":1,"276":1,"278":2,"279":3,"280":9,"281":1,"282":3,"283":1,"284":4,"285":1,"286":6,"287":1,"288":4,"289":5,"290":4,"291":1,"295":2,"298":1,"299":5,"304":1,"307":1,"312":1,"314":1,"315":3,"317":1,"321":1,"322":1,"323":1,"324":3,"325":1,"326":1,"327":3,"328":3,"329":2,"331":1,"332":1,"334":1,"335":1,"339":2,"340":2,"346":1,"348":1,"350":6,"357":1,"359":2,"360":1,"362":1,"363":1,"364":1,"365":1,"366":1,"368":6,"369":6,"372":1,"373":1,"374":1,"375":2,"376":2,"377":2,"379":1,"384":1,"388":1,"400":1,"401":1,"420":9},"2":{"42":1,"131":1,"155":1,"206":1,"221":1,"243":1,"280":1,"289":1,"290":1,"324":1,"327":1,"328":1}}],["csg",{"0":{"231":1,"236":1},"1":{"230":2,"231":1,"233":1,"234":1,"236":1,"250":1}}],["cd",{"1":{"128":1,"134":1}}],["cnc",{"1":{"124":1}}],["cnt",{"1":{"80":2}}],["cyl2",{"1":{"283":1}}],["cyl1",{"1":{"283":1}}],["cylindricaljoints",{"1":{"350":1}}],["cylindricaljoint",{"1":{"180":1,"184":1,"354":1},"2":{"180":1,"181":1,"351":1,"354":1,"360":1}}],["cylindricaljoint`",{"1":{"180":1,"181":1,"351":1,"354":2,"360":1}}],["cylindrical",{"0":{"180":1},"1":{"338":1,"342":1,"406":1,"411":1}}],["cylinders",{"1":{"61":1,"122":1,"198":1,"230":2,"376":1,"404":2,"405":1,"410":1,"413":1,"414":1,"415":1,"417":1}}],["cylinder`",{"1":{"49":1,"153":2,"220":1,"381":1,"387":1,"388":1}}],["cylinder",{"1":{"32":1,"34":1,"49":1,"61":1,"78":2,"108":1,"124":1,"146":2,"153":2,"155":2,"179":1,"185":1,"187":8,"189":6,"193":1,"198":1,"220":2,"227":1,"230":1,"238":2,"240":1,"241":1,"272":12,"273":2,"286":2,"350":2,"369":1,"381":2,"382":4,"385":2,"388":1,"389":1,"392":1,"421":1},"2":{"10":1,"32":1,"34":1,"49":1,"61":1,"78":1,"108":1,"124":1,"146":1,"153":1,"179":1,"185":1,"187":1,"189":1,"198":1,"220":1,"227":1,"230":1,"240":1,"272":1,"273":1,"286":1,"350":1,"369":1,"381":1,"382":1,"385":1,"387":1,"388":1,"389":1}}],["cyl",{"1":{"109":5}}],["ci",{"1":{"91":2,"134":1}}],["circuit",{"0":{"64":1},"1":{"62":1,"64":2,"73":3}}],["circumstances",{"1":{"34":1,"192":1}}],["circular",{"1":{"25":1,"37":1,"65":1,"69":1,"183":1,"211":1,"310":1,"315":1,"345":2}}],["circle`",{"1":{"49":1,"157":1,"164":2,"219":1,"222":1,"387":1}}],["circles",{"0":{"376":1,"391":1,"392":1},"1":{"30":1,"40":1,"80":1,"113":1,"149":2,"152":2,"156":2,"312":3,"368":1,"369":1,"376":4,"377":1,"392":2,"393":1,"406":1,"414":1},"2":{"312":1}}],["circle",{"1":{"4":3,"11":2,"25":1,"37":4,"42":1,"49":1,"59":4,"63":2,"64":6,"65":2,"68":9,"69":10,"70":4,"71":1,"72":2,"74":4,"80":1,"81":2,"102":1,"149":2,"152":2,"154":2,"155":4,"156":2,"157":2,"158":3,"161":2,"163":2,"164":2,"171":2,"173":4,"174":4,"179":1,"193":1,"195":1,"208":3,"219":2,"221":3,"224":4,"226":1,"238":2,"241":1,"256":1,"262":4,"266":3,"273":5,"279":2,"280":5,"282":1,"283":2,"284":4,"286":2,"287":6,"288":3,"289":5,"290":2,"299":2,"304":1,"312":1,"329":7,"331":4,"350":3,"368":2,"369":2,"376":2,"377":2,"385":1,"388":1,"389":2,"391":2,"392":1,"393":2,"394":1,"417":12},"2":{"4":1,"10":1,"11":1,"25":1,"37":2,"42":1,"49":1,"59":1,"63":1,"64":1,"65":1,"68":1,"69":1,"70":1,"71":1,"72":1,"74":1,"80":1,"149":1,"152":1,"154":1,"155":1,"156":1,"157":1,"158":1,"161":1,"163":1,"164":1,"171":1,"173":1,"174":1,"179":1,"193":1,"195":1,"208":1,"219":1,"221":1,"222":1,"224":1,"226":1,"238":1,"262":1,"279":1,"280":1,"283":1,"284":1,"286":1,"287":1,"288":1,"289":1,"299":1,"304":1,"350":1,"368":1,"369":1,"376":1,"377":1,"385":1,"387":1,"388":1,"389":1,"391":1,"417":1}}],["cmpd",{"1":{"67":2}}],["cm",{"1":{"36":1,"49":1,"69":4,"230":8,"243":3,"354":2,"356":6,"357":11,"358":1,"359":5}}],["crafted",{"1":{"291":1}}],["criteria",{"1":{"267":2,"268":2,"270":1,"271":8,"272":4,"275":1,"320":1},"2":{"320":1}}],["critical",{"1":{"157":1,"258":1,"275":1,"279":1,"295":1,"339":1,"344":1}}],["cruciform",{"1":{"70":1}}],["crucial",{"1":{"15":1,"206":1,"252":1,"336":1}}],["cross",{"1":{"34":6,"61":2,"68":2,"78":9,"110":1,"124":4,"133":1,"140":1,"290":3,"340":1},"2":{"34":1},"3":{"49":1,"71":1,"72":1,"73":1,"158":1,"190":1,"229":1,"235":1,"236":1,"238":1,"239":1,"252":1,"285":1}}],["creating",{"0":{"151":1},"1":{"11":1,"14":1,"22":1,"27":1,"31":1,"32":1,"34":1,"39":1,"66":1,"68":1,"70":1,"77":1,"78":2,"81":1,"124":2,"135":1,"139":1,"146":1,"160":1,"176":1,"184":1,"187":1,"198":1,"201":1,"206":1,"230":1,"232":1,"233":2,"235":1,"236":1,"250":1,"259":1,"262":2,"263":1,"298":1,"299":2,"307":1,"340":2,"341":1,"343":1,"345":1,"366":1,"419":1,"420":3,"421":1}}],["creation",{"1":{"7":1,"14":1,"34":1,"42":1,"63":1,"78":3,"81":1,"101":1,"123":1,"124":1,"211":1,"222":1,"278":1,"310":1,"332":1,"340":1,"420":1,"421":1}}],["creates",{"1":{"19":1,"23":1,"32":1,"37":1,"61":1,"67":1,"69":1,"71":1,"74":1,"75":1,"76":1,"144":1,"146":1,"189":1,"191":1,"198":2,"202":1,"221":1,"248":1,"276":1,"303":1,"306":1,"307":1,"313":1,"340":3,"345":4,"374":2}}],["create",{"0":{"14":1,"155":1,"160":1,"340":1,"350":1,"357":1,"359":1,"373":1,"374":1,"375":1,"381":1,"385":1,"387":1,"388":1,"401":1},"1":{"7":1,"12":2,"19":2,"23":1,"24":1,"25":3,"26":3,"32":1,"33":1,"34":3,"37":1,"38":1,"42":5,"59":1,"61":8,"62":2,"65":1,"66":2,"67":1,"68":6,"70":2,"71":1,"75":4,"77":5,"78":7,"80":6,"81":2,"94":1,"98":1,"108":2,"110":2,"124":3,"133":2,"135":1,"139":2,"141":1,"144":1,"148":1,"155":1,"156":1,"162":3,"163":1,"164":2,"165":1,"166":1,"170":4,"172":1,"174":1,"175":1,"176":2,"179":3,"182":2,"184":1,"190":1,"191":2,"193":3,"198":1,"201":3,"204":1,"206":1,"222":1,"224":1,"229":1,"230":1,"233":1,"235":3,"236":1,"237":1,"238":6,"243":1,"260":1,"270":1,"272":1,"278":4,"279":1,"295":1,"299":1,"343":1,"345":1,"348":1,"350":5,"357":1,"368":3,"369":6,"371":2,"373":4,"374":1,"375":1,"376":1,"377":1,"379":1,"382":1,"386":1,"387":1,"388":1,"395":6,"397":1,"399":1,"400":3,"401":1,"418":1,"419":1,"420":13}}],["created",{"1":{"2":1,"5":3,"23":1,"31":3,"32":1,"36":1,"37":1,"42":1,"62":1,"67":1,"74":1,"76":1,"77":1,"78":1,"100":1,"124":1,"155":1,"166":1,"181":3,"182":1,"189":4,"190":1,"191":1,"197":1,"198":2,"201":2,"202":3,"211":1,"212":1,"222":2,"235":1,"238":1,"250":1,"258":1,"262":1,"263":1,"272":3,"273":1,"338":1,"340":1,"342":1,"343":1,"344":1,"345":3,"350":1,"357":1,"358":1,"359":1,"368":1,"369":2,"370":1,"372":1,"373":1,"374":3,"376":1,"377":1,"382":1,"388":1,"420":4}}],["chord",{"1":{"398":1,"399":1}}],["choosing",{"1":{"311":1,"331":1}}],["choose",{"1":{"48":1,"127":1,"137":1,"312":1,"339":1,"354":1,"415":1}}],["choice",{"1":{"111":1,"113":1,"123":1,"135":1,"140":2,"230":1,"276":1,"319":1},"2":{"276":1}}],["chosen",{"1":{"61":1,"292":1,"319":1}}],["chimney",{"1":{"59":1}}],["child",{"1":{"20":4}}],["children=visible",{"1":{"76":1,"110":1}}],["children=screw",{"1":{"19":2}}],["children=",{"1":{"14":1,"17":3,"62":2,"67":3,"76":1,"77":1}}],["children",{"1":{"20":2,"166":1},"2":{"12":1,"14":1,"20":1}}],["cherrymx",{"1":{"70":1}}],["cherry",{"1":{"70":2}}],["cheat",{"0":{"49":1},"1":{"126":1}}],["checked",{"1":{"267":1}}],["checkout",{"1":{"129":1}}],["check",{"1":{"21":1,"49":4,"95":1}}],["championship",{"1":{"291":1}}],["chamfering",{"1":{"344":1}}],["chamfered",{"1":{"256":2}}],["chamfers",{"0":{"177":1,"253":1,"344":1},"1":{"135":1,"232":1,"233":1,"253":2}}],["chamfer",{"1":{"51":1,"144":2,"151":2,"177":2,"179":1,"239":1,"253":1,"256":1,"272":1,"273":1},"2":{"49":1,"144":1,"151":1,"177":1,"179":1,"238":1,"239":1,"256":1}}],["chamfer`",{"1":{"49":2,"177":1,"238":1}}],["challenges",{"1":{"291":4}}],["challenge",{"1":{"278":1,"279":1}}],["challenging",{"1":{"230":1,"262":1}}],["chain",{"1":{"240":1,"261":1}}],["chained",{"1":{"176":1}}],["chaining",{"1":{"7":1,"147":1},"2":{"7":1}}],["changing",{"1":{"20":1,"102":2,"139":2,"182":1,"183":1,"184":1,"217":1,"303":1,"331":1,"365":1,"378":1}}],["changes",{"1":{"19":1,"30":1,"54":1,"61":1,"86":1,"133":1,"134":4,"141":6,"204":1,"230":1,"255":1,"261":1,"310":1,"333":1,"378":1}}],["change",{"1":{"14":1,"99":1,"134":1,"183":1,"188":1,"189":1,"194":1,"204":6,"238":1,"240":1,"254":1,"258":1,"261":1,"262":1,"320":1,"331":1,"364":1}}],["changed",{"1":{"4":1,"139":1,"262":1,"272":1}}],["channel",{"1":{"71":1,"124":1,"291":1},"3":{"4":1,"16":1,"25":1,"31":1,"32":1,"34":1,"37":1,"42":1,"49":1,"51":1,"59":1,"60":1,"61":1,"62":1,"64":1,"65":1,"68":1,"69":1,"70":1,"71":1,"74":1,"76":1,"78":1,"80":1,"124":1,"144":1,"147":1,"149":1,"151":1,"152":1,"153":1,"156":1,"161":1,"164":1,"169":1,"170":1,"173":1,"174":1,"175":1,"179":1,"182":1,"184":1,"192":1,"193":1,"224":1,"229":1,"235":1,"236":1,"238":1,"239":1,"252":1,"278":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"299":1,"345":1,"346":1,"350":1,"357":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"385":1,"387":1,"388":1,"389":1,"420":1}}],["cluster",{"1":{"411":1}}],["clues",{"1":{"408":1}}],["clubs",{"1":{"76":7}}],["club",{"1":{"26":3,"76":8,"222":4},"2":{"76":1,"222":1}}],["clamp",{"0":{"283":1},"1":{"283":1,"291":1}}],["clarity",{"1":{"119":1,"196":1}}],["classic",{"0":{"163":1},"1":{"378":1}}],["class=300",{"1":{"184":1}}],["class=",{"1":{"131":1}}],["class",{"0":{"242":1},"1":{"3":1,"12":2,"13":1,"14":3,"19":3,"20":6,"31":1,"40":4,"48":2,"49":126,"52":1,"54":2,"57":2,"58":7,"59":1,"65":1,"69":1,"71":1,"75":1,"76":5,"77":2,"108":2,"109":2,"119":1,"142":1,"143":3,"144":3,"146":2,"147":1,"150":2,"152":3,"153":5,"156":1,"157":3,"159":1,"162":1,"164":6,"165":2,"166":1,"167":2,"168":1,"169":2,"170":7,"171":1,"172":3,"173":3,"174":1,"175":2,"176":1,"179":1,"180":3,"181":18,"182":2,"183":1,"184":4,"187":1,"191":2,"192":2,"204":6,"206":10,"210":2,"211":4,"217":1,"218":28,"219":18,"220":10,"222":10,"224":1,"241":5,"242":1,"247":1,"257":1,"259":1,"266":1,"271":2,"272":2,"293":4,"294":1,"295":1,"299":2,"303":2,"306":11,"307":7,"308":1,"310":14,"313":1,"314":1,"315":1,"316":1,"329":2,"330":4,"347":2,"348":2,"350":2,"351":4,"352":2,"353":4,"354":3,"355":2,"356":1,"357":3,"358":4,"359":2,"360":4,"363":1,"381":2,"382":1,"383":2,"386":1,"387":2,"388":1,"396":1,"402":1,"408":1,"410":1,"416":1,"419":4,"420":3,"421":4},"2":{"19":1}}],["classes",{"1":{"2":3,"52":1,"55":1,"57":1,"58":2,"123":2,"124":1,"186":1,"192":2,"204":3,"206":1,"222":2,"224":1,"367":1},"2":{"204":1}}],["click",{"1":{"291":1}}],["clipping",{"1":{"102":1,"104":1}}],["cli>`",{"1":{"90":1}}],["cli``",{"1":{"90":1}}],["cli",{"0":{"90":1},"1":{"90":3,"91":2}}],["clearly",{"1":{"290":1}}],["clearfix",{"1":{"259":1}}],["clear",{"1":{"124":1,"140":1,"310":1,"411":1}}],["clearances",{"1":{"313":1,"314":1}}],["clearance",{"1":{"61":1,"337":1},"2":{"61":1}}],["cleaner",{"1":{"307":1,"417":1}}],["clean",{"1":{"75":1,"124":1,"176":1,"411":1},"2":{"11":1,"75":1,"176":1}}],["clouds",{"1":{"135":1}}],["clone",{"1":{"128":1}}],["clock",{"0":{"65":1},"1":{"64":1,"65":29,"73":3,"198":1}}],["clockwise",{"1":{"49":2,"299":1}}],["closes",{"1":{"400":1}}],["close=true",{"1":{"288":1}}],["closely",{"1":{"78":1,"81":1}}],["closed=false",{"1":{"290":1}}],["closed",{"1":{"71":1,"138":2,"165":1,"172":4,"206":2,"340":2,"368":1,"395":1,"400":1,"401":1,"420":1}}],["close",{"1":{"61":1,"364":1,"396":1,"420":1,"421":1}}],["c09",{"1":{"417":1}}],["c08",{"1":{"417":1}}],["c07",{"1":{"417":1}}],["c04",{"1":{"417":1}}],["c03",{"1":{"417":1}}],["c02",{"1":{"417":1}}],["c01",{"1":{"417":1}}],["c0",{"1":{"303":1},"2":{"10":1,"303":1}}],["c^1`",{"1":{"10":1}}],["c^2`",{"1":{"10":1}}],["c^3",{"1":{"10":1}}],["c^n`",{"1":{"9":2,"10":3}}],["c^n",{"1":{"9":4,"10":7}}],["c`",{"1":{"9":3,"10":1}}],["c",{"0":{"283":1,"325":1,"326":1},"1":{"9":4,"10":2,"11":2,"148":7,"166":2,"167":3,"168":3,"173":7,"174":5,"175":8,"187":1,"224":5,"279":2,"283":1,"289":2,"291":1,"295":1,"299":10},"2":{"10":1,"294":2,"295":1,"299":1}}],["cq",{"0":{"86":1},"1":{"7":2,"51":1,"86":2,"93":2,"94":1,"178":1,"251":5}}],["cubic",{"1":{"303":1}}],["cubes",{"1":{"230":1,"234":1}}],["cube",{"1":{"75":3,"206":1,"230":3,"417":1},"2":{"75":1,"230":1}}],["cumbersome",{"1":{"230":1}}],["cumulative",{"1":{"201":1}}],["cups",{"1":{"78":1}}],["cup",{"0":{"78":1},"1":{"34":10,"36":1,"73":3,"77":1,"78":26,"124":12,"396":1}}],["curvature",{"1":{"61":2,"102":1,"218":1,"303":3,"304":3,"421":1},"2":{"304":1}}],["curve`",{"1":{"172":1,"330":1}}],["curves`",{"1":{"421":1}}],["curves",{"0":{"397":1},"1":{"61":5,"76":1,"178":1,"218":1,"233":1,"304":1,"306":1,"310":1,"312":1,"329":1,"396":1,"403":1},"2":{"421":1}}],["curved",{"0":{"279":1},"1":{"25":1,"48":1,"49":1,"60":1,"61":8,"184":1,"279":5,"291":2,"307":1,"340":1,"421":1}}],["curve",{"0":{"165":1},"1":{"10":1,"49":27,"58":1,"61":4,"67":1,"71":1,"74":1,"145":1,"148":1,"157":2,"165":2,"170":2,"172":1,"176":1,"206":1,"218":34,"222":1,"225":1,"238":1,"243":2,"278":1,"299":1,"303":3,"304":4,"306":7,"307":7,"310":10,"312":1,"315":1,"316":1,"317":1,"324":1,"329":4,"330":2,"331":3,"398":1,"402":1,"403":1},"2":{"10":1,"11":1,"58":1,"67":1,"74":1,"148":1,"172":1,"186":1,"188":1,"243":1,"304":1,"330":1},"3":{"5":1,"10":1,"25":1,"34":1,"49":1,"61":1,"62":1,"68":1,"78":1,"81":1,"124":1,"145":1,"218":1,"225":1,"241":1,"304":1,"310":1}}],["currently",{"1":{"31":1,"238":1}}],["current",{"0":{"173":1},"1":{"20":1,"31":2,"40":1,"51":1,"90":1,"194":5,"196":1,"198":2,"217":1,"238":10,"272":1}}],["cutout",{"1":{"179":1}}],["cutouts",{"1":{"76":1}}],["cutting",{"1":{"124":1,"187":1,"345":1}}],["cuts",{"1":{"80":1,"143":1}}],["cut",{"1":{"10":2,"42":1,"71":2,"144":2,"151":2,"152":2,"153":2,"162":2,"193":1,"223":1,"286":1,"345":2},"2":{"10":1,"144":1},"3":{"4":1,"16":1,"25":1,"31":1,"32":1,"34":1,"37":1,"42":1,"49":2,"51":1,"59":2,"60":1,"61":2,"62":1,"64":1,"65":1,"68":1,"69":1,"70":1,"71":1,"74":2,"76":1,"78":1,"80":2,"124":1,"144":1,"147":1,"149":1,"151":1,"152":1,"153":1,"156":1,"157":1,"161":2,"164":1,"169":1,"170":1,"173":1,"174":1,"175":1,"179":2,"182":2,"184":1,"192":1,"193":1,"224":1,"229":1,"235":1,"236":1,"238":2,"239":2,"252":1,"259":1,"278":1,"280":1,"281":2,"282":2,"283":1,"284":1,"285":1,"286":1,"287":2,"288":1,"289":2,"299":1,"345":1,"346":1,"350":1,"357":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"385":1,"387":1,"388":1,"389":1,"408":1,"409":1,"413":1,"420":1}}],["customization",{"1":{"138":2}}],["customizable",{"1":{"133":1}}],["customizable``",{"1":{"91":1}}],["customized",{"1":{"133":2,"138":1}}],["customs",{"1":{"76":1}}],["custom",{"0":{"222":1,"240":1},"1":{"2":1,"6":1,"75":1,"77":2,"84":1,"108":1,"152":2,"222":4,"240":3,"242":1,"262":2,"383":1}}],["coherent",{"1":{"402":1,"403":1},"2":{"402":1}}],["coding",{"1":{"255":1}}],["codebase",{"1":{"134":2,"141":3}}],["code=https",{"1":{"104":1}}],["code`",{"1":{"26":1}}],["code",{"0":{"98":1,"141":1,"243":1,"406":1},"1":{"3":1,"4":2,"5":2,"6":1,"7":4,"11":3,"13":1,"14":5,"16":3,"17":1,"19":2,"21":1,"23":1,"25":1,"26":7,"28":3,"30":1,"31":1,"32":2,"34":1,"36":1,"37":1,"39":3,"42":3,"50":1,"51":5,"52":3,"53":5,"56":1,"59":1,"60":1,"61":1,"62":2,"63":1,"64":2,"65":3,"66":1,"67":2,"68":2,"69":2,"70":2,"71":1,"72":2,"74":2,"75":1,"76":3,"77":1,"78":2,"80":1,"81":4,"90":1,"91":3,"94":3,"97":1,"105":1,"108":2,"109":2,"110":1,"118":1,"122":1,"124":4,"131":1,"133":9,"134":18,"138":3,"140":4,"141":7,"142":2,"143":2,"144":2,"145":2,"146":3,"147":2,"148":2,"149":2,"150":2,"151":2,"152":2,"153":2,"154":2,"155":2,"156":2,"157":2,"158":2,"159":2,"160":2,"161":2,"162":2,"163":2,"164":2,"165":2,"166":2,"167":2,"168":2,"169":2,"170":2,"171":2,"172":2,"173":2,"174":2,"175":2,"176":2,"177":2,"178":1,"179":1,"180":1,"182":3,"184":4,"185":1,"187":4,"188":8,"189":3,"190":1,"191":3,"192":1,"193":1,"195":2,"198":3,"199":2,"201":2,"202":2,"206":1,"208":3,"209":5,"210":1,"211":1,"213":4,"215":2,"216":2,"217":2,"221":2,"222":1,"224":2,"230":3,"238":2,"240":2,"243":1,"250":1,"251":2,"255":1,"256":1,"262":2,"263":1,"267":1,"268":1,"270":1,"272":6,"273":2,"275":1,"276":3,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"292":1,"295":3,"296":1,"298":1,"299":5,"304":1,"307":2,"310":2,"311":1,"314":1,"317":1,"318":1,"319":2,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"331":1,"332":1,"336":1,"340":3,"341":2,"344":3,"345":3,"346":2,"347":3,"349":1,"350":2,"352":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"362":1,"363":1,"364":1,"365":1,"367":1,"368":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"380":1,"381":1,"382":1,"385":1,"388":1,"389":1,"395":1,"397":1,"398":1,"399":1,"400":1,"401":1,"406":1,"408":1,"409":1,"410":4,"411":1,"412":1,"413":1,"414":1,"417":5,"420":7},"2":{"26":1,"56":1,"105":1,"108":1,"124":1,"406":1,"408":1,"410":1,"414":1}}],["covered",{"1":{"408":1}}],["coverage",{"1":{"134":1}}],["covers",{"1":{"119":1,"183":1,"329":1}}],["coincident",{"0":{"298":1},"1":{"154":1,"298":3,"310":1}}],["coin",{"0":{"71":1},"1":{"70":1,"71":11,"73":3}}],["coil",{"3":{"10":1,"49":1,"218":1,"225":1,"259":1}}],["costs",{"1":{"253":1}}],["cost",{"1":{"134":3,"138":2}}],["cos",{"1":{"62":2,"279":2,"295":2},"2":{"62":1,"279":1,"295":1}}],["column",{"1":{"194":1,"200":1}}],["collide",{"1":{"255":1}}],["collisions",{"1":{"255":1}}],["collision",{"1":{"135":1}}],["collaborate",{"1":{"140":1}}],["collaboration",{"1":{"113":1,"120":1,"139":1,"141":1}}],["collections",{"1":{"206":1}}],["collection",{"1":{"140":1,"145":1,"206":1,"414":1}}],["collect",{"1":{"11":1}}],["colored",{"1":{"420":1}}],["colormap",{"1":{"276":1}}],["colors=colormap",{"1":{"276":1}}],["colors",{"1":{"110":1,"113":1}}],["color=",{"1":{"76":1,"110":1,"243":1}}],["color=color",{"1":{"67":1}}],["color",{"1":{"55":1,"62":16,"63":2,"67":2,"76":10,"80":6,"108":4,"109":4,"110":1,"111":1,"121":1,"179":2,"209":2,"395":1,"401":1,"420":1},"2":{"55":1,"62":1,"63":1,"76":1,"80":1,"108":1,"179":1}}],["corresponding",{"1":{"410":1}}],["correspond",{"1":{"354":1}}],["correspondence",{"1":{"308":1}}],["corresponds",{"1":{"189":1,"339":1,"344":1}}],["correct",{"1":{"290":1,"344":1,"359":1,"417":1}}],["correctness",{"1":{"255":1}}],["correctly",{"1":{"129":1,"144":1,"189":1,"211":1}}],["corrected",{"1":{"49":1}}],["corners",{"1":{"80":1,"159":1,"182":1,"218":1,"219":1,"313":1,"344":8,"346":2,"373":2,"404":1,"417":1},"2":{"159":1}}],["corner",{"0":{"289":1},"1":{"75":2,"221":1,"243":5,"262":1,"289":1,"291":1,"303":1,"340":1,"344":1,"417":1}}],["core",{"1":{"2":2,"58":1,"69":1,"123":1,"200":1,"222":1,"252":2}}],["coordinate",{"0":{"254":1},"1":{"42":1,"61":1,"188":1,"202":1,"204":1,"208":1,"241":1,"254":3,"257":1,"262":1,"339":2,"344":1,"345":4}}],["coordinates",{"1":{"23":1,"31":4,"42":1,"202":1,"262":1,"295":1,"310":1},"2":{"23":1}}],["coords",{"1":{"39":1,"64":4},"2":{"39":1}}],["coords`",{"1":{"39":1}}],["coupled",{"1":{"310":1}}],["couple",{"1":{"34":1,"110":1,"238":1}}],["could",{"1":{"31":1,"80":1,"171":1,"177":1,"192":1,"241":1,"254":1,"255":1,"261":1,"262":1,"338":1,"343":1,"345":1,"354":2,"368":1,"369":1,"378":1,"417":1}}],["count``",{"1":{"367":1,"374":2}}],["countless",{"1":{"260":1}}],["counts=",{"1":{"109":4}}],["count=pip",{"1":{"368":1,"369":1,"376":1,"377":1}}],["count=6",{"1":{"175":2,"385":1,"388":1,"389":1}}],["count=7",{"1":{"152":2}}],["count=1",{"1":{"149":1,"368":2,"369":2,"374":1,"375":1,"376":2,"377":2}}],["count=3",{"1":{"149":1,"162":2}}],["count=4",{"1":{"146":4}}],["count=2",{"1":{"109":1,"198":2,"368":1,"369":1,"374":1,"375":1,"376":1,"377":1}}],["count=",{"1":{"109":1}}],["count=rank",{"1":{"76":1}}],["count=8",{"1":{"71":1}}],["count=exchanger",{"1":{"69":4}}],["count=5",{"1":{"11":1,"144":2,"150":2,"159":6}}],["count",{"1":{"68":8,"69":3,"72":6,"75":5,"266":3,"315":1,"367":2,"368":2,"369":3,"374":1,"375":1,"376":2,"377":2},"2":{"75":1,"367":1,"374":1}}],["counterpart",{"1":{"340":1}}],["counterparts",{"1":{"253":1}}],["counterintuitive",{"1":{"250":1}}],["counter",{"1":{"49":1,"67":6,"146":8,"220":4,"289":2}}],["countersunk",{"1":{"19":2,"351":1,"354":1,"360":3}}],["countersinkholes",{"0":{"146":1}}],["countersinkhole`",{"1":{"49":1,"220":1}}],["countersinkhole",{"1":{"146":2,"227":1,"283":1,"350":1},"2":{"10":1,"49":1,"146":1,"220":1,"227":1,"283":1,"350":1}}],["counterboreholes",{"0":{"146":1}}],["counterborehole`",{"1":{"49":1,"220":1}}],["counterborehole",{"1":{"63":1,"146":2,"227":1,"280":1,"281":1,"287":1,"289":1},"2":{"10":1,"49":1,"63":1,"146":1,"220":1,"227":1,"280":1,"281":1,"287":1,"289":1}}],["coplanar",{"1":{"333":1}}],["copied",{"1":{"77":1}}],["copies",{"0":{"19":1,"261":1},"1":{"19":4,"77":2,"261":1}}],["copyright",{"1":{"278":1}}],["copy>`",{"1":{"261":1}}],["copy",{"1":{"14":1,"19":13,"55":6,"58":1,"60":4,"73":1,"77":9,"81":1,"184":3,"204":2,"213":2,"261":1,"278":1},"2":{"19":1,"60":1,"77":1,"184":1}}],["conics",{"1":{"307":1}}],["conical",{"1":{"158":1,"342":1}}],["conditions",{"1":{"278":1,"306":1,"322":1}}],["condition",{"1":{"267":1,"307":1}}],["concise",{"1":{"421":1}}],["conclusion",{"0":{"229":1,"347":1,"378":1}}],["concepts",{"0":{"185":1,"186":1,"196":1,"197":1,"203":1},"1":{"126":3,"156":1,"177":1,"186":1,"197":1,"203":1,"422":2},"2":{"186":1,"197":1}}],["concept",{"1":{"60":1,"123":1,"210":1}}],["connector",{"1":{"304":4}}],["connects",{"1":{"235":1}}],["connected",{"1":{"147":1,"176":1,"181":1,"182":1,"206":3,"276":1,"340":1,"359":1,"360":1,"361":1,"362":2,"363":1,"364":1}}],["connection",{"1":{"303":1,"345":1}}],["connecting",{"1":{"140":2,"184":1}}],["connectivity",{"1":{"112":1}}],["connect",{"0":{"361":1},"1":{"77":3,"80":2,"179":4,"180":4,"181":1,"182":5,"183":4,"184":12,"290":1,"345":1,"350":1,"362":1,"363":1,"364":1,"365":1,"421":1},"2":{"77":1,"80":1,"179":1,"180":1,"182":1,"183":1,"184":1,"347":1,"362":1,"363":1,"364":1,"365":1}}],["congruent",{"1":{"75":1}}],["conflicts",{"1":{"255":1}}],["conflicting",{"1":{"129":1}}],["confusing",{"1":{"255":1}}],["confusion",{"1":{"254":1}}],["conformal",{"1":{"61":1}}],["conform",{"1":{"61":1}}],["configuration",{"1":{"51":1,"99":1}}],["convention",{"1":{"177":1,"294":1,"339":1}}],["conventions",{"1":{"119":2,"299":1}}],["convenience",{"1":{"98":1,"395":1}}],["convenient",{"0":{"339":1},"1":{"31":1,"42":1,"98":1,"415":1,"416":1,"420":1}}],["convexhull",{"1":{"75":2},"2":{"75":1}}],["convex",{"1":{"75":3,"220":2,"235":1,"238":1}}],["convexpolyhedron",{"1":{"227":1},"2":{"49":1,"220":1,"227":1}}],["convexpolyhedron`",{"1":{"49":1,"220":1}}],["converter",{"1":{"415":1}}],["converted",{"1":{"31":2,"135":1,"191":1,"276":1,"299":1,"303":1}}],["converts",{"1":{"235":1}}],["converting",{"1":{"235":1}}],["convert",{"1":{"172":2,"238":1,"341":1,"375":1}}],["conversions",{"1":{"31":1,"124":1},"2":{"124":1}}],["consuming",{"1":{"147":1}}],["consumed",{"1":{"91":1,"97":1,"99":1}}],["consumes",{"1":{"25":1}}],["consortium",{"1":{"111":1}}],["constant",{"1":{"313":1,"314":1,"419":1,"420":1}}],["constants",{"1":{"36":1}}],["construct",{"1":{"174":1,"200":1,"206":1,"245":1,"295":1,"306":1,"308":1,"310":1,"329":1,"403":1,"421":1}}],["constructive",{"0":{"231":1},"1":{"230":1,"231":1,"234":1,"250":1}}],["constructing",{"1":{"78":1,"189":1,"200":1,"235":1,"236":1}}],["constructions",{"1":{"307":1,"327":1,"328":1,"329":1}}],["construction",{"0":{"400":1},"1":{"31":1,"80":1,"196":1,"211":1,"223":6,"282":1,"286":1,"295":1,"299":2,"302":1,"306":1,"310":1,"312":1,"313":1,"318":1,"319":1,"329":1,"331":1,"332":1,"388":1,"406":2,"414":1,"417":1,"421":1}}],["constructors",{"1":{"299":1,"306":1,"307":1,"310":2,"330":1}}],["constructor",{"1":{"66":1,"306":2,"319":1,"333":1}}],["constructed",{"1":{"34":1,"39":1,"42":1,"182":1,"234":1,"252":1,"357":1,"419":1}}],["constructs",{"1":{"20":1,"66":1,"294":1}}],["constraint",{"0":{"293":1,"302":1,"323":1,"325":1,"327":1,"328":1},"1":{"298":1,"310":3,"311":1,"318":1,"329":1}}],["constraints",{"0":{"27":1,"294":1,"295":1,"303":1,"304":1,"305":1,"306":1,"307":1,"308":1,"309":1,"313":1,"314":1,"321":1,"322":1,"324":1,"326":1,"329":1,"330":1},"1":{"26":1,"27":2,"28":1,"30":1,"134":1,"139":2,"236":1,"293":1,"303":2,"310":3,"312":1,"329":1,"331":1,"422":1},"2":{"331":1}}],["constrainedlines",{"0":{"301":1},"1":{"225":1,"321":1,"323":1,"325":1},"2":{"49":1,"218":1,"225":1,"310":1,"316":1,"321":1,"323":1,"325":1,"329":1,"330":1}}],["constrainedlines`",{"1":{"49":1,"218":1,"310":1,"316":1,"329":1,"330":1}}],["constrainedarcs",{"0":{"300":1},"1":{"225":1,"292":1,"296":1,"299":2,"311":3,"319":2,"322":1,"324":1,"326":1,"327":1,"328":1,"331":2},"2":{"49":1,"218":1,"225":1,"292":1,"296":1,"299":1,"310":1,"311":1,"315":1,"319":1,"322":1,"324":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1}}],["constrainedarcs`",{"1":{"49":1,"218":1,"299":1,"310":1,"315":1,"329":1,"330":1}}],["constrained",{"1":{"15":1,"218":4,"299":2,"302":1,"310":2,"315":2,"329":2}}],["considered",{"1":{"31":1,"138":1,"254":1}}],["consider",{"1":{"19":1,"34":1,"48":1,"184":1,"256":1,"262":1,"326":1,"337":1,"417":1}}],["considerations",{"0":{"11":1}}],["consists",{"1":{"340":1,"373":1,"404":1,"420":1}}],["consistency",{"1":{"119":1,"133":1}}],["consistently",{"1":{"403":1,"404":1,"421":1}}],["consistent",{"1":{"61":1,"133":2,"139":1,"140":1,"206":1}}],["consist",{"1":{"12":1}}],["cone`",{"1":{"49":1,"220":1}}],["cone",{"1":{"49":1,"108":1,"109":5,"220":2,"227":1,"241":1},"2":{"10":1,"49":1,"108":1,"220":1,"227":1}}],["continue",{"1":{"418":1}}],["continuity=continuitylevel",{"1":{"304":2}}],["continuity",{"0":{"303":1,"304":1},"1":{"303":5,"304":2,"332":1,"421":1}}],["continuous",{"1":{"134":2,"206":1,"421":1}}],["contents",{"0":{"126":1},"1":{"178":1}}],["content",{"1":{"117":2,"263":1,"291":1}}],["contexts",{"1":{"40":2,"49":1,"166":1,"198":2,"218":1,"272":1,"374":1},"2":{"40":1}}],["context",{"0":{"7":1,"198":1,"272":1},"1":{"3":1,"7":1,"23":3,"24":1,"26":2,"32":3,"33":1,"34":1,"37":3,"38":1,"40":2,"47":1,"51":3,"64":1,"143":1,"184":1,"189":1,"197":1,"198":3,"202":1,"206":2,"235":1,"255":1,"270":7,"272":5,"296":1,"303":1,"311":1,"319":1,"340":2,"341":1,"343":1,"345":4,"359":1,"368":2,"371":1,"374":1,"376":1},"2":{"189":1,"374":1}}],["contact",{"1":{"259":1,"315":5,"316":3,"322":1,"326":1,"330":1}}],["contacts",{"1":{"34":1,"78":2,"124":1}}],["containing",{"1":{"330":1}}],["container",{"1":{"206":3}}],["containers",{"1":{"17":1}}],["contain",{"1":{"58":1,"222":2,"270":1,"415":1}}],["contains",{"1":{"57":1,"100":1,"189":1,"221":1,"222":1,"353":1,"405":1,"412":2}}],["contrast",{"1":{"230":1}}],["contributors",{"1":{"54":1}}],["contribute",{"1":{"23":1,"32":1,"37":1,"140":1,"141":1,"299":1}}],["controls",{"1":{"98":2,"124":1,"223":1,"304":1,"373":2,"396":1,"420":1}}],["controlled",{"1":{"313":1,"325":1,"417":1}}],["controller",{"1":{"42":9}}],["controlling",{"1":{"61":1}}],["control",{"0":{"141":1},"1":{"34":1,"42":1,"78":2,"104":1,"124":1,"141":10,"169":2,"194":1,"196":1,"218":2,"236":2,"257":1,"303":1,"310":1,"319":1,"357":1,"421":2},"3":{"5":1,"10":1,"25":1,"34":1,"49":1,"61":1,"62":1,"68":1,"78":1,"81":1,"124":1,"145":1,"218":1,"225":1,"241":1,"304":1,"310":1}}],["comfortably",{"1":{"405":1}}],["comfortable",{"1":{"141":1}}],["comb``",{"1":{"304":1}}],["comb",{"1":{"304":4},"2":{"304":1}}],["combination",{"0":{"192":1},"1":{"194":1,"204":1,"319":1}}],["combing",{"0":{"185":1}}],["combines",{"1":{"124":1,"210":1}}],["combine",{"0":{"343":1},"1":{"75":1,"77":1,"80":1,"148":1,"201":1,"223":1,"232":1,"234":1,"278":1,"341":1,"342":1}}],["combined=part",{"1":{"273":2}}],["combined",{"1":{"39":1,"185":1,"192":1,"194":1,"204":1,"210":1,"222":1,"223":1,"250":1,"273":3,"419":1}}],["combining",{"1":{"37":1,"180":1,"184":1,"194":1,"204":1,"230":1,"231":1,"343":1}}],["comes",{"1":{"413":1}}],["come",{"1":{"250":1,"331":1,"421":1}}],["com",{"1":{"59":1,"73":1,"82":1,"85":1,"86":1,"87":5,"90":2,"91":5,"93":2,"94":2,"95":1,"99":1,"101":1,"102":1,"104":2,"124":2,"128":2,"129":3,"130":1,"181":1,"251":1,"291":1,"299":1,"396":1,"420":1}}],["comprehensive",{"1":{"112":1,"233":1}}],["comprehensions",{"1":{"144":1,"174":1,"175":1}}],["comprehension",{"1":{"11":1,"267":1}}],["compilation",{"1":{"99":1}}],["computes",{"1":{"295":1}}],["compute",{"1":{"290":1}}],["computer",{"1":{"19":1,"102":1,"112":2,"113":1,"119":1,"120":2,"121":1,"123":1,"140":1}}],["computational",{"1":{"206":1,"237":1}}],["computationally",{"1":{"66":1,"230":1,"236":2}}],["computing",{"1":{"140":1}}],["complicated",{"1":{"253":1}}],["compliant",{"1":{"124":1}}],["compliance",{"1":{"54":1,"278":1}}],["complementary",{"1":{"410":1}}],["completely",{"1":{"272":1}}],["completes",{"1":{"66":1,"369":1}}],["completed",{"1":{"42":1,"51":3,"194":1}}],["complete",{"0":{"395":1},"1":{"19":1,"24":1,"33":1,"38":1,"42":2,"80":1,"141":1,"241":2,"259":1,"340":1,"356":1,"368":1,"376":1,"377":1,"419":1,"420":1}}],["complexity",{"1":{"61":2,"66":1,"236":1,"237":1,"253":2}}],["complex",{"0":{"299":1},"1":{"7":1,"17":1,"48":1,"61":1,"62":1,"74":1,"78":1,"80":1,"108":1,"111":1,"112":1,"117":1,"120":1,"121":1,"135":1,"140":1,"145":1,"172":1,"178":1,"200":1,"204":1,"206":7,"230":2,"233":2,"235":1,"236":2,"237":1,"240":1,"250":1,"252":1,"278":1,"299":4,"341":1,"343":1,"353":1,"420":1,"421":1}}],["comparing",{"1":{"273":1}}],["comparison",{"0":{"230":1}}],["compares",{"1":{"273":1}}],["compared",{"1":{"66":1,"133":2,"230":1}}],["compare",{"1":{"17":1,"49":1,"230":1}}],["companies",{"1":{"138":1}}],["company",{"1":{"133":2,"138":3}}],["compatibility",{"1":{"138":1}}],["compatible",{"1":{"61":1}}],["compact",{"1":{"18":1,"111":1,"117":1,"135":1}}],["component",{"1":{"148":1,"179":1,"180":1,"182":1,"183":1,"201":1,"204":1}}],["components",{"1":{"13":1,"83":1,"108":2,"182":1,"184":1,"206":1,"209":1,"339":1,"420":1}}],["compose",{"1":{"206":1,"310":1}}],["composable",{"1":{"124":1}}],["composition",{"1":{"124":1}}],["composite",{"1":{"58":1}}],["compounds",{"0":{"17":1},"1":{"17":3,"206":1,"394":1}}],["compound",{"0":{"14":1},"1":{"14":8,"17":3,"19":2,"21":2,"48":1,"57":1,"58":1,"62":2,"67":5,"76":3,"77":1,"110":1,"181":1,"188":3,"206":1,"208":4,"350":1},"2":{"12":1,"14":1,"17":1,"19":1,"20":1,"21":1,"58":1,"62":1,"67":1,"76":1,"110":1,"187":1,"191":1,"192":1,"206":1,"360":1}}],["compound``",{"1":{"187":1}}],["compound`",{"1":{"12":2,"14":3,"20":1,"58":2,"206":1,"360":1}}],["comments",{"1":{"133":2}}],["committed",{"1":{"134":1}}],["commit",{"1":{"129":1}}],["community",{"1":{"138":6,"140":2,"141":1}}],["communicate",{"1":{"119":1}}],["communication",{"1":{"111":1}}],["commutative",{"1":{"10":1}}],["commands",{"1":{"128":1,"129":1,"148":2}}],["command",{"1":{"90":1,"91":1,"128":1,"129":3,"131":1,"141":2,"340":1,"345":1,"379":2}}],["commonly",{"1":{"30":1,"74":1,"160":1,"191":1,"192":1,"211":1,"255":1,"313":1}}],["common",{"0":{"43":1},"1":{"6":1,"19":1,"40":4,"43":1,"45":4,"46":5,"49":16,"65":1,"69":1,"78":1,"144":2,"146":2,"152":2,"156":1,"166":1,"173":1,"174":1,"189":1,"194":1,"211":4,"238":10,"239":10,"251":1,"257":1,"263":1,"310":1,"314":1,"329":1,"350":1,"404":1,"408":1},"2":{"45":1,"46":1}}],["careful",{"1":{"413":1}}],["carbon",{"1":{"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["cards",{"0":{"76":1},"1":{"73":3,"75":1,"76":1,"222":2}}],["card",{"1":{"49":21,"73":22,"76":18,"218":28,"219":18,"220":10,"222":2,"264":4,"265":3,"266":6,"291":13}}],["categories",{"1":{"271":1}}],["cater",{"1":{"141":1}}],["causes",{"1":{"374":1,"377":1}}],["caused",{"1":{"253":1}}],["cause",{"1":{"134":1,"255":1}}],["cae",{"1":{"112":1,"120":1}}],["camera",{"1":{"110":4,"124":1,"245":1,"249":1,"396":1,"420":1}}],["cam>`",{"1":{"93":2}}],["cam",{"0":{"93":1},"1":{"93":3,"120":1}}],["cached",{"1":{"410":1}}],["cached``",{"1":{"91":1}}],["cache",{"0":{"416":1},"1":{"90":1,"413":1}}],["cab",{"1":{"80":16}}],["cascade",{"1":{"124":1}}],["castable",{"1":{"63":1}}],["cast",{"0":{"63":1},"1":{"63":1,"67":1,"73":3,"238":1}}],["cases",{"1":{"97":2,"141":1,"171":1,"202":1,"331":1,"411":1}}],["case",{"1":{"19":2,"36":1,"66":1,"141":1,"144":1,"147":2,"153":2,"158":2,"160":1,"161":1,"177":1,"222":1,"245":1,"262":1,"267":1,"269":1,"272":1,"312":1,"360":1,"369":3,"373":1,"374":2,"420":1}}],["capability",{"1":{"267":1}}],["capabilities",{"1":{"230":1,"233":2,"235":1}}],["cap",{"0":{"70":1,"282":1,"290":1,"401":1},"1":{"61":2,"69":1,"70":22,"73":3,"282":1,"290":1,"291":2,"401":1}}],["caps",{"1":{"61":1,"69":1}}],["captures",{"1":{"344":1}}],["captured",{"1":{"275":2}}],["capture",{"1":{"27":1,"275":1}}],["calculations",{"1":{"135":1}}],["calculating",{"1":{"15":1,"28":1}}],["calculate",{"1":{"62":2,"64":1,"66":1,"354":1,"395":1,"398":1}}],["calculated",{"1":{"28":2,"30":1,"31":1}}],["callback",{"1":{"311":1}}],["callable",{"1":{"271":4,"276":1}}],["calling",{"1":{"268":1}}],["calls",{"1":{"167":1,"222":1,"306":1}}],["call",{"0":{"355":1},"1":{"11":2,"157":1,"296":1,"304":1,"306":1,"332":1,"333":1,"410":1}}],["called",{"1":{"11":1,"157":1,"189":1,"222":1}}],["cad",{"0":{"48":1,"104":1,"235":1},"1":{"12":1,"19":3,"48":1,"49":4,"55":1,"78":1,"87":1,"92":1,"93":1,"94":2,"95":1,"97":2,"104":4,"112":2,"113":3,"119":2,"120":2,"121":1,"123":1,"124":3,"130":1,"134":1,"135":11,"139":10,"140":2,"141":2,"181":1,"197":1,"202":1,"206":1,"230":2,"235":1,"250":1,"252":3,"255":3,"258":1,"277":1,"278":1,"291":4,"299":1,"310":2,"340":1,"346":1,"349":1,"350":1,"367":1,"378":1,"380":1,"415":1,"421":1},"2":{"94":1,"123":1}}],["cadquery>`",{"1":{"87":1}}],["cadquery",{"0":{"132":1,"251":1},"1":{"2":1,"7":1,"54":2,"85":1,"87":2,"93":1,"94":1,"97":1,"104":1,"124":1,"128":1,"140":1,"191":2,"251":7}}],["cannot",{"1":{"421":1}}],["candidate",{"1":{"306":1,"331":1,"414":1}}],["candidates",{"1":{"296":1}}],["canadian",{"0":{"62":1},"1":{"62":8,"63":1,"73":3}}],["can",{"0":{"252":1},"1":{"2":1,"3":1,"4":1,"7":2,"12":1,"13":1,"14":2,"17":1,"19":1,"20":1,"21":1,"22":1,"28":3,"34":3,"36":1,"39":2,"42":1,"48":1,"51":1,"53":2,"61":3,"75":1,"91":1,"97":1,"99":1,"102":2,"108":1,"110":3,"113":1,"121":1,"122":1,"123":2,"124":3,"128":2,"129":4,"131":1,"133":13,"134":12,"135":4,"138":7,"139":6,"140":2,"141":5,"143":1,"144":7,"147":1,"149":1,"158":2,"159":3,"160":4,"161":1,"164":2,"166":1,"171":1,"173":2,"174":2,"175":2,"177":1,"178":4,"181":2,"182":1,"184":1,"185":1,"187":4,"188":2,"189":1,"190":1,"191":1,"192":1,"194":1,"197":2,"198":2,"201":3,"202":2,"204":1,"206":4,"210":2,"218":1,"221":1,"222":3,"230":1,"232":1,"233":2,"235":1,"236":2,"237":1,"238":3,"240":2,"249":1,"250":1,"252":1,"253":2,"257":2,"258":3,"260":1,"261":1,"262":1,"267":2,"268":5,"269":1,"270":1,"272":2,"273":1,"275":3,"276":3,"295":2,"306":1,"307":1,"310":3,"311":1,"312":2,"313":1,"325":1,"326":1,"329":1,"331":1,"335":2,"336":1,"340":1,"341":1,"342":1,"343":1,"347":1,"350":1,"356":1,"360":2,"361":1,"363":1,"369":1,"374":1,"379":1,"391":1,"409":1,"413":1,"416":1,"420":4}}],["tp",{"1":{"290":1}}],["tp=sqrt",{"1":{"290":1}}],["tpd",{"1":{"119":1}}],["tttt",{"1":{"422":1}}],["ttt",{"0":{"291":1},"1":{"278":4,"279":3,"280":2,"281":3,"282":4,"283":3,"284":3,"285":3,"286":3,"287":3,"288":3,"289":3,"290":3,"291":41}}],["tmp",{"1":{"276":2}}],["tmp28",{"1":{"162":2}}],["txt",{"1":{"189":1}}],["txt=rank",{"1":{"76":2}}],["t1",{"1":{"67":5}}],["tessellated",{"1":{"410":1,"412":1}}],["tested",{"1":{"138":1}}],["tests",{"1":{"134":8}}],["testing",{"0":{"134":1},"1":{"134":6}}],["test",{"0":{"131":1,"337":1},"1":{"61":1,"108":1,"189":1}}],["tempfile",{"1":{"276":1}}],["temporarydirectory",{"1":{"276":2},"2":{"276":1}}],["temporary",{"1":{"189":1}}],["terminate",{"1":{"307":1}}],["terminated",{"1":{"307":1}}],["termination",{"0":{"306":1,"307":1}}],["term",{"1":{"255":1}}],["terms",{"1":{"138":1}}],["tech",{"1":{"219":1,"422":1}}],["technical",{"0":{"248":1},"1":{"119":4,"219":1,"243":1,"246":1,"247":1,"248":1}}],["technicaldrawing",{"1":{"226":1,"243":1},"2":{"49":1,"219":1,"226":1,"243":1}}],["technicaldrawing`",{"1":{"49":1,"219":1}}],["techniques",{"1":{"50":3,"61":1,"78":1,"80":1,"81":1,"159":1,"260":2,"299":1,"419":1,"421":1}}],["technique",{"1":{"36":1,"53":1,"78":1,"403":1,"421":1}}],["tension",{"1":{"303":1}}],["tens",{"1":{"261":1}}],["tensorflow",{"1":{"140":1}}],["ten",{"1":{"76":3}}],["tetrahedron",{"1":{"75":3},"2":{"75":1}}],["teams",{"1":{"140":1}}],["team",{"1":{"139":1}}],["teacup",{"1":{"124":1}}],["tea",{"0":{"78":1},"1":{"34":8,"36":1,"73":3,"77":1,"78":21,"124":10,"396":1}}],["textures",{"1":{"117":1}}],["texture",{"1":{"111":1}}],["textalign",{"2":{"49":1}}],["textalign`",{"1":{"49":1}}],["text`",{"1":{"49":1,"219":1}}],["text",{"0":{"169":1,"228":1},"1":{"61":6,"65":2,"67":19,"71":3,"76":2,"113":1,"123":2,"169":12,"189":4,"219":2,"226":1,"228":1,"243":3},"2":{"10":1,"49":1,"61":1,"65":1,"67":1,"71":1,"76":1,"169":1,"219":1,"226":1,"243":1}}],["typical",{"1":{"61":1,"66":1,"308":1}}],["typically",{"1":{"24":1,"33":1,"38":1,"138":3,"204":1,"235":1,"243":1,"275":1,"310":1,"312":1,"410":1}}],["typing",{"1":{"34":1,"75":1,"76":1,"255":1}}],["type=",{"1":{"108":1,"124":1,"396":1,"420":1}}],["type=linetype",{"1":{"76":1,"110":1,"243":1}}],["typefaces",{"1":{"102":1}}],["types",{"0":{"302":1},"1":{"19":1,"48":1,"55":1,"110":1,"119":5,"140":1,"141":1,"206":1,"219":1,"241":1,"348":1,"353":1}}],["type",{"1":{"12":1,"27":1,"51":1,"72":1,"73":22,"81":2,"119":1,"124":1,"131":1,"194":1,"264":4,"265":3,"266":6,"274":1,"291":13,"318":1,"354":1,"391":1},"2":{"51":1}}],["tiny",{"1":{"412":1}}],["tight",{"1":{"420":1,"421":1}}],["tighten",{"1":{"365":1}}],["tightly",{"1":{"310":1}}],["tie",{"0":{"288":1,"289":1},"1":{"288":1,"289":1,"291":2}}],["title",{"1":{"245":1}}],["title=",{"1":{"243":2}}],["tire",{"0":{"60":1},"1":{"59":1,"60":9,"73":3}}],["tips",{"0":{"233":1,"260":1,"402":1},"1":{"61":1,"126":1}}],["tip",{"0":{"21":1,"398":1,"399":1},"1":{"61":34,"395":10,"396":1,"397":1,"398":4,"399":3,"400":4}}],["timed",{"1":{"94":1}}],["timer",{"1":{"66":2},"2":{"66":1}}],["timeit",{"1":{"66":3}}],["time",{"1":{"19":1,"66":4,"133":2,"134":3,"135":2,"139":2,"140":1,"141":2,"147":1,"164":2,"184":1,"202":1,"310":1,"340":1}}],["times",{"1":{"9":4,"10":2,"261":1}}],["tune",{"1":{"303":1}}],["tube",{"1":{"69":44}}],["tubes",{"1":{"69":6}}],["turning",{"0":{"414":1},"1":{"341":1}}],["turn",{"1":{"61":1,"150":1}}],["turned",{"3":{"34":1,"38":1,"49":1,"60":1,"71":1,"78":1,"81":1,"124":1,"147":1,"157":1,"171":1,"179":1,"182":1,"238":1,"239":1,"250":1,"282":1,"290":1,"342":1}}],["tuples",{"1":{"31":3,"40":1,"352":1},"2":{"352":1}}],["tuple",{"1":{"20":3,"59":2,"67":1,"75":2,"76":5,"77":2,"109":4,"110":1,"147":1,"201":1,"202":1,"222":1,"243":2},"2":{"59":1,"109":1}}],["tutorials",{"0":{"291":1,"422":1},"1":{"126":1,"421":1,"422":3}}],["tutorial`",{"1":{"122":1,"183":1,"415":1}}],["tutorial>`",{"1":{"12":1}}],["tutorial",{"0":{"248":1,"348":1,"366":1,"379":1,"403":1,"415":1,"420":1},"1":{"12":1,"180":1,"345":1,"348":2,"350":3,"357":1,"359":1,"360":1,"362":1,"363":1,"364":1,"365":1,"366":1,"379":2,"403":1,"415":2,"417":1,"419":1,"420":1,"421":2,"422":8}}],["tshape",{"2":{"19":1}}],["t",{"0":{"252":1,"254":1,"255":1,"262":1,"279":1},"1":{"13":1,"39":1,"60":4,"61":1,"110":1,"163":6,"176":14,"182":1,"189":1,"192":2,"194":1,"197":1,"198":1,"223":2,"254":1,"257":2,"263":1,"272":2,"278":1,"279":2,"280":1,"290":2,"291":3,"367":1,"369":1,"420":1}}],["troubleshooting",{"0":{"333":1}}],["trying",{"1":{"405":1}}],["try",{"0":{"249":1},"1":{"67":1,"75":1,"365":1}}],["truck",{"0":{"80":1},"1":{"73":3,"78":1,"80":10,"104":1}}],["truly",{"1":{"61":1}}],["truncated",{"1":{"61":1}}],["true",{"1":{"61":2,"67":1,"70":2,"192":1,"241":1,"253":1,"254":1,"256":1,"350":2},"2":{"259":1}}],["truediv",{"1":{"55":1}}],["triad",{"1":{"208":4},"2":{"208":1}}],["triangulated",{"1":{"415":1}}],["triangular",{"1":{"75":3,"121":1,"162":2,"276":1}}],["triangles",{"1":{"135":2,"166":1,"415":1}}],["triangle`",{"1":{"49":1,"219":1,"294":1,"295":1,"310":1}}],["triangle",{"1":{"48":1,"109":2,"219":2,"226":1,"290":1,"294":1,"295":3},"2":{"49":1,"219":1,"226":1,"294":1,"295":1,"310":1}}],["tricky",{"1":{"257":1}}],["trick",{"1":{"61":1}}],["trimming",{"1":{"307":1}}],["trims",{"1":{"306":1}}],["trim",{"1":{"299":1,"306":1,"307":1,"331":2},"2":{"299":1,"307":1,"331":1},"3":{"49":1,"59":1,"61":1,"74":1,"80":1,"157":1,"161":1,"179":1,"182":1,"238":1,"239":1,"259":1,"281":1,"282":1,"287":1,"289":1,"408":1,"409":1,"413":1}}],["trailing",{"1":{"395":10,"396":1,"397":6,"398":4,"400":2}}],["traversal",{"1":{"299":1,"331":1}}],["traversing",{"1":{"277":1,"331":1}}],["traditional",{"0":{"235":1},"1":{"111":1,"230":1}}],["trace",{"1":{"239":1},"2":{"49":1,"238":1,"239":1}}],["trace`",{"1":{"49":1,"238":1}}],["track",{"1":{"13":1,"34":1,"139":1,"141":1,"272":1}}],["transmission",{"1":{"117":2}}],["transparency",{"1":{"104":1}}],["transitions",{"1":{"235":1,"304":1,"421":1}}],["transitioning",{"0":{"233":1,"234":1},"1":{"237":1}}],["transition`",{"1":{"49":1}}],["transition",{"0":{"236":1,"237":1},"1":{"44":1,"71":1,"303":2},"2":{"44":1,"49":1},"3":{"49":1,"71":1,"72":1,"73":1,"158":1,"190":1,"229":1,"235":1,"236":1,"238":1,"239":1,"252":1,"285":1}}],["translation",{"0":{"217":1},"1":{"204":1,"217":1}}],["translating",{"1":{"26":1}}],["translate",{"1":{"26":1,"217":1,"230":3,"257":1,"395":2,"399":2},"2":{"217":1,"230":1,"395":1,"399":1}}],["translated",{"1":{"15":1,"243":1,"358":1}}],["transforming",{"1":{"231":1,"235":1,"253":1}}],["transformation",{"0":{"217":1},"1":{"237":1}}],["transformations",{"1":{"204":1,"206":1,"212":1,"245":1}}],["transforms",{"1":{"81":1}}],["transformed",{"1":{"49":1,"159":2,"160":1,"230":1,"235":1}}],["transform",{"1":{"26":1,"217":1,"238":1,"339":1},"2":{"217":1}}],["transferring",{"1":{"251":1}}],["transferred",{"1":{"25":2}}],["transfers",{"1":{"190":1}}],["transfer",{"1":{"26":1,"181":1,"377":1}}],["trapezoid`",{"1":{"49":1,"219":1}}],["trapezoid",{"1":{"60":1,"80":4,"219":2,"226":1,"280":4},"2":{"10":1,"49":1,"60":1,"80":1,"219":1,"226":1,"280":1}}],["trend",{"1":{"303":1,"304":1}}],["treat",{"1":{"406":1,"413":1}}],["treated",{"1":{"12":1,"414":1}}],["tread",{"1":{"60":18}}],["tree",{"1":{"12":1,"20":3,"73":1}}],["tasked",{"1":{"291":1}}],["tasks",{"1":{"112":1,"139":1,"140":2,"141":1}}],["tan3",{"1":{"326":1}}],["tan2",{"1":{"321":1,"322":1,"324":1}}],["tangency",{"0":{"329":1,"330":1,"331":1},"1":{"293":1,"312":2,"315":5,"319":1,"321":2,"322":3,"323":1,"324":2,"325":2,"326":3,"327":1,"328":1,"329":1,"330":1,"331":5,"421":1},"2":{"331":1}}],["tangent=",{"1":{"67":4,"71":1,"74":2,"147":2,"184":1,"290":1}}],["tangent=l3",{"1":{"74":2}}],["tangent=l1",{"1":{"71":1,"74":2,"147":2,"290":1,"332":1}}],["tangent=l6",{"1":{"62":2}}],["tangent=l2",{"1":{"30":1,"31":1,"62":2}}],["tangential",{"1":{"27":1}}],["tangentarc`",{"1":{"49":1,"218":1}}],["tangentarc",{"1":{"62":4,"67":4,"184":1,"225":1,"290":2},"2":{"10":1,"49":1,"62":1,"67":1,"184":1,"218":1,"225":1,"290":1}}],["tangents=",{"1":{"5":1,"25":1,"34":2,"61":1,"62":2,"68":2,"78":4,"81":4,"124":2}}],["tangents",{"1":{"5":2,"34":1,"61":2,"78":2,"124":1,"290":1,"303":1}}],["tangent",{"0":{"332":1},"1":{"5":1,"30":3,"34":1,"49":3,"61":2,"62":2,"68":2,"78":2,"124":1,"147":1,"218":14,"289":2,"290":7,"303":3,"304":2,"308":2,"310":2,"312":2,"316":3,"317":2,"326":1,"329":1,"330":1,"331":1,"332":4},"2":{"30":2,"49":1,"61":1,"147":1,"289":2,"304":1,"317":1}}],["tan",{"1":{"279":2,"295":2,"323":1,"328":1},"2":{"279":1,"295":1}}],["tall",{"0":{"291":1},"1":{"278":1,"279":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"291":2}}],["tally",{"1":{"189":1}}],["taking",{"1":{"255":1,"270":1,"369":1}}],["taken",{"1":{"147":2,"254":1}}],["take",{"1":{"135":1,"190":1,"224":1,"233":1,"238":1,"240":1,"267":1,"271":2,"272":1,"368":1}}],["takes",{"1":{"11":2,"19":2,"28":1,"147":2,"158":1,"345":1}}],["tags",{"1":{"378":1}}],["tag",{"1":{"75":1,"77":1}}],["tapered",{"1":{"80":1}}],["taper=",{"1":{"287":1}}],["taper=2",{"1":{"80":1}}],["taper=4",{"1":{"80":1}}],["taper=15",{"1":{"70":2}}],["taper",{"1":{"70":2,"238":1}}],["tabs",{"1":{"182":1,"350":1}}],["tab",{"1":{"51":1,"278":10}}],["tables",{"0":{"125":1},"1":{"102":1,"241":1}}],["table",{"0":{"126":1},"1":{"42":1,"225":2,"238":2}}],["targeted",{"1":{"302":1,"310":1,"329":1}}],["target=ex36",{"1":{"171":1}}],["target=key",{"1":{"70":1}}],["targets",{"1":{"42":1}}],["target",{"1":{"39":3,"42":1,"252":1,"291":1,"331":3,"409":2,"410":1},"2":{"331":1}}],["two",{"0":{"321":1,"322":1,"324":1,"393":1},"1":{"9":1,"18":1,"19":1,"23":1,"26":1,"28":3,"38":1,"48":1,"58":1,"61":4,"67":7,"71":1,"76":1,"80":1,"129":1,"147":1,"152":3,"158":1,"165":1,"170":2,"177":1,"179":1,"184":2,"186":1,"197":1,"198":3,"201":1,"218":6,"219":2,"240":1,"262":1,"279":1,"289":4,"295":1,"303":2,"304":1,"310":1,"312":1,"315":2,"316":1,"320":1,"321":1,"322":2,"324":1,"326":1,"335":1,"345":2,"347":1,"350":2,"352":1,"353":1,"356":1,"371":1,"374":2,"376":1,"389":1,"393":2,"397":1,"399":1}}],["thumb",{"1":{"264":4,"265":3,"266":6}}],["thumbnails",{"1":{"73":2,"81":1}}],["thumbnail",{"1":{"73":4}}],["thus",{"1":{"32":1,"42":1,"195":1,"368":1}}],["throughout",{"1":{"120":1}}],["through",{"0":{"323":1},"1":{"39":1,"42":1,"53":1,"61":1,"102":1,"124":1,"143":1,"145":1,"147":2,"152":2,"178":1,"194":1,"276":2,"316":1,"323":1,"329":1,"334":1,"338":1,"345":3,"346":1,"415":1,"422":2}}],["three",{"0":{"326":1,"335":1},"1":{"31":2,"33":1,"48":1,"58":1,"67":11,"75":2,"94":1,"179":1,"182":1,"183":1,"188":1,"191":1,"201":2,"209":1,"214":1,"218":2,"222":1,"243":1,"289":2,"294":1,"295":1,"315":1,"326":2,"340":1,"348":1,"351":1,"370":1,"371":1,"377":1,"405":1,"410":1,"417":4}}],["threepointarc`",{"1":{"49":1,"218":1}}],["threepointarc",{"1":{"23":1,"28":3,"62":2,"163":2,"172":2,"225":1,"280":1,"420":1},"2":{"10":1,"23":1,"28":1,"49":1,"62":1,"163":1,"172":1,"218":1,"225":1,"280":1,"420":1}}],["threads",{"1":{"84":1},"2":{"84":1}}],["thread",{"1":{"84":1,"179":6,"259":1,"354":1},"3":{"10":1,"49":1,"218":1,"225":1,"259":1}}],["though",{"1":{"271":1}}],["thou",{"1":{"36":1}}],["those",{"1":{"28":1,"31":1,"81":1,"100":1,"135":1,"163":1,"344":1,"391":1,"408":1,"417":1,"421":1}}],["thank",{"1":{"54":1}}],["than",{"1":{"12":1,"19":1,"31":1,"62":2,"72":1,"108":1,"134":1,"135":1,"139":3,"172":1,"182":2,"236":1,"253":1,"268":1,"276":1,"302":1,"304":1,"307":1,"312":1,"324":1,"353":2,"417":1,"421":2}}],["that",{"1":{"2":1,"3":1,"4":1,"10":1,"13":1,"15":3,"18":1,"19":2,"22":1,"23":2,"24":2,"26":2,"28":1,"30":3,"31":3,"32":2,"33":2,"34":3,"37":3,"38":2,"39":2,"42":2,"48":2,"50":1,"51":1,"53":3,"54":1,"58":2,"59":1,"60":1,"61":7,"62":3,"75":1,"76":1,"77":2,"81":1,"84":1,"87":1,"89":1,"90":1,"91":2,"99":2,"101":1,"102":2,"104":1,"108":1,"117":1,"119":2,"123":2,"129":3,"133":1,"134":7,"135":1,"138":1,"139":2,"140":5,"141":2,"144":4,"145":1,"146":2,"152":5,"155":1,"157":2,"158":3,"160":1,"165":1,"169":3,"171":1,"172":3,"177":2,"179":1,"181":2,"182":2,"183":1,"184":1,"187":1,"188":1,"189":1,"192":2,"195":2,"196":1,"197":1,"198":3,"201":2,"204":2,"206":5,"211":1,"218":1,"221":1,"222":3,"224":1,"235":1,"238":5,"240":1,"243":1,"250":2,"252":2,"254":1,"255":1,"256":1,"257":2,"258":1,"259":1,"260":1,"261":2,"262":2,"263":1,"276":3,"290":1,"295":2,"302":1,"303":2,"304":1,"306":1,"310":3,"312":1,"334":1,"338":1,"339":2,"340":1,"342":1,"344":5,"345":4,"347":1,"350":3,"352":2,"353":3,"354":3,"356":1,"357":1,"358":1,"360":1,"361":1,"362":1,"363":2,"367":1,"368":3,"369":1,"371":3,"373":2,"374":3,"376":2,"377":2,"378":2,"379":1,"382":1,"383":2,"384":1,"387":1,"388":1,"391":2,"393":1,"394":1,"395":1,"399":1,"405":2,"406":1,"408":2,"410":2,"413":1,"414":1,"415":1,"416":1,"417":2,"420":10,"421":3}}],["third",{"1":{"304":1,"354":1}}],["thick",{"1":{"230":1}}],["thickens",{"1":{"340":1}}],["thicken`",{"1":{"238":1}}],["thickening",{"1":{"61":3},"2":{"61":1}}],["thicken",{"1":{"60":3,"61":1,"239":1},"2":{"60":1,"61":1,"238":1,"239":1}}],["thickness=2",{"1":{"356":2}}],["thickness=sheet",{"1":{"278":2}}],["thickness+fillet",{"1":{"230":4}}],["thickness",{"1":{"7":2,"32":2,"34":7,"61":6,"69":12,"71":6,"77":13,"78":14,"124":7,"142":4,"143":3,"144":6,"149":2,"151":6,"152":5,"153":4,"154":6,"156":6,"158":4,"160":4,"161":6,"162":5,"164":4,"169":4,"170":6,"172":3,"177":4,"190":1,"230":5,"256":2,"278":7,"313":1,"314":1,"336":1,"340":1,"345":4,"346":2,"350":5,"367":1,"368":5,"369":5,"373":1,"374":1,"375":3,"376":3,"377":4},"2":{"61":1,"77":2,"350":1},"3":{"34":1,"42":1,"49":1,"52":1,"61":1,"62":1,"71":1,"72":1,"76":1,"78":1,"80":1,"81":1,"124":1,"149":1,"152":1,"154":1,"158":1,"159":1,"160":1,"161":1,"163":1,"182":1,"238":1,"239":1,"241":1,"243":1,"278":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"287":1,"290":1,"310":1,"313":1,"314":1,"340":1,"341":1,"346":1,"357":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"406":1,"417":1,"419":1,"420":1}}],["thin",{"0":{"160":1},"1":{"160":1,"374":1}}],["think",{"1":{"42":1,"189":1,"233":1,"272":1}}],["things",{"1":{"25":1,"34":1,"389":1,"405":1}}],["this",{"1":{"4":1,"10":1,"11":1,"15":1,"17":1,"19":4,"20":1,"22":2,"23":3,"24":1,"25":2,"26":1,"27":1,"28":5,"31":1,"32":4,"33":1,"34":1,"36":1,"37":3,"38":1,"42":4,"53":2,"54":2,"55":1,"59":1,"60":1,"61":4,"62":1,"63":1,"64":1,"66":5,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":2,"74":1,"75":2,"76":1,"77":1,"78":2,"80":1,"81":4,"86":1,"95":1,"100":1,"108":1,"110":1,"124":1,"128":1,"129":3,"134":6,"135":2,"137":1,"139":4,"140":5,"141":2,"143":4,"144":2,"145":1,"146":1,"147":4,"152":1,"153":2,"156":1,"158":2,"160":3,"161":1,"162":2,"164":2,"167":2,"172":1,"176":1,"177":2,"178":1,"179":1,"184":1,"188":2,"189":1,"190":1,"191":1,"192":2,"194":1,"195":3,"198":1,"199":1,"200":1,"201":1,"202":2,"204":5,"206":2,"209":2,"210":1,"211":2,"221":1,"222":2,"223":4,"230":3,"234":1,"235":1,"236":1,"237":1,"240":1,"244":1,"245":1,"248":1,"250":5,"253":2,"254":1,"255":2,"256":1,"257":3,"259":1,"262":5,"263":2,"267":2,"272":3,"276":2,"278":2,"279":1,"291":1,"295":4,"299":4,"303":1,"306":2,"307":2,"310":4,"312":1,"313":1,"314":1,"319":1,"326":1,"329":1,"331":1,"332":1,"334":1,"336":1,"339":2,"340":10,"341":2,"342":1,"344":3,"345":10,"348":1,"349":1,"350":3,"353":3,"354":3,"357":1,"358":2,"360":1,"361":1,"362":1,"363":1,"365":1,"366":1,"367":2,"368":4,"369":6,"371":2,"372":1,"373":3,"374":3,"375":1,"377":2,"378":1,"379":2,"380":1,"382":2,"388":2,"391":1,"393":1,"403":1,"406":2,"407":1,"410":1,"412":1,"415":3,"417":4,"419":1,"420":4,"421":4}}],["therefore",{"1":{"19":1,"108":1,"189":1,"201":1,"202":1,"262":1,"263":1,"353":2,"370":1,"374":1,"421":1}}],["there",{"0":{"252":1},"1":{"15":1,"25":1,"26":1,"31":2,"34":1,"40":1,"48":2,"50":1,"51":1,"71":1,"78":3,"110":1,"124":1,"140":1,"167":1,"183":1,"184":1,"188":1,"190":1,"197":2,"204":1,"214":1,"256":1,"260":1,"263":1,"279":2,"295":2,"338":1,"352":1,"354":1,"363":1,"367":1,"368":1,"411":1,"422":1}}],["they",{"1":{"12":1,"13":1,"15":1,"34":2,"37":1,"102":2,"120":1,"121":2,"133":2,"135":4,"139":1,"141":5,"159":1,"178":1,"181":1,"189":1,"192":1,"198":1,"202":1,"238":1,"242":1,"254":2,"255":1,"257":2,"262":3,"268":1,"270":1,"299":1,"304":1,"310":2,"343":1,"350":1,"361":1,"395":1,"399":1,"421":1}}],["then",{"1":{"11":1,"15":2,"26":1,"34":1,"61":1,"65":1,"66":1,"74":1,"134":1,"141":1,"144":1,"151":3,"152":5,"155":1,"156":1,"162":2,"164":2,"166":1,"170":2,"185":1,"188":2,"189":2,"202":2,"230":1,"231":1,"255":2,"256":2,"259":1,"268":1,"275":1,"295":2,"299":2,"303":1,"306":1,"307":1,"310":1,"315":1,"331":1,"344":1,"369":1,"399":1,"419":1,"420":2}}],["their",{"1":{"5":2,"20":2,"21":1,"26":1,"27":1,"39":1,"48":1,"52":1,"75":1,"77":1,"81":1,"112":2,"134":1,"141":2,"177":1,"178":1,"181":1,"204":1,"206":1,"229":1,"238":1,"253":1,"254":3,"260":1,"272":1,"291":1,"344":2,"345":1,"361":1,"384":1,"392":1,"421":1}}],["themselves",{"1":{"189":1,"191":1,"211":1,"221":1,"259":1,"274":1}}],["them",{"1":{"4":1,"25":1,"26":1,"34":1,"36":1,"61":2,"77":1,"80":1,"102":1,"108":1,"120":1,"123":1,"134":1,"135":2,"141":1,"147":2,"178":3,"181":1,"184":3,"190":1,"231":1,"238":1,"245":1,"341":1,"343":1,"345":1,"367":1,"419":1,"420":2}}],["these",{"1":{"2":1,"3":1,"5":1,"17":1,"25":1,"42":1,"50":1,"55":1,"61":1,"66":1,"74":1,"75":1,"110":1,"119":1,"123":1,"144":1,"147":1,"152":2,"165":1,"167":1,"174":1,"177":1,"180":1,"182":1,"190":1,"191":2,"198":3,"206":1,"212":1,"214":1,"217":1,"222":2,"224":1,"235":1,"236":1,"242":1,"246":1,"253":2,"256":1,"258":1,"259":1,"260":1,"269":1,"274":2,"291":3,"303":1,"306":1,"310":1,"312":1,"316":1,"329":1,"330":1,"331":1,"335":1,"339":1,"340":1,"342":1,"344":4,"345":2,"346":1,"365":1,"374":3,"376":2,"394":1,"397":1,"410":2,"411":1,"415":1,"422":1}}],["the",{"0":{"14":1,"62":1,"79":1,"155":1,"163":1,"173":1,"194":1,"200":1,"208":1,"232":1,"263":1,"335":1,"351":1,"357":1,"359":1,"361":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":2,"394":1,"401":2,"404":1,"405":1,"406":1,"407":1,"409":1},"1":{"2":3,"3":2,"4":10,"5":13,"6":2,"7":6,"9":3,"10":9,"11":4,"12":2,"13":4,"14":5,"15":9,"17":7,"18":2,"19":17,"20":15,"21":2,"22":8,"23":13,"24":3,"25":13,"26":10,"27":2,"28":24,"30":19,"31":16,"32":15,"33":3,"34":21,"36":8,"37":14,"38":3,"39":17,"40":3,"42":30,"43":2,"47":2,"48":7,"50":2,"51":3,"52":4,"53":8,"54":7,"55":3,"57":3,"58":2,"59":11,"60":12,"61":61,"62":17,"63":2,"64":2,"65":6,"66":8,"67":7,"68":11,"69":10,"70":21,"71":16,"72":1,"73":5,"74":6,"75":12,"76":3,"77":15,"78":34,"80":36,"81":13,"87":1,"89":1,"90":2,"91":5,"92":1,"94":2,"95":1,"97":1,"98":3,"99":3,"100":1,"102":7,"104":1,"108":8,"109":1,"110":20,"111":4,"112":1,"113":2,"117":7,"119":11,"120":4,"121":6,"122":2,"123":9,"124":15,"128":6,"129":13,"130":1,"133":13,"134":21,"135":10,"137":2,"138":6,"139":12,"140":4,"141":13,"142":1,"143":7,"144":13,"146":1,"147":14,"148":6,"149":3,"150":3,"151":3,"152":14,"153":5,"154":5,"155":2,"156":7,"157":3,"158":3,"159":2,"160":1,"161":2,"162":3,"163":4,"164":1,"167":3,"168":4,"169":15,"171":1,"172":5,"173":3,"174":2,"176":1,"177":2,"178":5,"179":14,"180":4,"181":10,"182":29,"183":4,"184":25,"186":1,"187":1,"188":22,"189":29,"190":12,"191":7,"192":14,"193":1,"194":26,"195":6,"196":6,"197":8,"198":14,"199":6,"200":3,"201":11,"202":22,"203":1,"204":10,"206":22,"208":8,"209":15,"210":1,"211":6,"212":1,"214":2,"215":2,"216":2,"217":3,"218":1,"221":7,"222":17,"223":10,"224":3,"229":1,"230":8,"232":4,"233":5,"234":1,"235":3,"236":2,"238":9,"240":3,"241":3,"242":2,"243":21,"244":2,"245":8,"246":3,"248":1,"249":2,"250":1,"251":1,"252":4,"253":5,"254":3,"255":7,"256":4,"257":8,"258":3,"259":3,"260":2,"261":2,"262":17,"263":13,"267":6,"268":12,"269":1,"270":3,"271":2,"272":21,"273":6,"274":1,"275":7,"276":9,"277":2,"278":19,"279":14,"280":1,"289":1,"290":11,"291":6,"294":1,"295":20,"296":1,"298":2,"299":20,"303":8,"304":6,"306":11,"307":4,"308":1,"310":4,"311":3,"312":9,"313":1,"314":1,"317":1,"318":2,"319":2,"331":14,"332":3,"333":1,"334":4,"335":6,"336":4,"337":3,"338":4,"339":19,"340":33,"341":10,"342":2,"343":1,"344":26,"345":64,"346":2,"347":4,"348":1,"349":2,"350":17,"351":4,"352":12,"353":13,"354":18,"355":2,"356":3,"357":11,"358":6,"359":7,"360":4,"361":2,"362":8,"363":4,"364":5,"365":6,"367":6,"368":45,"369":35,"370":3,"371":6,"372":13,"373":21,"374":17,"375":11,"376":14,"377":16,"378":6,"379":4,"380":2,"381":2,"382":7,"383":7,"384":10,"385":3,"386":1,"387":5,"388":8,"389":8,"390":1,"391":4,"392":4,"393":4,"394":5,"395":9,"396":6,"397":2,"398":6,"399":4,"400":11,"401":2,"402":2,"403":1,"404":3,"405":5,"406":5,"407":2,"408":8,"409":9,"410":7,"411":2,"412":6,"413":7,"414":3,"415":4,"416":1,"417":11,"419":9,"420":56,"421":9,"422":2}}],["token",{"0":{"420":1},"1":{"420":16,"421":1},"2":{"420":1}}],["tot",{"1":{"286":9}}],["total",{"1":{"17":2,"189":1,"194":9,"196":1,"200":1,"345":1}}],["toby",{"0":{"291":1},"1":{"278":1,"279":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"291":2},"2":{"291":1}}],["to|",{"1":{"266":1,"271":1,"276":1}}],["to`",{"1":{"183":1,"184":2,"266":1}}],["to``",{"1":{"179":1,"180":1,"182":1,"347":1}}],["together",{"0":{"361":1},"1":{"147":1,"165":1,"182":1,"184":1,"255":1,"278":1,"286":1,"310":1,"356":1,"359":1,"361":1,"376":1,"420":3,"421":1}}],["torg",{"1":{"102":1}}],["torus`",{"1":{"49":1,"220":1,"224":1}}],["torus",{"1":{"49":1,"220":2,"227":1,"241":1},"2":{"10":1,"49":1,"220":1,"224":1,"227":1}}],["tournament",{"1":{"94":1}}],["too",{"0":{"291":1},"1":{"278":1,"279":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"291":2,"333":1,"405":2}}],["tootalltoby>`",{"1":{"291":1}}],["tootalltoby",{"1":{"94":1}}],["toolpaths",{"1":{"313":1}}],["tooling",{"1":{"99":1}}],["tool",{"1":{"90":1,"98":1,"141":1,"158":1,"311":1,"346":1,"382":1},"2":{"90":1}}],["tools",{"0":{"89":1,"103":1},"1":{"74":2,"89":1,"91":3,"98":1,"104":1,"117":1,"124":1,"133":2,"134":1,"191":1,"211":1,"233":1,"235":1,"237":1,"302":1,"310":1,"421":1}}],["todo",{"1":{"73":1,"74":1,"81":2}}],["toy",{"0":{"80":1},"1":{"73":3,"78":1,"80":4,"104":1}}],["tolist",{"1":{"75":1},"2":{"75":1}}],["tol",{"1":{"59":3}}],["tolerance=10",{"1":{"278":1}}],["tolerance=",{"1":{"72":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["tolerances",{"0":{"337":1},"1":{"61":1,"337":1}}],["tolerance",{"1":{"72":2,"278":2,"279":2,"280":2,"281":2,"282":2,"283":2,"284":2,"285":2,"286":2,"287":2,"288":2,"289":2,"290":2},"3":{"34":1,"42":1,"49":1,"52":1,"61":1,"62":1,"71":1,"72":1,"76":1,"78":1,"80":1,"81":1,"124":1,"149":1,"152":1,"154":1,"158":1,"159":1,"160":1,"161":1,"163":1,"182":1,"238":1,"239":1,"241":1,"243":1,"278":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"287":1,"290":1,"310":1,"313":1,"314":1,"337":1,"340":1,"341":1,"346":1,"357":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"406":1,"417":1,"419":1,"420":1}}],["towards",{"1":{"23":1,"32":1,"37":1,"253":1}}],["topo",{"1":{"266":1,"276":4},"2":{"266":1,"276":2}}],["topologies",{"1":{"259":1}}],["topological",{"0":{"58":1,"276":1},"1":{"58":1,"112":2,"135":2,"204":2,"206":8,"230":3,"233":2,"271":1,"276":2,"378":1}}],["topology`",{"1":{"14":1,"206":1}}],["topology",{"0":{"206":1,"277":1},"1":{"14":3,"57":1,"58":8,"87":1,"126":1,"131":1,"135":1,"188":1,"203":1,"206":4,"256":1,"264":5,"265":4,"266":7,"267":1,"268":1,"272":5,"273":2,"275":1,"276":2,"277":2,"310":1,"333":1},"2":{"14":1,"131":1,"188":1,"206":1}}],["topf",{"1":{"152":7,"160":2,"169":3,"170":2},"2":{"169":1}}],["topfirstline",{"1":{"49":1}}],["topangs",{"1":{"74":4}}],["topx",{"1":{"74":2}}],["top",{"0":{"368":1,"382":1,"384":1,"389":1,"394":1},"1":{"6":1,"17":1,"34":1,"42":2,"49":2,"53":1,"59":1,"70":2,"71":2,"72":3,"73":22,"76":1,"77":7,"78":3,"80":5,"81":4,"124":1,"144":1,"151":1,"169":5,"202":2,"221":1,"243":9,"246":1,"256":2,"262":3,"264":4,"265":3,"266":6,"276":3,"278":2,"280":1,"291":13,"335":1,"360":1,"368":10,"369":7,"382":4,"384":1,"385":1,"389":1,"393":1,"394":1,"419":1,"420":11},"2":{"53":1,"202":1}}],["topics",{"0":{"0":1}}],["to",{"0":{"25":1,"26":1,"110":1,"160":1,"208":1,"209":1,"237":1,"351":1,"360":1,"362":1,"363":1,"364":1,"365":1,"373":1,"393":1},"1":{"1":3,"2":1,"3":1,"4":1,"5":6,"6":1,"7":2,"9":1,"10":1,"11":5,"12":3,"13":3,"14":3,"15":3,"17":2,"18":1,"19":11,"20":8,"22":2,"23":2,"24":1,"25":9,"26":8,"27":3,"28":6,"30":2,"31":12,"32":1,"33":1,"34":8,"36":4,"37":1,"38":1,"39":9,"40":1,"42":13,"43":1,"48":3,"50":1,"51":2,"52":1,"53":2,"54":1,"55":1,"56":1,"57":2,"58":1,"59":3,"60":4,"61":14,"62":10,"63":1,"64":2,"65":2,"66":5,"67":2,"68":4,"69":4,"70":5,"71":2,"73":1,"74":3,"75":8,"76":3,"77":18,"78":10,"80":10,"81":3,"86":1,"89":1,"90":1,"91":2,"92":1,"95":1,"97":2,"98":5,"99":4,"102":3,"108":3,"109":4,"110":8,"111":1,"112":1,"113":1,"117":1,"118":1,"119":1,"121":3,"122":2,"123":4,"124":4,"127":2,"128":4,"129":5,"130":2,"131":1,"133":14,"134":13,"135":8,"138":5,"139":7,"140":12,"141":21,"143":5,"144":10,"146":2,"147":4,"148":3,"149":1,"151":2,"152":7,"153":2,"154":1,"155":1,"156":3,"157":4,"158":2,"160":1,"162":3,"163":1,"165":2,"166":1,"167":3,"168":2,"169":4,"170":2,"171":3,"172":6,"173":1,"174":3,"175":1,"176":2,"177":4,"178":15,"179":4,"180":5,"181":7,"182":9,"183":5,"184":19,"188":10,"189":10,"190":6,"191":5,"192":3,"193":2,"194":6,"195":4,"196":3,"197":1,"198":4,"199":3,"200":1,"201":6,"202":9,"204":3,"206":5,"209":7,"210":4,"211":3,"214":2,"217":3,"219":2,"221":1,"222":2,"223":1,"229":2,"230":2,"231":1,"232":2,"233":6,"234":3,"235":5,"236":2,"237":3,"238":9,"240":2,"241":1,"242":1,"243":14,"245":4,"246":2,"248":1,"249":1,"250":5,"251":4,"252":5,"253":5,"254":1,"255":5,"256":3,"257":7,"258":3,"260":1,"262":1,"263":5,"267":3,"268":5,"269":1,"270":3,"271":1,"272":5,"273":3,"274":1,"275":2,"276":6,"277":2,"278":2,"280":2,"286":1,"290":4,"291":7,"295":1,"296":2,"299":3,"304":3,"306":1,"307":1,"308":4,"310":3,"311":2,"312":7,"313":1,"315":1,"316":3,"317":1,"319":1,"320":1,"325":1,"326":1,"329":6,"331":4,"335":2,"336":1,"337":1,"339":5,"340":3,"341":4,"343":1,"344":9,"345":11,"346":1,"347":3,"348":1,"349":2,"350":8,"351":1,"352":4,"353":3,"354":7,"355":1,"356":2,"357":2,"358":6,"360":3,"361":1,"362":5,"363":5,"364":4,"365":3,"366":2,"367":2,"368":7,"369":11,"371":2,"372":3,"373":6,"374":3,"375":5,"376":4,"377":6,"378":5,"379":1,"380":2,"381":1,"382":2,"384":3,"387":2,"388":2,"389":4,"394":1,"395":1,"396":1,"397":1,"398":2,"399":1,"405":3,"406":4,"408":1,"409":2,"410":2,"412":1,"413":1,"415":7,"416":2,"418":2,"419":2,"420":9,"421":6,"422":1},"2":{"23":1,"39":1,"59":1,"61":1,"62":1,"67":1,"75":1,"76":1,"77":2,"80":1,"108":1,"109":1,"110":1,"179":1,"180":1,"181":1,"182":1,"183":1,"184":3,"189":1,"243":2,"266":1,"268":1,"276":1,"347":1,"352":1,"354":1,"362":1,"363":1,"364":1,"365":1}}],["toctree",{"1":{"0":1,"47":1,"126":1,"264":1,"265":1,"266":1,"421":1,"422":1}}],["s6b",{"1":{"284":1}}],["s6",{"1":{"284":1,"287":1}}],["s5",{"1":{"284":1,"287":1}}],["s4",{"1":{"281":2,"284":1,"285":1,"287":1}}],["s3a",{"1":{"284":1}}],["s3",{"1":{"281":1,"284":1,"285":1,"287":1,"288":1}}],["s19",{"1":{"417":1}}],["s18",{"1":{"417":1}}],["s1",{"1":{"182":1,"288":1}}],["s25",{"1":{"417":1}}],["s24",{"1":{"417":1}}],["s23",{"1":{"417":1}}],["s22",{"1":{"417":1}}],["s21",{"1":{"417":1}}],["s20",{"1":{"417":1}}],["s2",{"1":{"179":3,"182":2,"284":1,"285":1,"287":1,"288":1}}],["src=",{"1":{"124":2,"396":2,"420":2}}],["squircle",{"1":{"102":1}}],["squares",{"1":{"166":1}}],["square",{"1":{"18":1,"75":1,"102":1,"168":5,"373":1},"2":{"18":1,"168":1}}],["sqrt",{"1":{"75":2,"289":2,"290":1},"2":{"75":1,"289":1,"290":1}}],["swing",{"1":{"238":1}}],["switches",{"1":{"262":1}}],["switching",{"1":{"196":1}}],["switch",{"1":{"70":4,"410":1}}],["swept",{"1":{"61":2}}],["sweeps",{"1":{"147":2}}],["sweeping",{"1":{"68":2,"74":1,"78":1,"229":1,"235":1,"236":1}}],["sweep",{"0":{"147":1},"1":{"25":3,"34":2,"61":5,"68":5,"74":4,"78":6,"124":2,"147":2,"184":1,"239":1,"282":1},"2":{"25":2,"31":1,"34":1,"49":1,"61":1,"68":1,"74":1,"78":1,"124":1,"147":1,"184":1,"238":1,"239":1,"252":1,"282":1}}],["sweep`",{"1":{"25":1,"34":2,"49":2,"147":2,"238":1,"252":1}}],["sm",{"0":{"278":1},"1":{"278":6,"290":1,"291":3}}],["smallest",{"1":{"268":2,"409":1,"413":1}}],["smaller",{"1":{"138":2,"182":1,"200":1,"290":1}}],["small",{"1":{"61":2,"230":1,"318":1,"374":1,"404":1,"420":1}}],["smoke",{"1":{"59":17}}],["smooths",{"1":{"344":1}}],["smoother",{"1":{"236":1,"303":1,"304":1}}],["smoothly",{"1":{"102":1,"303":1}}],["smoothness",{"1":{"61":1}}],["smooth",{"1":{"34":1,"71":1,"78":2,"123":1,"124":1,"230":1,"232":1,"235":1,"303":2,"403":1},"3":{"5":1,"10":1,"25":1,"34":1,"49":1,"61":1,"62":1,"68":1,"78":1,"81":1,"124":1,"145":1,"218":1,"225":1,"241":1,"304":1,"310":1}}],["skillfully",{"1":{"291":1}}],["skin",{"1":{"61":1,"421":1}}],["skins",{"1":{"61":1}}],["sk8",{"1":{"176":2}}],["sk7",{"1":{"175":2}}],["sk6",{"1":{"174":2}}],["sk5",{"1":{"173":2}}],["sk4",{"1":{"172":2}}],["sk3",{"1":{"159":1,"164":2}}],["sk29",{"1":{"163":2}}],["sk28",{"1":{"162":2}}],["sk27",{"1":{"161":2}}],["sk25",{"1":{"159":12}}],["sk23",{"1":{"157":5}}],["sk20",{"1":{"154":2}}],["sk2",{"1":{"152":6,"158":1,"159":1,"169":3,"171":3,"282":2}}],["sk1",{"1":{"159":1,"169":1,"282":1,"283":1},"2":{"169":1}}],["sk18",{"1":{"151":2}}],["sk17",{"1":{"150":2}}],["sk16",{"1":{"149":6}}],["sk15",{"1":{"148":2}}],["sk14",{"1":{"147":2}}],["sk12",{"1":{"145":2}}],["sk",{"1":{"144":1,"145":1,"147":1,"148":1,"149":2,"150":1,"152":3,"155":1,"156":1,"157":1,"158":2,"161":1,"162":1,"163":1,"164":1,"165":3,"166":1,"167":5,"168":4,"169":3,"170":5,"171":3,"172":1,"173":1,"174":1,"175":1,"176":1,"286":3,"290":5}}],["skeletal",{"1":{"117":1}}],["sketching",{"0":{"42":1},"1":{"37":1,"81":1,"230":1,"262":1,"263":2,"310":1,"318":1,"345":3}}],["sketch``",{"1":{"37":1,"194":2}}],["sketches",{"0":{"39":1,"414":1},"1":{"34":1,"39":1,"42":1,"72":1,"178":2,"223":1,"233":1,"235":1,"250":1,"262":1,"307":1,"310":1,"311":1,"334":1,"343":1,"414":1,"417":1}}],["sketch",{"0":{"72":1,"154":1,"159":1,"371":1,"377":1,"382":1},"1":{"10":1,"11":2,"24":1,"26":2,"37":1,"39":10,"40":2,"41":1,"42":7,"47":1,"49":18,"58":1,"62":3,"65":2,"67":6,"68":1,"69":1,"71":1,"72":1,"73":2,"76":17,"80":8,"81":2,"144":3,"156":1,"157":5,"158":1,"159":2,"164":5,"167":4,"168":4,"169":1,"170":4,"172":3,"175":2,"178":1,"182":1,"190":1,"191":3,"193":2,"195":1,"201":1,"202":3,"219":13,"221":1,"222":8,"224":2,"226":1,"230":2,"235":1,"238":7,"239":4,"262":7,"263":2,"270":3,"286":1,"290":1,"294":1,"295":1,"299":5,"302":1,"310":5,"329":1,"340":9,"341":4,"345":3,"346":1,"368":2,"369":2,"371":5,"372":2,"373":3,"375":1,"376":1,"377":3,"382":4,"385":1,"386":1,"387":3,"388":2,"406":2,"408":1,"414":2,"420":1},"2":{"10":1,"11":1,"37":1,"39":2,"58":1,"68":1,"69":1,"72":1,"144":1,"156":1,"158":1,"159":1,"168":1,"186":1,"188":1,"195":1,"235":1,"262":2,"345":1,"382":1}}],["skt",{"1":{"80":3}}],["syntax",{"1":{"140":1,"393":1}}],["sympy",{"1":{"279":4,"295":4},"2":{"295":1}}],["symbols",{"1":{"279":2,"295":2,"347":1},"2":{"279":1,"295":1}}],["symbolic",{"1":{"279":1,"295":2}}],["symbol",{"1":{"48":1,"208":4,"209":7,"347":3},"2":{"181":1,"208":2,"209":1}}],["symmetries",{"0":{"338":1},"1":{"335":2}}],["symmetrically",{"1":{"80":1}}],["symmetrical",{"1":{"75":1,"78":1,"235":1,"340":1,"341":1}}],["symmetric",{"0":{"148":1},"1":{"42":1,"80":2,"148":1,"182":1,"307":1,"409":1,"420":1}}],["symmetry",{"1":{"61":1,"75":1,"80":2,"290":1,"308":1,"335":2,"339":2,"340":1,"341":1,"405":1,"408":1,"409":1,"411":1,"412":1,"413":1,"415":1},"3":{"26":1,"49":1,"60":1,"61":1,"62":1,"67":1,"69":1,"76":1,"80":1,"148":1,"149":1,"150":1,"163":1,"176":1,"222":1,"238":1,"239":1,"278":1,"280":1,"281":1,"286":1,"288":1,"289":1,"290":1,"308":1,"310":1,"340":1,"341":1,"346":1,"420":1}}],["systematic",{"1":{"334":1}}],["systems",{"0":{"141":1,"254":1},"1":{"53":1,"112":1,"119":1,"120":1,"133":6,"134":1,"135":14,"137":1,"138":2,"139":9,"140":1,"141":5,"254":2,"310":1,"311":1,"339":1},"2":{"135":1}}],["system",{"1":{"42":1,"51":1,"53":1,"99":1,"133":1,"137":1,"141":4,"179":1,"188":1,"204":1,"208":1,"233":1,"241":1,"254":1,"262":1,"339":2,"340":1,"345":2},"2":{"179":1,"208":1}}],["sleeve",{"0":{"285":1},"1":{"285":1,"291":1}}],["slight",{"1":{"420":1}}],["slightly",{"1":{"80":1,"108":1}}],["slide",{"1":{"182":18}}],["slider",{"1":{"181":1,"182":2}}],["sliding",{"1":{"182":1}}],["slicer",{"1":{"257":1}}],["slices",{"1":{"238":1}}],["slice",{"0":{"393":1},"1":{"72":7,"275":2},"3":{"49":1,"59":1,"61":1,"74":1,"80":1,"157":1,"161":1,"179":1,"182":1,"238":1,"239":1,"259":1,"281":1,"282":1,"287":1,"289":1,"408":1,"409":1,"413":1}}],["slicing",{"1":{"22":1,"49":1,"241":1,"393":2}}],["slope",{"1":{"279":3,"289":1,"295":3},"2":{"279":1,"295":1}}],["slow",{"1":{"217":1,"415":1,"416":1}}],["slower",{"1":{"11":2,"250":1}}],["slotw2",{"1":{"284":2}}],["slotw1",{"1":{"284":2}}],["sloth2",{"1":{"284":2}}],["sloth1",{"1":{"284":2}}],["slot",{"1":{"83":2,"181":1,"182":1,"219":4,"286":1,"345":8},"2":{"345":1}}],["slots",{"0":{"170":1},"1":{"65":1,"80":1}}],["slotoverall`",{"1":{"49":1,"219":1}}],["slotoverall",{"1":{"65":2,"80":1,"182":3,"219":1,"226":1,"281":2,"284":2,"285":4,"288":1,"345":2,"346":1},"2":{"10":1,"49":1,"65":1,"80":1,"182":1,"219":1,"226":1,"281":1,"284":1,"285":1,"288":1,"345":1,"346":1}}],["slotcentertocenter`",{"1":{"49":1,"170":2,"219":1}}],["slotcentertocenter",{"1":{"170":2,"219":1,"226":1},"2":{"10":1,"49":1,"170":1,"219":1,"226":1}}],["slotcenterpoint`",{"1":{"49":1,"219":1}}],["slotcenterpoint",{"1":{"219":1,"226":1,"278":2},"2":{"10":1,"49":1,"219":1,"226":1,"278":1}}],["slotarc`",{"1":{"49":1,"170":2,"219":1}}],["slotarc",{"1":{"170":4,"219":1,"226":1},"2":{"10":1,"49":1,"170":1,"219":1,"226":1}}],["satisfy",{"1":{"322":1,"331":1}}],["satisfies",{"1":{"303":1,"304":1}}],["sample",{"1":{"396":1}}],["sampled",{"1":{"303":1,"308":1}}],["same`",{"1":{"49":1}}],["same",{"1":{"20":1,"22":1,"28":2,"31":1,"50":1,"61":1,"75":2,"108":1,"141":2,"143":1,"169":2,"181":1,"188":1,"197":1,"202":1,"209":1,"221":1,"272":1,"276":1,"307":3,"374":1,"378":1,"402":1,"406":2,"410":1,"414":1,"415":1,"417":1,"420":1,"421":1},"2":{"49":1}}],["sagitta=sagitta",{"1":{"292":1,"296":1,"319":1,"322":1,"324":1,"326":1}}],["sagitta",{"1":{"218":2},"2":{"315":1}}],["sagittaarc`",{"1":{"49":1,"218":1}}],["sagittaarc",{"1":{"62":2,"225":1},"2":{"10":1,"49":1,"62":1,"218":1,"225":1}}],["saving",{"1":{"134":1}}],["saved",{"1":{"182":1}}],["saves",{"1":{"133":1}}],["save",{"1":{"34":1,"133":1,"134":1,"139":2,"140":1,"178":3,"182":1,"408":1,"416":1}}],["safer",{"1":{"255":1,"281":1}}],["safety",{"1":{"134":1}}],["safe",{"1":{"129":1}}],["say",{"1":{"42":1,"259":1,"267":1,"295":1}}],["svg`",{"1":{"67":1}}],["svg",{"0":{"123":1},"1":{"16":3,"19":1,"23":1,"25":1,"26":8,"30":1,"31":1,"32":1,"37":1,"42":1,"48":2,"56":2,"67":17,"76":2,"105":2,"110":2,"119":2,"123":6,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"202":1,"218":28,"219":18,"220":10,"221":1,"222":2,"243":2,"247":1,"248":1,"256":2,"257":2,"298":1,"299":1,"304":1,"307":1,"312":1,"314":1,"317":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"331":1,"332":1,"348":1,"350":2,"357":1,"359":1,"360":1,"362":1,"363":1,"364":1,"365":1,"366":1,"368":1,"369":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"379":1,"388":1,"400":1},"2":{"26":1,"56":2,"67":1,"105":2,"123":1}}],["scikit",{"1":{"140":1}}],["science",{"1":{"140":2}}],["scientific",{"1":{"140":1}}],["scipy",{"1":{"75":1}}],["scenes",{"1":{"117":1}}],["scene",{"1":{"110":1,"204":1}}],["scenarios",{"1":{"15":1}}],["scans",{"1":{"90":1}}],["scalability",{"1":{"123":1}}],["scalable",{"1":{"123":2}}],["scalars",{"2":{"304":1}}],["scalars``",{"1":{"304":1}}],["scalars=",{"1":{"34":1,"62":2,"68":2,"78":2,"124":1,"304":1}}],["scalar",{"1":{"49":2,"243":1}}],["scales",{"1":{"398":1}}],["scale=29",{"1":{"299":1}}],["scale=20",{"1":{"67":1}}],["scale=1",{"1":{"243":1}}],["scale=100",{"1":{"76":1,"110":1}}],["scale=scale",{"1":{"208":2}}],["scaled",{"1":{"70":2,"243":2,"246":1}}],["scale",{"1":{"62":5,"70":2,"75":2,"76":4,"208":3,"222":1,"239":1,"243":5,"249":1,"256":1,"280":1,"395":2,"399":3},"2":{"49":1,"62":2,"70":1,"75":1,"76":1,"222":1,"238":1,"239":1,"243":2,"280":1,"395":1,"399":1}}],["scale`",{"1":{"49":3,"238":1}}],["scaling",{"1":{"36":1,"303":1}}],["scratch",{"1":{"139":1}}],["script>",{"1":{"124":1,"396":1,"420":1}}],["scripts",{"1":{"98":2,"255":1}}],["script",{"0":{"410":1},"1":{"66":1,"74":1,"245":1,"249":1,"349":1,"366":1,"367":1,"380":1,"395":1,"410":2,"416":1}}],["screen",{"1":{"255":1}}],["screenshot",{"1":{"53":1}}],["screws",{"1":{"19":1,"84":1,"350":1,"351":1,"354":1}}],["screw",{"0":{"360":1,"365":1},"1":{"13":2,"14":3,"19":9,"179":1,"180":1,"181":1,"182":1,"259":1,"347":1,"354":5,"360":9,"365":3},"2":{"259":1,"354":1}}],["scopes",{"1":{"310":1}}],["scope",{"0":{"263":1},"1":{"23":1,"26":1,"32":1,"37":1,"51":1,"181":2,"195":3,"198":5,"202":1,"238":2,"254":1,"263":2,"345":1,"368":1,"374":1,"376":1,"377":2},"2":{"23":1,"32":1,"37":1}}],["spitfire",{"0":{"403":1},"1":{"396":2,"400":1,"401":1,"403":1,"418":2,"421":1}}],["spikes",{"1":{"304":1}}],["spiritual",{"1":{"93":1}}],["spiral",{"3":{"10":1,"49":1,"218":1,"225":1,"259":1}}],["speedmodeling",{"1":{"291":1}}],["speaking",{"1":{"271":1}}],["specialized",{"1":{"310":1}}],["specially",{"1":{"222":2}}],["special",{"1":{"55":6,"58":6}}],["specify",{"1":{"40":1,"129":1,"201":1,"211":1,"243":1,"269":1,"272":2,"277":1,"295":1}}],["specifying",{"1":{"28":1,"31":1,"272":1}}],["specifies",{"1":{"182":1,"345":1}}],["specified",{"1":{"15":1,"65":1,"129":1,"181":1,"189":1,"192":1,"217":1,"263":1,"291":1,"329":3,"344":1,"345":1,"352":1}}],["specification",{"1":{"117":1}}],["specifically",{"1":{"26":1,"81":1}}],["specific",{"1":{"50":1,"56":1,"58":1,"81":1,"118":1,"123":1,"201":1,"211":1,"255":2,"268":1,"278":1,"302":1,"310":1,"324":1,"344":2,"345":1}}],["spot",{"1":{"406":1}}],["spo",{"0":{"280":1},"1":{"238":1,"279":1,"280":1,"291":3}}],["spherical",{"1":{"338":1,"342":1,"406":1,"411":1}}],["spheres",{"1":{"61":1,"122":1,"234":1,"404":1,"405":1,"410":1,"413":1,"415":1,"417":1}}],["sphere`",{"1":{"49":1,"220":1}}],["sphere",{"1":{"49":1,"70":2,"162":4,"179":2,"198":1,"220":2,"227":1,"241":1,"276":12,"417":16},"2":{"10":1,"49":1,"70":1,"162":1,"179":1,"198":1,"220":1,"227":1,"276":1,"417":1}}],["sphinx",{"1":{"133":11}}],["spring",{"1":{"94":1}}],["sprof",{"1":{"74":4}}],["splits",{"1":{"74":2}}],["splitz",{"1":{"74":6}}],["splitting",{"0":{"161":1},"1":{"61":1,"413":1}}],["split",{"1":{"59":1,"74":4,"80":2,"157":2,"161":3,"179":1,"182":1,"239":1,"259":1,"281":1,"282":1,"287":2,"289":1,"408":1,"409":2},"2":{"49":1,"59":1,"74":1,"80":1,"157":1,"161":1,"179":1,"182":1,"238":1,"239":1,"281":1,"282":1,"287":1,"289":1,"409":1}}],["split`",{"1":{"49":3,"238":1}}],["splines",{"1":{"310":1}}],["spline`",{"1":{"49":1,"218":1}}],["spline",{"0":{"145":1},"1":{"5":2,"25":1,"34":2,"49":1,"61":2,"62":2,"68":2,"78":7,"81":4,"124":2,"145":3,"218":2,"225":1,"304":2},"2":{"5":1,"10":1,"25":1,"34":1,"49":1,"61":1,"62":1,"68":1,"78":1,"81":1,"124":1,"145":1,"218":1,"225":1,"304":2}}],["span",{"1":{"395":5,"397":6,"398":1}}],["spades",{"1":{"76":11}}],["spade",{"1":{"76":6},"2":{"76":1}}],["spacing=lego",{"1":{"368":2,"369":2,"374":1,"375":1,"376":2,"377":2}}],["spacing=length",{"1":{"149":1}}],["spacing=5",{"1":{"198":2}}],["spacing=0",{"1":{"149":1,"368":2,"369":2,"374":1,"375":1,"376":2,"377":2}}],["spacing",{"1":{"69":6,"77":4,"257":1},"2":{"77":1}}],["space=",{"1":{"108":1}}],["spaced",{"1":{"61":1}}],["spaces",{"1":{"15":1,"73":1,"74":1,"81":1}}],["space",{"1":{"15":1,"16":1,"18":1,"81":1,"178":1,"188":1,"202":1,"206":2,"255":2,"276":1,"345":1,"421":1}}],["spatial",{"1":{"15":1,"75":1,"204":2}}],["s0",{"2":{"10":1}}],["s",{"0":{"190":1},"1":{"12":1,"19":3,"20":1,"23":1,"26":2,"28":1,"30":1,"31":3,"32":1,"34":7,"37":1,"39":2,"40":1,"42":2,"48":1,"51":10,"60":1,"61":1,"62":2,"66":1,"71":1,"78":16,"86":1,"98":1,"113":1,"117":1,"121":1,"124":7,"133":2,"164":1,"181":2,"184":1,"186":1,"189":1,"191":1,"192":3,"194":1,"195":1,"198":2,"201":1,"202":2,"204":1,"211":1,"212":1,"217":1,"218":2,"221":1,"222":3,"229":1,"230":4,"231":1,"232":1,"233":4,"236":1,"238":3,"251":1,"252":2,"253":2,"255":2,"256":2,"257":3,"258":1,"263":1,"269":1,"278":1,"281":1,"284":1,"285":1,"287":1,"290":4,"291":2,"339":2,"340":3,"344":1,"345":2,"348":1,"351":1,"354":1,"357":1,"358":2,"360":2,"369":2,"370":1,"382":2,"384":1,"389":1,"390":1,"410":1,"420":1},"2":{"10":1}}],["sizing",{"0":{"398":1}}],["sized",{"1":{"410":1}}],["sizes",{"1":{"188":1,"395":5,"398":3,"399":2,"414":1}}],["size=70",{"1":{"332":1}}],["size=axis",{"1":{"307":1}}],["size=line",{"1":{"307":1}}],["size=pagesize",{"1":{"243":1}}],["size=playingcard",{"1":{"76":2}}],["size=fontsz",{"1":{"169":4}}],["size=60",{"1":{"80":1}}],["size=",{"1":{"74":2,"147":2}}],["size=topangs",{"1":{"74":2}}],["size=3",{"1":{"243":1}}],["size=300",{"1":{"71":1}}],["size=360",{"1":{"61":1}}],["size=5",{"1":{"67":2}}],["size=120",{"1":{"307":1}}],["size=170",{"1":{"74":2}}],["size=15",{"1":{"71":1}}],["size=10",{"1":{"67":6}}],["size=180",{"1":{"61":1,"147":2}}],["size=clock",{"1":{"65":2}}],["size=width",{"1":{"61":1}}],["size=90``",{"1":{"30":1}}],["size=90",{"1":{"30":1,"31":1}}],["size",{"1":{"19":3,"30":1,"59":1,"61":1,"75":1,"76":5,"77":3,"110":1,"121":1,"168":1,"222":1,"238":1,"243":10,"245":1,"306":1,"350":1,"367":2,"368":4,"369":6,"372":1,"373":1,"374":3,"375":3,"376":4,"377":4,"396":1,"398":1},"2":{"30":1}}],["six",{"1":{"202":1,"386":1,"417":1}}],["signs",{"0":{"411":1,"412":1}}],["signatures",{"1":{"325":1}}],["signature",{"0":{"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1},"1":{"315":1,"316":1}}],["sign",{"1":{"189":1,"194":1}}],["significantly",{"1":{"66":1,"229":1,"253":1}}],["significant",{"1":{"48":1,"179":1}}],["situations",{"1":{"252":1}}],["situation",{"1":{"189":1,"354":1}}],["site",{"1":{"104":1}}],["sits",{"1":{"61":1}}],["simultaneously",{"1":{"139":1,"141":1,"144":1}}],["simulated",{"1":{"262":1}}],["simulate",{"1":{"69":2}}],["similarly",{"1":{"147":1,"189":1}}],["similar",{"1":{"110":1,"131":1,"188":1,"189":1,"198":1,"231":1,"290":1,"404":1}}],["simplified",{"1":{"236":1}}],["simplifies",{"1":{"196":1,"200":1,"236":1}}],["simplify",{"1":{"148":1,"335":1}}],["simplicity",{"1":{"113":1,"135":1}}],["simplices",{"1":{"75":1}}],["simply",{"1":{"12":1,"14":1,"129":1,"169":1,"177":1,"178":1,"420":1}}],["simpler",{"1":{"417":1}}],["simplest",{"1":{"142":1}}],["simple",{"0":{"142":1},"1":{"2":1,"7":1,"23":1,"32":1,"37":1,"42":1,"48":1,"71":1,"77":1,"108":1,"121":1,"178":1,"193":1,"198":1,"201":1,"230":2,"253":1,"254":1,"258":1,"272":1,"350":1,"353":1,"357":1,"360":2,"404":1,"420":1,"421":1}}],["siblings",{"2":{"20":1}}],["sink",{"1":{"146":3,"220":2}}],["sin",{"1":{"62":2,"72":4,"279":2,"295":2},"2":{"62":1,"72":1,"279":1,"295":1}}],["single",{"1":{"11":1,"31":1,"66":1,"77":1,"147":1,"149":9,"180":1,"182":2,"183":1,"190":1,"192":1,"201":3,"202":1,"206":3,"221":1,"258":1,"259":1,"276":1,"299":1,"302":1,"312":1,"397":1}}],["since",{"1":{"10":1,"75":1,"198":1,"357":1,"368":1,"376":1,"391":1,"420":1}}],["side=side",{"1":{"278":2,"290":1,"314":1,"340":2,"341":1,"346":1}}],["sides",{"1":{"74":1,"80":1,"219":2,"276":1,"386":1,"419":1,"420":5}}],["side`",{"1":{"49":1}}],["side",{"1":{"11":1,"42":2,"61":4,"80":3,"81":1,"108":2,"144":2,"145":1,"150":2,"152":2,"157":2,"159":6,"162":2,"175":2,"219":1,"243":7,"246":2,"278":7,"290":1,"294":4,"295":2,"312":1,"325":1,"331":6,"335":1,"340":1,"345":2,"385":1,"388":1,"389":1,"420":7},"2":{"49":1}}],["shrinkage",{"1":{"337":1}}],["shifting",{"1":{"233":1}}],["shifts",{"1":{"149":1}}],["shift",{"1":{"80":3},"2":{"80":1}}],["shifted",{"1":{"80":1,"399":1}}],["sheet",{"0":{"49":1},"1":{"61":1,"126":1,"238":1,"243":1,"245":1,"278":8},"2":{"61":1}}],["shells",{"1":{"206":2,"314":1}}],["shell`",{"1":{"206":1,"419":1,"420":1,"421":2}}],["shelling",{"1":{"72":1,"81":2},"2":{"81":1}}],["shell",{"1":{"58":1,"61":2,"75":1,"78":1,"124":1,"131":1,"160":1,"206":3,"395":1,"401":2,"420":6,"421":1},"2":{"58":1,"61":1,"75":1,"206":1,"395":1,"401":1,"419":1,"420":1,"421":1},"3":{"34":1,"42":1,"49":1,"52":1,"61":1,"62":1,"71":1,"72":1,"76":1,"78":1,"80":1,"81":1,"124":1,"149":1,"152":1,"154":1,"158":1,"159":1,"160":1,"161":1,"163":1,"182":1,"238":1,"239":1,"241":1,"243":1,"278":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"287":1,"290":1,"310":1,"313":1,"314":1,"340":1,"341":1,"346":1,"357":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"406":1,"417":1,"419":1,"420":1}}],["short``",{"1":{"315":1}}],["shortest",{"1":{"306":1,"311":1}}],["shortcuts",{"1":{"197":1}}],["short",{"1":{"174":1,"210":1,"315":1,"322":1,"324":1},"2":{"315":1}}],["should",{"1":{"42":1,"131":1,"192":1,"222":1,"263":2,"325":1,"339":1,"346":1,"373":1,"417":1,"420":1}}],["showing",{"1":{"243":1}}],["showcases",{"1":{"81":1}}],["showcased",{"1":{"60":1}}],["showcasing",{"1":{"80":1}}],["shows",{"1":{"42":1,"51":1,"52":1,"53":1,"59":1,"221":1,"408":2}}],["show",{"1":{"14":3,"30":1,"34":2,"39":2,"59":1,"60":2,"61":2,"62":2,"63":2,"64":2,"65":4,"66":2,"67":6,"68":8,"69":4,"70":2,"71":1,"72":4,"73":1,"74":4,"75":2,"76":4,"77":1,"78":4,"80":3,"81":8,"124":2,"131":1,"178":1,"179":1,"182":4,"184":1,"187":1,"191":3,"206":1,"208":4,"209":17,"243":2,"256":2,"276":2,"278":1,"279":1,"280":2,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"318":1,"346":2,"347":3,"358":1,"367":1,"389":1,"395":2,"397":1,"401":1,"405":1,"413":1,"420":2},"2":{"14":1,"34":1,"39":1,"59":1,"60":1,"61":1,"62":1,"63":1,"64":2,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"74":1,"75":1,"76":1,"77":1,"78":1,"80":1,"81":1,"124":1,"131":1,"178":3,"179":1,"182":1,"184":1,"191":1,"206":1,"208":1,"209":1,"243":1,"276":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"346":1,"347":2,"369":2,"379":2,"389":1,"395":1,"401":1,"420":1}}],["shown",{"1":{"4":1,"6":1,"14":1,"26":1,"30":2,"36":1,"48":1,"110":1,"119":1,"179":1,"180":1,"182":1,"184":1,"202":1,"204":1,"206":1,"221":1,"224":1,"240":1,"250":1,"256":1,"304":1,"312":1,"341":1,"346":1,"357":1,"365":1,"366":1,"368":1,"369":1,"373":1,"382":1}}],["shaping",{"1":{"206":1}}],["shaped",{"1":{"74":1,"419":1,"420":1}}],["shapelist`",{"1":{"242":1,"266":1,"383":1,"410":1}}],["shapelist",{"0":{"242":1},"1":{"49":6,"54":1,"58":1,"152":2,"177":1,"199":2,"240":1,"241":6,"243":6,"266":5,"268":1,"384":1},"2":{"58":1,"242":1,"243":1,"266":1,"267":1,"268":1,"269":1,"271":1,"272":1,"275":1,"383":1,"410":1}}],["shape``",{"1":{"210":2}}],["shape`",{"1":{"13":1,"19":2,"20":2,"49":2,"204":1,"206":1,"257":1,"306":1}}],["shape",{"0":{"155":1,"208":1,"385":1},"1":{"12":1,"14":1,"28":1,"34":2,"37":2,"42":1,"48":1,"49":9,"54":1,"58":2,"61":3,"62":5,"67":9,"71":1,"76":2,"77":1,"78":4,"80":1,"81":1,"102":1,"108":11,"110":4,"122":1,"124":2,"135":1,"148":1,"158":1,"172":1,"176":2,"179":2,"182":1,"188":1,"204":5,"206":6,"210":2,"212":1,"213":6,"215":3,"216":3,"217":6,"230":2,"232":1,"235":1,"238":7,"243":5,"250":1,"259":2,"266":8,"270":1,"273":3,"274":1,"276":3,"286":1,"303":1,"310":1,"314":1,"338":1,"340":1,"344":1,"373":1,"388":1,"394":1,"420":1,"421":1},"2":{"13":1,"19":1,"20":1,"49":1,"58":1,"61":2,"62":1,"67":2,"76":1,"108":1,"110":1,"186":1,"204":1,"206":1,"243":1,"257":1,"271":1,"276":1,"306":1}}],["shapes",{"0":{"19":1,"20":1},"1":{"10":1,"11":1,"17":1,"22":1,"28":1,"37":2,"75":1,"78":1,"102":1,"108":2,"110":2,"112":1,"123":3,"135":2,"158":1,"166":1,"204":2,"206":6,"224":1,"230":1,"232":1,"233":1,"234":1,"235":1,"253":1,"257":2,"276":3,"341":2,"421":1}}],["shaft",{"1":{"179":1,"219":1,"243":3}}],["sharp",{"1":{"344":1}}],["sharing",{"1":{"104":1,"112":1,"113":1,"117":1}}],["shared",{"1":{"113":1,"124":1,"276":1}}],["share",{"1":{"99":1,"141":2,"229":1,"421":1}}],["shallow",{"0":{"19":1,"261":1},"1":{"14":1,"19":2,"261":1}}],["sophisticated",{"1":{"102":1}}],["soon",{"1":{"98":1}}],["solved",{"1":{"295":1}}],["solves",{"1":{"294":1}}],["solve",{"1":{"279":1,"295":3,"310":1,"329":1,"330":1},"2":{"279":1,"295":1}}],["solvers",{"1":{"295":1,"310":1}}],["solver",{"1":{"279":1,"295":3,"302":1,"310":3}}],["solving",{"1":{"140":1,"329":2}}],["solutions",{"0":{"311":1,"312":1},"1":{"279":1,"295":1,"311":2,"312":1}}],["solution",{"1":{"111":1,"279":5,"295":5,"312":6,"331":2}}],["solely",{"1":{"238":1}}],["sole",{"1":{"77":4}}],["solidworks",{"1":{"124":1,"135":1,"137":1,"250":1}}],["solid`",{"1":{"58":1,"206":1,"238":1,"396":1,"419":1,"420":1}}],["solid",{"0":{"164":1,"231":1,"401":1},"1":{"17":1,"57":1,"58":1,"59":1,"60":2,"61":9,"75":9,"81":1,"108":2,"131":1,"164":1,"172":1,"181":1,"194":1,"206":2,"230":1,"231":1,"233":1,"234":1,"236":1,"238":1,"239":1,"241":1,"250":1,"251":8,"340":1,"341":2,"395":3,"401":4,"420":6,"421":2},"2":{"19":1,"58":1,"61":2,"75":1,"124":1,"190":1,"206":1,"238":1,"239":1,"251":1,"270":1,"395":1,"396":1,"401":1,"419":1,"420":1}}],["solidsupport",{"1":{"49":1}}],["solids`",{"1":{"49":1,"238":1,"266":1}}],["solids",{"0":{"75":1},"1":{"17":1,"46":1,"61":1,"66":1,"73":3,"74":1,"75":7,"163":1,"206":4,"231":2,"236":3,"238":1,"239":1,"241":3,"242":1,"274":1,"394":1,"421":2},"2":{"4":1,"17":1,"49":1,"163":1,"238":1,"239":1,"241":1,"266":1}}],["socket",{"1":{"70":6,"179":3}}],["sorted",{"1":{"268":2,"274":1,"275":2,"345":2,"369":1,"393":1}}],["sorts",{"1":{"240":1,"345":2}}],["sort",{"0":{"275":1,"392":1},"1":{"49":2,"59":3,"60":1,"63":1,"67":5,"69":2,"76":4,"80":3,"81":3,"144":4,"146":2,"150":1,"151":2,"152":5,"154":1,"158":1,"160":2,"161":4,"163":4,"169":3,"170":2,"182":5,"193":1,"202":4,"241":5,"243":8,"256":1,"262":2,"264":9,"266":2,"269":1,"271":2,"275":3,"276":1,"278":3,"280":4,"281":1,"284":2,"285":1,"287":3,"289":2,"292":1,"296":1,"299":1,"311":1,"319":2,"320":3,"331":1,"345":6,"346":2,"350":1,"357":1,"368":2,"369":2,"382":2,"384":2,"385":1,"388":1,"389":3,"392":2,"393":1,"394":2},"2":{"49":1,"59":1,"60":1,"63":1,"67":1,"69":1,"76":1,"80":1,"81":1,"144":1,"146":1,"150":1,"151":1,"152":1,"154":1,"158":1,"160":1,"161":1,"163":1,"169":1,"170":1,"182":1,"193":1,"202":1,"243":1,"256":1,"262":1,"266":2,"275":1,"276":1,"278":1,"280":1,"281":1,"284":1,"285":1,"287":1,"289":1,"292":1,"296":1,"299":1,"311":1,"319":2,"320":2,"331":1,"345":1,"346":1,"350":1,"357":1,"368":1,"369":1,"382":1,"384":1,"385":1,"388":1,"389":1,"392":1,"393":1,"394":1}}],["sortby`",{"1":{"49":5,"241":1,"271":1}}],["sortby",{"1":{"44":1,"69":2,"241":6,"264":3,"268":1,"280":2,"287":1,"389":1,"392":1,"393":1,"394":1},"2":{"44":1,"49":1,"241":1,"271":1}}],["sorting",{"0":{"240":1},"1":{"6":1,"54":1,"242":1,"262":1,"275":2,"333":1}}],["sources",{"1":{"263":1}}],["source",{"0":{"138":1,"141":1},"1":{"26":1,"50":1,"90":1,"91":1,"133":2,"134":2,"137":2,"138":16,"140":2,"141":5,"303":2,"304":1,"308":1,"313":1,"314":1}}],["software",{"0":{"138":1},"1":{"22":1,"111":1,"112":1,"113":1,"120":1,"123":2,"134":1,"135":1,"138":23,"206":1,"255":2,"278":1}}],["so",{"1":{"20":1,"31":1,"42":1,"61":4,"75":1,"80":1,"91":1,"144":1,"167":1,"178":2,"179":1,"189":1,"190":1,"192":1,"198":1,"201":1,"202":1,"255":1,"257":3,"268":1,"275":1,"279":1,"290":2,"295":1,"299":1,"310":2,"318":1,"319":1,"335":1,"344":1,"350":1,"367":1,"368":1,"369":1,"372":1,"374":1,"381":1,"382":1,"383":1,"392":1,"393":1,"399":1,"400":1,"420":2}}],["something",{"1":{"131":1,"255":2}}],["sometimes",{"1":{"31":1,"52":1,"171":1,"172":1,"174":1,"253":1,"256":1}}],["some",{"1":{"12":1,"25":1,"34":3,"36":1,"50":1,"98":1,"137":1,"156":1,"178":1,"197":1,"251":1,"254":1,"257":1,"275":1,"278":1,"347":1}}],["snapshot``",{"1":{"143":1}}],["snapshot",{"1":{"90":1,"143":2},"2":{"143":1}}],["snap",{"1":{"5":1,"62":1,"77":1}}],["suggests",{"1":{"417":1}}],["suffixing",{"1":{"129":1}}],["suffer",{"1":{"129":1}}],["successful",{"1":{"259":1}}],["successfully",{"1":{"252":2}}],["successor",{"1":{"93":1}}],["such",{"1":{"4":1,"10":1,"15":1,"31":3,"34":2,"78":1,"91":2,"98":2,"102":1,"113":1,"124":1,"133":2,"134":1,"135":7,"139":2,"140":2,"171":1,"182":1,"194":2,"201":1,"206":2,"222":1,"230":1,"232":1,"235":2,"240":1,"241":1,"250":1,"295":1,"299":1,"304":1,"306":1,"310":2,"337":1,"354":2,"360":1,"406":2,"419":1,"421":1}}],["suitable",{"1":{"112":1,"123":1,"124":1,"135":1,"141":1,"206":1,"248":1}}],["suit=",{"1":{"76":5}}],["suits",{"1":{"76":5}}],["suit",{"1":{"76":9,"222":1},"2":{"76":1}}],["suited",{"1":{"19":1,"230":1,"416":1}}],["supermarine",{"1":{"403":1,"418":1}}],["superior",{"1":{"230":1}}],["superellipse",{"1":{"102":1}}],["superellipses",{"0":{"102":1},"1":{"102":2}}],["superellipsoids",{"0":{"102":1},"1":{"102":1}}],["super",{"0":{"355":1},"1":{"75":1,"76":5,"77":2,"222":3,"355":1},"2":{"75":1,"76":1,"77":1,"222":1,"355":1}}],["supplied",{"1":{"306":1}}],["supplementary",{"1":{"58":1}}],["supposed",{"1":{"134":2}}],["supported",{"1":{"97":2,"112":1,"121":1,"123":2,"329":1,"379":1}}],["supporting",{"1":{"70":2}}],["support",{"0":{"279":1},"1":{"49":1,"51":1,"133":3,"138":6,"181":1,"279":5,"291":2,"312":1,"367":2,"369":1}}],["supports",{"1":{"19":1,"104":1,"111":1,"117":1,"120":1,"178":1,"231":1,"302":1,"315":1,"316":1}}],["surfacing",{"1":{"403":1}}],["surface``",{"1":{"420":1}}],["surface`",{"1":{"403":1,"418":1,"419":1,"420":2,"421":3}}],["surfaces",{"0":{"402":1},"1":{"61":4,"78":1,"135":2,"206":2,"382":1,"403":1,"411":1,"412":1,"420":2,"421":3},"2":{"61":1}}],["surface",{"0":{"400":1,"403":1,"421":1},"1":{"31":1,"60":6,"61":20,"62":10,"121":2,"135":1,"206":1,"354":1,"395":7,"396":1,"397":1,"400":8,"401":2,"403":2,"419":2,"420":30,"421":12,"422":1},"2":{"61":2,"62":2,"395":1,"400":1,"403":1,"418":1,"419":1,"420":3,"421":7}}],["surrounding",{"1":{"307":1}}],["sure",{"1":{"291":1}}],["surprisingly",{"1":{"48":1}}],["summarizes",{"1":{"238":2}}],["summary",{"0":{"346":1,"413":1,"419":1},"1":{"133":1,"138":1,"139":1,"141":1,"230":1}}],["sum",{"1":{"17":2,"59":1,"189":1}}],["subclass",{"1":{"201":1,"242":1,"274":1,"275":1}}],["subclassing",{"1":{"124":1}}],["sub`",{"1":{"49":2}}],["sub",{"0":{"343":1},"1":{"20":1,"55":1,"58":3,"124":1,"204":1,"222":2,"243":1,"341":1,"342":1,"343":3,"383":1,"384":1,"389":1,"394":1},"2":{"49":1}}],["subscription",{"1":{"138":2}}],["substitute",{"1":{"128":1}}],["substantially",{"1":{"19":1,"66":1}}],["subsequent",{"1":{"37":1,"258":1,"277":1,"345":2}}],["subsequently",{"1":{"19":1,"20":1,"202":1}}],["subsequence",{"1":{"25":1}}],["subset",{"1":{"10":3,"272":1,"274":1,"311":1}}],["subtractive",{"1":{"80":2,"342":1,"345":1}}],["subtraction",{"1":{"66":1,"194":1,"299":1}}],["subtracting",{"1":{"66":1,"70":2,"230":1,"231":1,"343":1}}],["subtract``",{"1":{"32":1,"37":1,"144":1,"151":1,"153":1,"192":2,"387":1,"388":1}}],["subtracted",{"1":{"32":1,"37":1,"164":2,"343":1,"373":1,"375":1}}],["subtract",{"1":{"4":2,"16":3,"32":1,"37":1,"42":2,"49":3,"51":1,"59":2,"60":1,"62":1,"64":3,"65":3,"69":2,"70":4,"71":2,"76":9,"80":7,"144":2,"149":2,"151":1,"152":1,"153":2,"156":1,"161":1,"164":1,"169":1,"170":1,"173":2,"174":1,"175":1,"179":1,"182":2,"189":1,"192":2,"193":2,"194":1,"224":2,"232":1,"278":2,"280":2,"281":2,"282":1,"283":2,"284":5,"285":1,"286":4,"287":2,"288":3,"289":2,"299":1,"345":3,"346":1,"350":1,"357":1,"368":5,"369":5,"373":2,"374":2,"375":4,"376":5,"377":5,"385":1,"387":1,"388":4,"389":2,"420":1},"2":{"37":1,"144":1,"151":1,"192":1,"223":1}}],["sep=",{"1":{"410":1}}],["separating",{"1":{"230":1,"245":1}}],["separation",{"1":{"219":1}}],["separate",{"1":{"80":1,"167":1,"298":1,"306":1,"410":1}}],["semantics",{"1":{"331":1}}],["semi",{"1":{"304":1}}],["searchable",{"1":{"133":1}}],["searchability",{"1":{"133":1}}],["search",{"1":{"133":1}}],["seamless",{"1":{"111":1,"112":1,"113":1,"120":1,"196":1}}],["seamlessly",{"1":{"84":1,"421":1}}],["serious",{"1":{"415":1}}],["series",{"1":{"246":1,"291":1}}],["serve",{"1":{"134":1,"141":1}}],["servers",{"1":{"140":1}}],["server",{"1":{"124":1},"2":{"124":1}}],["server``",{"1":{"104":1}}],["serves",{"1":{"78":1}}],["sergels",{"1":{"102":1}}],["several",{"1":{"78":1,"133":1,"138":1,"139":1,"140":1,"141":1,"168":1,"214":1,"236":1,"241":1,"302":1,"307":1,"312":1,"315":1,"326":1,"350":1,"414":1,"417":1,"422":1}}],["segment",{"1":{"68":8,"147":1,"148":2,"299":1}}],["segments",{"1":{"25":1,"147":1,"172":4,"218":1,"340":2}}],["self",{"0":{"259":1},"1":{"51":1,"75":1,"76":5,"77":9,"160":1,"222":1,"350":1},"2":{"184":1,"347":1}}],["selected",{"1":{"81":1,"152":3,"160":1,"240":1,"270":1,"272":1,"303":1,"344":1,"345":6,"368":1,"391":1}}],["selective",{"1":{"80":1}}],["selecting",{"0":{"319":1},"1":{"72":1,"81":2,"202":1,"256":2,"276":2,"296":1,"390":1}}],["selection",{"0":{"256":1,"277":1,"320":1},"1":{"4":1,"6":1,"126":1,"262":1,"264":5,"265":4,"266":7,"267":1,"268":1,"272":5,"273":2,"275":1,"276":1,"277":1,"292":1,"319":1,"320":1,"325":1,"329":1,"333":2}}],["select`",{"1":{"49":1,"143":1,"272":2}}],["selector=lambda",{"1":{"296":1,"299":1,"311":3,"319":1,"320":4,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"331":1}}],["selector",{"0":{"46":1,"379":1},"1":{"49":1,"233":1,"238":1,"240":1,"241":2,"269":1,"270":3,"272":4,"275":2,"331":1,"349":1,"379":1,"380":1,"388":1},"2":{"311":1,"312":1,"315":1,"319":1,"326":1,"331":1,"333":1}}],["selectors",{"0":{"6":1,"177":1,"205":1,"274":1},"1":{"6":1,"49":1,"124":1,"205":1,"238":1,"240":2,"241":1,"262":1,"268":1,"272":6,"273":1,"274":1,"277":1,"344":1,"378":1,"379":1,"382":1,"389":1,"422":1}}],["select",{"0":{"143":1,"272":1,"273":1,"339":1,"394":1},"1":{"4":1,"44":1,"71":1,"143":3,"144":1,"150":1,"151":1,"152":3,"161":1,"169":2,"177":1,"182":2,"199":1,"238":10,"256":4,"270":1,"272":23,"274":1,"280":1,"286":1,"289":1,"319":1,"344":1,"350":1,"390":1,"393":1,"394":1},"2":{"44":1,"49":1,"143":1,"272":1}}],["selects",{"1":{"4":1,"272":1,"315":1,"344":1,"345":2,"384":1}}],["session",{"1":{"49":1}}],["sense",{"1":{"48":1,"354":1}}],["sequence",{"1":{"40":1,"42":1,"202":2,"406":1}}],["seem",{"1":{"250":1}}],["seeking",{"1":{"123":1}}],["see",{"1":{"39":1,"40":1,"48":1,"59":1,"70":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"90":1,"91":1,"92":1,"93":1,"94":1,"95":2,"98":2,"99":2,"100":3,"101":1,"102":1,"104":1,"122":1,"141":2,"147":1,"159":1,"172":1,"174":1,"178":1,"184":1,"189":1,"190":1,"241":2,"262":2,"278":1,"335":1,"374":1,"379":1,"420":1}}],["seen",{"1":{"2":1,"19":1,"147":1,"246":1}}],["secant",{"1":{"312":1}}],["secure",{"1":{"138":1}}],["security",{"1":{"138":3}}],["section`",{"1":{"49":1,"110":1,"238":1}}],["section``",{"1":{"34":1}}],["sections",{"1":{"27":1,"47":1,"50":1,"68":9,"82":1,"89":1,"137":1,"181":1,"224":1,"238":1,"259":1,"340":1,"398":1},"3":{"49":1,"71":1,"72":1,"73":1,"158":1,"190":1,"229":1,"235":1,"236":1,"238":1,"239":1,"252":1,"285":1}}],["section",{"0":{"416":1},"1":{"24":1,"25":4,"33":1,"34":6,"38":1,"55":1,"57":1,"61":17,"68":6,"73":2,"78":12,"110":2,"124":5,"238":2,"239":1,"252":1,"261":1,"290":3,"291":1,"310":1,"395":4,"397":2,"398":1,"399":1,"400":1,"405":2,"408":2,"409":1,"410":2,"416":1,"420":1,"421":1},"2":{"34":1,"49":1,"61":1,"110":1,"238":1,"239":1}}],["secondly",{"1":{"177":1,"251":1}}],["second",{"1":{"19":1,"23":1,"32":2,"37":1,"110":1,"152":1,"298":1,"303":1,"353":1,"374":1}}],["seconds",{"1":{"19":1,"66":1}}],["sec",{"1":{"11":2}}],["setting",{"1":{"345":1}}],["setter",{"1":{"204":1}}],["setters",{"1":{"204":1}}],["setups",{"1":{"257":1}}],["setuptools",{"1":{"128":1}}],["setup",{"0":{"349":1,"367":1,"380":1},"1":{"22":1,"52":1,"354":1}}],["sets",{"1":{"10":1,"179":1,"245":1,"345":2}}],["set",{"1":{"9":1,"10":4,"20":1,"36":1,"61":1,"72":1,"80":1,"117":1,"139":1,"144":1,"154":1,"184":1,"194":1,"204":1,"210":1,"215":1,"216":1,"222":1,"257":1,"258":1,"299":1,"339":1,"354":3,"363":1,"376":1,"382":1,"420":1}}],["still",{"1":{"189":1,"365":1,"405":2,"410":1,"413":1,"415":1,"417":1}}],["sticker",{"1":{"42":1}}],["style",{"1":{"133":1,"197":1,"245":1,"318":1,"329":1}}],["style=",{"1":{"124":1,"396":1,"420":1}}],["style=fontstyle",{"1":{"65":2}}],["steel",{"1":{"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["stems",{"1":{"121":1}}],["stereolithography",{"1":{"121":1}}],["step9",{"1":{"377":1}}],["step8",{"1":{"376":1}}],["step7",{"1":{"375":1}}],["step6",{"1":{"374":1}}],["step5",{"1":{"373":1}}],["step4",{"1":{"372":1}}],["step10",{"1":{"368":1}}],["step>`",{"1":{"360":1}}],["stepper",{"1":{"243":8,"245":1,"247":2,"248":1}}],["steppermotor",{"1":{"243":2},"2":{"243":1}}],["steps",{"0":{"418":1},"1":{"110":1,"200":1,"230":1,"245":1,"346":1,"389":1,"411":1,"415":2,"417":1}}],["step",{"0":{"120":1,"335":1,"336":1,"337":1,"338":1,"339":1,"340":1,"341":1,"342":1,"343":1,"344":1,"345":1,"349":1,"350":1,"351":1,"352":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"367":1,"368":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"380":1,"381":1,"382":1,"383":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"394":1,"397":1,"398":1,"399":1,"400":1,"401":1},"1":{"11":1,"19":9,"42":1,"53":2,"56":1,"61":9,"67":2,"81":1,"106":1,"107":1,"118":2,"120":2,"178":1,"196":2,"235":1,"275":1,"310":1,"339":1,"340":2,"341":1,"348":2,"360":4,"361":1,"365":1,"366":2,"369":2,"372":1,"379":2,"383":1,"384":1,"389":1,"390":1,"391":2,"394":2,"399":1,"407":1,"422":2},"2":{"19":2,"36":1,"56":1,"67":1,"106":1,"107":1,"118":1,"120":1,"360":1}}],["stuff",{"1":{"251":1}}],["stubs",{"1":{"128":2}}],["stub",{"1":{"74":2}}],["stud0",{"1":{"77":1}}],["studs",{"1":{"77":6}}],["studwall",{"1":{"77":4},"2":{"77":1}}],["stud",{"0":{"77":1},"1":{"73":3,"76":1,"77":38},"2":{"77":3}}],["studio",{"1":{"53":1,"94":1}}],["storage",{"1":{"135":1,"222":1}}],["storing",{"1":{"112":1,"135":1}}],["stores",{"1":{"201":1}}],["stored",{"1":{"20":1,"74":1,"192":1,"259":1,"340":1}}],["store",{"1":{"19":1,"113":1,"120":1,"121":1,"135":2,"141":1,"243":1}}],["stockholm",{"1":{"102":1}}],["stopped",{"1":{"53":1}}],["stl>`",{"1":{"59":1}}],["stl",{"0":{"121":1,"122":1,"415":1},"1":{"56":1,"59":6,"106":1,"107":1,"108":2,"109":1,"121":2,"122":1,"178":6,"276":1,"369":1,"408":1,"409":2,"412":1,"413":1,"415":4,"416":1,"422":1},"2":{"36":1,"56":1,"106":1,"107":1,"121":1,"178":1}}],["stricter",{"1":{"333":1}}],["string",{"1":{"6":1,"219":1,"352":1}}],["strings",{"1":{"1":1,"13":1,"54":1}}],["strongest",{"1":{"310":1}}],["stronger",{"1":{"185":1}}],["strongly",{"1":{"303":1,"304":1}}],["strategy",{"1":{"152":1}}],["strategies",{"1":{"152":1}}],["straightforward",{"1":{"230":1}}],["straight",{"1":{"23":1,"25":1,"28":1,"49":1,"235":1,"299":1}}],["structured",{"1":{"417":1}}],["structure",{"1":{"113":1,"120":1,"206":5,"250":1,"277":1,"371":2,"406":2,"408":1,"415":1,"417":1}}],["structures",{"1":{"34":1,"206":1,"250":1,"338":2}}],["str",{"1":{"61":5,"65":2,"67":2,"68":2,"108":1,"354":1}}],["strength",{"1":{"99":1}}],["stress",{"1":{"61":1}}],["stream",{"1":{"51":3}}],["streamlines",{"1":{"117":1}}],["streamline",{"1":{"22":1}}],["stage",{"1":{"406":1}}],["stages",{"1":{"139":1}}],["stand",{"0":{"280":1},"1":{"280":1,"291":2}}],["standardization",{"1":{"119":1}}],["standardized",{"1":{"84":2,"99":2,"120":1,"246":1}}],["standards",{"1":{"119":5,"124":1}}],["standard",{"0":{"7":1},"1":{"3":1,"6":1,"7":5,"19":1,"51":1,"76":1,"111":1,"113":1,"119":2,"120":3,"123":1,"167":1,"168":1,"191":1,"235":1,"240":1,"241":1,"243":1,"245":1,"248":1,"294":1,"295":1,"393":1},"2":{"120":1}}],["stainless",{"1":{"184":1}}],["stay",{"1":{"184":1}}],["stays",{"1":{"133":1}}],["station",{"1":{"278":2}}],["static",{"1":{"104":1,"124":1,"134":1,"230":2,"254":1,"378":1,"396":1,"420":1}}],["states",{"1":{"119":1}}],["stateful",{"1":{"47":1,"49":1}}],["state",{"1":{"16":1,"124":1,"194":1}}],["statement",{"1":{"7":1,"23":1,"32":1,"37":1,"52":1,"312":1}}],["stable",{"1":{"61":1,"135":1}}],["stack",{"1":{"59":17,"175":1}}],["starting",{"1":{"231":1,"235":1,"236":1,"237":1,"276":4,"308":1,"421":1}}],["start=",{"1":{"147":2,"290":1,"307":2}}],["start=l6",{"1":{"74":2,"290":1}}],["start=l4",{"1":{"74":2}}],["start=l3",{"1":{"74":2}}],["start=l1",{"1":{"71":1,"74":4,"147":2,"317":1,"332":1}}],["start=l2",{"1":{"30":1,"31":1,"74":2}}],["start",{"1":{"30":2,"34":1,"61":1,"66":2,"70":1,"76":1,"78":2,"80":2,"124":1,"139":1,"146":2,"151":1,"172":1,"182":1,"218":5,"250":1,"279":1,"295":1,"306":2,"307":2,"333":1,"335":1,"362":1,"368":1,"369":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"381":1,"395":2,"397":2,"409":1,"414":1},"2":{"30":1}}],["started",{"1":{"28":1,"334":1}}],["starts",{"1":{"23":1,"30":1,"230":1,"298":1,"299":1,"332":1,"340":2}}],["irregular",{"1":{"405":1}}],["iron",{"1":{"230":8}}],["i30",{"1":{"279":3,"295":1}}],["idx",{"1":{"167":4,"168":2}}],["idea",{"1":{"255":1}}],["ideas",{"1":{"92":1,"415":1}}],["ideally",{"1":{"339":1}}],["ideals",{"1":{"75":1}}],["ideal",{"1":{"40":1,"61":1,"80":1,"111":1,"123":1}}],["identifies",{"1":{"352":1}}],["identified",{"1":{"339":1,"340":1}}],["identifier=",{"1":{"184":1}}],["identifier",{"1":{"23":1,"32":1,"37":1,"372":1,"379":1,"383":1}}],["identify",{"0":{"338":1},"1":{"335":1,"338":1,"344":1,"405":1,"415":2}}],["identifying",{"1":{"181":1,"378":1}}],["identical",{"1":{"19":1,"75":1}}],["ides",{"1":{"1":1,"2":1,"53":1}}],["illustrations",{"1":{"123":1}}],["illustrate",{"1":{"12":1,"48":1,"137":1,"199":1,"230":1,"348":1,"420":1}}],["icons",{"1":{"102":1,"123":1}}],["icosahedron",{"1":{"75":3},"2":{"75":1}}],["ipn",{"1":{"82":1}}],["ios",{"1":{"102":1}}],["io>`",{"1":{"83":1}}],["io",{"1":{"20":1,"84":1,"97":2,"104":1,"124":2,"128":1,"178":1,"251":1}}],["img",{"1":{"73":22,"264":4,"265":3,"266":6,"291":13}}],["immediately",{"1":{"61":1,"189":2,"190":1,"299":1}}],["immutable",{"1":{"20":1}}],["imageface",{"1":{"299":1},"2":{"299":1}}],["images",{"1":{"62":1,"64":1,"123":1,"124":1,"396":1,"420":1}}],["image",{"1":{"16":3,"19":1,"23":1,"25":1,"26":3,"30":1,"31":1,"32":1,"34":1,"37":1,"42":1,"48":2,"53":1,"59":3,"60":1,"61":1,"62":3,"63":1,"64":2,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"74":1,"75":1,"76":1,"77":1,"78":1,"80":2,"81":3,"119":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"179":1,"182":3,"184":2,"202":1,"208":2,"209":5,"218":28,"219":18,"220":10,"221":1,"222":2,"225":1,"230":1,"240":1,"247":1,"256":1,"257":2,"262":2,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"291":1,"299":2,"334":1,"335":1,"339":1,"340":1,"346":1,"348":1,"350":2,"357":1,"359":1,"360":1,"362":1,"363":1,"364":1,"365":1,"366":1,"368":1,"369":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"379":1,"388":1,"400":1,"401":1,"420":4},"2":{"184":1}}],["impact",{"1":{"195":1}}],["impacting",{"1":{"7":1}}],["improving",{"1":{"134":2}}],["improves",{"1":{"134":1,"299":1}}],["improvement",{"1":{"78":1}}],["improved",{"1":{"28":2,"236":1}}],["improve",{"1":{"22":1,"134":2}}],["implementing",{"1":{"341":1}}],["implements",{"1":{"278":1}}],["implementation",{"1":{"10":1,"19":1,"59":1,"60":1,"61":1,"62":2,"63":1,"64":2,"65":2,"66":1,"67":2,"68":2,"69":2,"70":2,"71":1,"72":2,"74":2,"75":1,"76":1,"77":1,"78":2,"80":1,"81":4,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"299":1},"2":{"59":1,"60":1,"61":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"74":1,"75":1,"76":1,"77":1,"78":1,"80":1,"81":1}}],["implied",{"1":{"144":1,"278":1}}],["implicit",{"0":{"34":1,"195":1},"1":{"10":1,"34":2}}],["implicitly",{"1":{"3":1,"34":2,"270":1,"421":1}}],["imports",{"1":{"255":2,"257":1,"367":1}}],["important",{"1":{"177":1,"178":1,"210":1,"238":1,"240":1,"272":1,"339":1,"359":1,"412":1}}],["imported",{"1":{"76":1,"91":1,"109":2,"255":1,"360":1}}],["importer",{"1":{"59":2,"109":9,"409":2}}],["importers",{"0":{"105":1,"107":1},"1":{"56":1,"105":1}}],["importing",{"1":{"56":1,"118":1,"416":1}}],["import",{"0":{"56":1,"109":1,"118":1,"255":1,"360":1},"1":{"4":1,"16":3,"17":3,"19":2,"26":3,"34":2,"56":5,"59":2,"60":3,"61":2,"63":2,"65":4,"66":3,"68":4,"69":4,"70":4,"72":6,"74":4,"75":5,"76":3,"78":4,"80":2,"81":4,"97":1,"99":1,"105":4,"107":3,"108":1,"109":1,"124":2,"126":1,"131":1,"178":2,"179":3,"182":2,"184":5,"193":1,"202":1,"204":1,"243":4,"251":3,"255":1,"256":1,"276":4,"278":2,"279":4,"280":2,"281":2,"282":2,"283":2,"284":2,"285":2,"286":2,"287":2,"288":2,"289":3,"290":3,"295":4,"346":2,"349":3,"360":1,"367":5,"380":3,"381":2,"382":2,"385":2,"388":2,"389":2,"395":2,"397":2,"408":1,"409":2,"410":2,"420":2},"2":{"19":1,"26":1,"56":5,"105":3,"107":3,"109":1,"255":1,"360":1,"410":1}}],["if",{"1":{"11":2,"19":1,"21":1,"31":1,"51":1,"61":2,"67":2,"68":2,"69":2,"76":5,"81":2,"108":1,"127":1,"128":2,"129":4,"131":1,"141":1,"144":1,"152":2,"169":1,"175":1,"178":3,"181":1,"190":1,"197":2,"234":1,"243":1,"252":1,"255":1,"257":1,"259":3,"261":1,"262":2,"268":2,"272":1,"306":1,"331":1,"336":2,"341":1,"342":1,"345":1,"350":2,"353":1,"405":1,"409":1,"421":1}}],["italic",{"1":{"49":1}}],["iterables",{"1":{"124":1}}],["iterable",{"1":{"49":4,"199":4}}],["iterations",{"1":{"258":1}}],["iteration",{"1":{"258":1}}],["iterative",{"1":{"230":2,"416":1}}],["iterating",{"0":{"17":1},"1":{"408":1}}],["iterator",{"1":{"20":1}}],["iterate",{"1":{"17":1,"20":1,"174":1,"410":1}}],["iter",{"2":{"20":1}}],["items",{"1":{"275":2,"279":1,"295":1},"2":{"279":1,"295":1}}],["item",{"1":{"19":1,"49":9,"73":22,"218":28,"219":18,"220":10,"255":1,"264":4,"265":3,"266":6,"291":13,"384":1}}],["itself",{"1":{"179":1,"189":1,"204":1,"217":1,"222":1,"259":1,"417":1,"420":1}}],["its",{"1":{"19":1,"30":1,"42":1,"51":1,"53":1,"61":1,"81":1,"89":1,"99":1,"111":1,"112":1,"113":1,"117":1,"121":1,"140":1,"141":1,"181":1,"184":1,"188":2,"189":1,"190":1,"198":1,"200":1,"202":1,"204":2,"211":1,"217":1,"222":1,"229":1,"231":1,"233":1,"312":1,"331":1,"332":1,"337":1,"339":1,"420":1,"421":1}}],["it",{"0":{"245":1,"249":1,"360":1},"1":{"11":3,"15":1,"18":1,"19":2,"23":1,"25":1,"26":3,"31":3,"32":1,"34":1,"37":1,"39":1,"42":4,"59":1,"61":4,"62":2,"65":2,"70":1,"71":1,"74":1,"80":1,"81":2,"90":1,"91":2,"97":1,"98":3,"99":4,"104":1,"108":1,"111":2,"112":3,"113":1,"117":2,"119":1,"120":1,"121":1,"123":2,"124":2,"128":1,"129":1,"133":4,"134":5,"138":2,"139":2,"140":8,"141":5,"143":2,"144":1,"147":1,"150":1,"151":2,"156":1,"157":2,"169":1,"172":4,"184":1,"188":2,"189":1,"190":3,"195":1,"197":1,"198":1,"200":1,"202":1,"204":2,"206":9,"210":1,"212":1,"222":3,"230":4,"235":2,"236":2,"238":2,"240":1,"241":1,"248":1,"250":1,"251":1,"252":2,"253":2,"254":2,"255":2,"256":1,"257":4,"258":1,"263":1,"276":1,"290":1,"299":1,"302":1,"306":2,"307":1,"310":6,"335":1,"338":1,"339":2,"340":1,"341":2,"345":3,"352":1,"356":1,"357":1,"360":1,"370":1,"372":1,"377":1,"388":1,"405":2,"412":1,"413":1,"415":1,"416":1,"417":2,"420":5,"421":1},"2":{"25":1,"172":1}}],["i",{"1":{"9":2,"12":1,"23":1,"32":1,"37":1,"61":2,"64":8,"68":10,"72":6,"75":27,"76":5,"77":2,"168":5,"176":1,"188":1,"198":1,"222":1,"240":1,"350":2,"352":1,"395":2,"398":2}}],["inward",{"1":{"345":1}}],["inwards",{"1":{"159":1,"160":1}}],["infer",{"1":{"310":1}}],["inf",{"2":{"276":1}}],["informative",{"1":{"417":1}}],["information",{"1":{"5":2,"52":1,"81":1,"91":1,"111":1,"112":1,"113":1,"119":2,"120":1,"121":1,"133":1,"135":2,"178":1,"195":1,"204":1}}],["info",{"1":{"51":16,"81":1},"2":{"51":1}}],["inevitable",{"1":{"258":1}}],["inequality",{"1":{"49":2}}],["inlet",{"1":{"184":6}}],["incorrect",{"1":{"254":1,"263":1}}],["incorrectly",{"1":{"169":1}}],["increase",{"1":{"230":1,"253":1}}],["incrementally",{"1":{"215":1,"216":1}}],["incremental",{"1":{"196":1,"200":1}}],["inclusive=",{"1":{"70":2,"241":1}}],["included",{"1":{"61":1,"295":1,"331":1}}],["include",{"1":{"19":1,"84":1,"104":1,"119":1,"132":1,"133":1,"194":1,"205":1,"228":1,"242":1,"246":1,"293":1,"308":1,"329":1,"342":1,"404":1,"420":1}}],["includes",{"1":{"10":1,"65":1,"80":1,"147":1,"295":1,"331":1,"351":1}}],["including",{"1":{"15":1,"49":1,"61":1,"83":1,"117":1,"119":1,"140":2,"141":1,"178":1,"233":1,"310":2}}],["init",{"1":{"75":2,"76":10,"77":4,"222":4,"350":1,"355":1},"2":{"75":1,"76":1,"77":1,"222":1,"350":1,"355":1}}],["initialized",{"1":{"355":1}}],["initialize",{"1":{"243":1}}],["initialization",{"1":{"31":1}}],["initial",{"1":{"16":2,"232":1,"258":1,"332":1}}],["industry",{"1":{"77":1,"117":1,"135":1,"235":1}}],["indicates",{"1":{"345":1,"388":1,"406":1}}],["indicate",{"1":{"194":1,"350":1,"354":1,"373":1,"405":1,"410":1,"414":3}}],["indicators",{"1":{"350":1}}],["indicator",{"1":{"65":8,"198":1}}],["indices",{"0":{"125":1},"1":{"75":3,"378":1}}],["individual",{"1":{"66":1,"100":1,"135":1,"138":1,"275":1,"421":1}}],["independence",{"1":{"121":1,"123":1}}],["independently",{"1":{"141":1,"204":1}}],["independent",{"1":{"31":1,"80":1,"240":1,"257":1,"262":1,"357":1}}],["index``",{"1":{"268":1}}],["indexed",{"1":{"268":1}}],["index",{"1":{"73":1,"76":1,"84":1,"251":1,"268":1,"269":1,"333":1},"2":{"76":1,"268":1}}],["indexing",{"1":{"49":1,"241":1,"320":1}}],["indented",{"1":{"23":1,"32":1,"37":1,"169":2}}],["inheriting",{"1":{"254":1}}],["inherit",{"0":{"254":1},"1":{"254":1}}],["inheritance",{"1":{"55":1,"58":1}}],["inherently",{"1":{"236":1}}],["inherent",{"1":{"36":1,"254":1}}],["inputs",{"0":{"199":1},"1":{"144":1,"168":1,"224":1,"238":1,"325":1,"330":1}}],["input",{"1":{"53":1,"61":2,"144":1,"158":1,"165":1,"201":2,"238":1,"257":1,"303":1,"331":2}}],["inverted",{"1":{"331":1}}],["inverse",{"1":{"9":2},"2":{"9":1}}],["invoked",{"1":{"190":1,"202":1}}],["involved",{"1":{"245":1}}],["involve",{"1":{"235":1}}],["involves",{"1":{"50":1,"78":1,"81":1,"235":1,"255":1,"334":1}}],["involving",{"1":{"81":1}}],["invalid",{"1":{"189":1,"259":1},"2":{"259":1}}],["invite",{"1":{"124":1}}],["inner``",{"1":{"364":1}}],["inner=false",{"1":{"356":1}}],["inner",{"1":{"13":2,"14":3,"179":5,"230":1,"240":2,"266":3,"350":7,"353":4,"356":1,"359":1,"363":3,"364":2,"367":1,"368":1,"369":1,"376":1,"377":1},"2":{"240":1,"350":1,"364":1}}],["intuitive",{"1":{"181":1,"189":1,"200":1,"230":1,"312":1}}],["int",{"1":{"76":10,"77":1}}],["introducing",{"1":{"310":1}}],["introduces",{"1":{"177":1,"420":1}}],["introduce",{"0":{"144":1,"147":1},"1":{"134":1}}],["introduced",{"1":{"134":1,"422":1}}],["introduction",{"0":{"136":1,"310":1},"1":{"126":1}}],["introductory",{"0":{"178":1},"1":{"32":1,"126":1}}],["intricate",{"1":{"121":1,"124":1,"235":1,"236":1,"250":1}}],["intrinsic",{"2":{"49":1}}],["intrinsic`",{"1":{"49":1}}],["intelligently",{"0":{"343":1}}],["intelligence",{"1":{"140":1}}],["intensive",{"1":{"236":1}}],["intended",{"1":{"178":1,"263":1,"331":1,"337":1,"345":1}}],["intentionally",{"1":{"318":1,"406":1,"408":1,"413":1}}],["intent",{"1":{"27":1,"30":1,"295":1,"306":1,"310":2,"313":1,"412":1,"414":1,"415":1,"417":1}}],["integration",{"0":{"251":1},"1":{"85":1,"120":1,"124":1,"133":1,"134":2,"240":1}}],["integrating",{"1":{"51":3}}],["integrated",{"1":{"94":1,"133":2,"134":2,"139":1}}],["integrate",{"1":{"84":1,"192":1,"255":1}}],["integrates",{"1":{"65":1}}],["integer",{"1":{"28":1,"189":1}}],["interested",{"1":{"368":1}}],["interesting",{"1":{"361":1}}],["interdependent",{"1":{"310":1}}],["interchange",{"1":{"251":1}}],["interoperability",{"1":{"138":3}}],["interoperable",{"1":{"111":1,"117":1,"120":1}}],["interpretation",{"1":{"405":1,"413":1}}],["interpret",{"1":{"119":1,"405":1}}],["interpolation",{"3":{"5":1,"10":1,"25":1,"34":1,"49":1,"61":1,"62":1,"68":1,"78":1,"81":1,"124":1,"145":1,"218":1,"225":1,"241":1,"304":1,"310":1}}],["international",{"1":{"119":1,"133":1}}],["internals",{"1":{"280":1}}],["internally",{"1":{"39":1,"200":1,"201":1,"358":1}}],["internal",{"0":{"374":1},"1":{"34":1,"124":1,"190":1,"194":1,"217":1,"295":1,"350":1,"369":1,"371":1,"373":1,"374":1,"375":1,"376":1}}],["interact",{"1":{"190":1,"192":1,"223":1}}],["interactive",{"1":{"104":1,"123":1,"310":1}}],["interacts",{"1":{"3":1}}],["interior",{"1":{"81":2,"206":1,"219":2,"230":2,"271":1,"294":1,"312":1,"331":3,"374":1}}],["interfaces",{"1":{"141":1}}],["interface",{"1":{"54":2,"99":3,"124":1,"255":1}}],["interfere",{"1":{"25":1,"179":1,"353":1}}],["intersects",{"1":{"402":1,"403":1}}],["intersected",{"1":{"343":1}}],["intersect``",{"1":{"192":2}}],["intersecting",{"1":{"160":1,"187":1,"218":2,"341":1,"342":1,"343":1,"403":1}}],["intersectingline",{"1":{"225":1,"286":1,"289":1,"290":1,"420":1},"2":{"49":1,"218":1,"225":1,"286":1,"289":1,"290":1,"420":1}}],["intersectingline`",{"1":{"49":1,"218":1}}],["intersection``",{"1":{"373":1}}],["intersectional",{"1":{"99":1}}],["intersection",{"0":{"259":1},"1":{"34":1,"49":1,"71":1,"78":2,"124":1,"159":2,"206":1,"306":2,"307":1,"339":1,"368":2,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"420":1},"2":{"34":1,"78":1,"124":1,"373":1}}],["intersections",{"1":{"34":5,"78":10,"124":5,"206":1,"299":1,"402":1}}],["intersect",{"1":{"10":1,"49":3,"179":2,"192":2,"194":1,"223":1,"232":1,"259":1,"272":3,"280":2,"281":2,"286":1,"288":1,"299":1,"307":2,"350":1,"395":2,"398":3,"403":1},"2":{"10":1,"37":1,"192":1,"223":1,"299":1,"395":1,"398":1}}],["into",{"0":{"377":1,"414":1},"1":{"7":1,"21":1,"26":3,"51":3,"61":3,"65":1,"71":1,"77":1,"81":1,"84":1,"94":1,"98":1,"134":1,"135":1,"139":1,"141":1,"150":1,"165":1,"172":2,"184":1,"190":1,"200":1,"206":2,"230":2,"231":1,"233":2,"235":4,"238":2,"240":1,"245":1,"253":1,"255":1,"259":1,"271":1,"276":1,"277":1,"295":1,"299":2,"303":1,"341":3,"344":1,"345":3,"359":1,"371":1,"377":2,"383":1,"388":2,"403":1,"411":1,"414":1,"417":1,"419":1,"420":4,"421":1}}],["inspecting",{"0":{"407":1}}],["inspection",{"1":{"104":1,"192":1,"248":1,"407":1}}],["inspect",{"1":{"331":1,"344":1,"408":1,"413":1}}],["inset",{"1":{"76":1,"238":1}}],["insert",{"1":{"7":1,"73":1,"81":1}}],["inserted",{"1":{"7":1}}],["inside0",{"1":{"77":2}}],["inside",{"1":{"49":1,"80":1,"233":1,"296":1,"312":1,"314":2,"345":1}}],["instructs",{"1":{"192":1,"388":1}}],["instructions",{"1":{"7":1}}],["installs",{"1":{"129":1}}],["installing",{"1":{"128":1,"129":1}}],["install",{"0":{"128":1,"129":1},"1":{"128":5,"129":5,"130":3}}],["installation",{"0":{"130":1,"131":1},"1":{"126":1,"129":1}}],["instance>",{"1":{"190":2}}],["instances",{"1":{"19":1,"170":2,"175":1,"187":1,"263":1,"406":1}}],["instance",{"0":{"195":1},"1":{"3":1,"7":1,"28":1,"108":1,"190":2,"191":1,"195":1,"252":1,"261":1,"263":1,"338":1,"371":1,"383":1}}],["instantiate",{"0":{"356":1},"1":{"222":1,"356":1,"370":1}}],["instantiated",{"0":{"3":1},"1":{"184":1,"254":1}}],["instantiating",{"1":{"42":1}}],["instantiations",{"1":{"3":1}}],["instantiation",{"1":{"3":1,"179":1,"183":1}}],["institute",{"1":{"119":1}}],["instead",{"1":{"7":1,"19":2,"66":1,"188":1,"195":1,"236":1,"280":1,"295":1,"310":2,"347":1,"405":1,"421":1}}],["in",{"0":{"11":1,"62":1,"155":1,"272":1,"273":1,"334":1,"335":1,"387":1},"1":{"2":2,"4":1,"5":2,"7":2,"9":11,"10":1,"11":5,"12":3,"13":1,"14":1,"15":2,"17":5,"18":1,"19":4,"23":1,"26":3,"28":1,"31":5,"32":1,"34":3,"36":5,"37":1,"39":1,"42":2,"49":1,"51":3,"52":2,"53":1,"55":1,"59":4,"60":5,"61":10,"62":5,"64":5,"65":2,"66":5,"67":1,"68":4,"69":2,"71":1,"72":2,"73":2,"74":1,"75":26,"76":8,"77":12,"78":2,"80":3,"81":4,"91":1,"92":1,"93":1,"94":2,"95":1,"99":2,"102":4,"104":2,"110":2,"111":2,"112":1,"113":2,"117":2,"119":8,"120":2,"121":1,"122":1,"123":2,"124":5,"128":2,"129":3,"133":4,"134":2,"135":5,"138":4,"139":2,"140":1,"141":4,"143":2,"144":3,"146":1,"147":3,"149":3,"150":1,"152":1,"153":2,"154":1,"156":3,"158":2,"159":1,"160":1,"161":1,"162":5,"167":6,"168":3,"171":1,"172":1,"174":2,"175":1,"177":2,"178":3,"179":1,"181":4,"182":4,"183":1,"184":3,"185":1,"187":2,"188":2,"189":4,"190":1,"192":4,"194":1,"195":3,"197":2,"198":5,"200":1,"201":2,"202":5,"204":1,"206":21,"209":1,"210":2,"211":4,"214":1,"217":1,"218":2,"221":4,"222":1,"224":3,"230":3,"233":3,"234":2,"235":2,"236":3,"238":2,"240":1,"243":3,"245":1,"246":1,"250":1,"252":1,"253":1,"254":2,"255":5,"256":2,"259":1,"260":1,"261":4,"262":3,"267":2,"268":1,"269":1,"270":1,"272":5,"273":1,"274":2,"276":1,"278":5,"279":1,"280":1,"289":1,"291":2,"295":3,"299":1,"303":1,"304":1,"306":2,"307":1,"310":4,"311":1,"312":1,"315":1,"318":2,"319":2,"329":1,"331":3,"332":1,"333":1,"334":1,"335":2,"338":1,"339":5,"340":3,"341":4,"343":2,"345":6,"346":1,"347":1,"348":1,"350":2,"353":1,"354":4,"359":1,"360":1,"364":2,"365":2,"367":2,"368":3,"369":3,"371":1,"372":1,"373":2,"374":4,"376":1,"377":1,"378":1,"379":2,"382":1,"385":2,"387":1,"389":1,"390":1,"391":1,"395":4,"396":1,"397":2,"398":1,"403":1,"404":1,"405":1,"406":2,"411":1,"412":1,"413":2,"414":1,"416":1,"417":2,"419":1,"420":6,"421":3,"422":3},"3":{"49":1,"59":1,"61":1,"74":1,"80":1,"157":1,"161":1,"179":1,"182":1,"238":1,"239":1,"259":1,"281":1,"282":1,"287":1,"289":1,"408":1,"409":1,"413":1}}],["isn",{"0":{"255":1},"1":{"192":1,"198":1,"254":1,"263":1,"290":1,"420":1}}],["issues",{"1":{"134":1,"138":1}}],["issue",{"1":{"129":2,"263":1}}],["isolating",{"1":{"275":1}}],["isolates",{"1":{"344":1}}],["isolated",{"1":{"269":1,"344":1,"416":1}}],["isolate",{"1":{"80":1,"267":1,"408":1,"409":1,"413":1},"2":{"267":1}}],["isometric",{"1":{"243":1,"246":1,"248":1}}],["isothread",{"1":{"179":2},"2":{"179":1}}],["iso",{"1":{"76":1,"84":1,"110":1,"119":5,"120":2,"243":5},"2":{"119":1}}],["isosceles",{"1":{"48":1,"295":5}}],["ish",{"1":{"18":1}}],["is",{"0":{"263":1},"1":{"2":2,"3":1,"5":1,"7":1,"10":7,"11":2,"14":2,"15":4,"18":1,"19":6,"20":2,"22":1,"23":5,"24":3,"25":3,"26":3,"28":2,"30":4,"31":5,"32":7,"33":3,"34":1,"37":7,"38":3,"39":3,"42":9,"48":2,"49":1,"51":13,"52":1,"53":3,"54":2,"57":1,"59":1,"60":1,"61":12,"66":4,"67":1,"72":1,"74":1,"77":2,"78":5,"80":1,"91":3,"92":1,"97":1,"99":1,"108":1,"110":4,"111":1,"112":1,"113":1,"117":2,"119":2,"120":2,"121":1,"123":7,"124":3,"127":1,"128":2,"129":2,"130":1,"134":8,"135":3,"138":10,"140":6,"141":5,"143":2,"144":1,"146":1,"147":5,"148":3,"152":2,"154":2,"155":1,"156":1,"157":5,"158":2,"163":1,"165":2,"167":2,"168":1,"169":4,"172":4,"174":1,"176":1,"177":1,"178":1,"179":2,"181":1,"182":1,"183":1,"184":3,"186":1,"188":4,"189":10,"190":1,"191":1,"192":3,"193":1,"194":2,"195":2,"197":2,"198":3,"199":4,"200":2,"201":6,"202":9,"204":1,"206":7,"209":4,"210":2,"217":1,"221":1,"222":3,"224":1,"230":4,"233":1,"234":1,"235":2,"236":2,"238":2,"240":3,"241":3,"243":1,"246":1,"250":2,"252":1,"253":2,"254":3,"255":4,"257":1,"258":1,"259":4,"260":1,"262":5,"263":4,"268":1,"271":1,"272":5,"273":3,"274":1,"275":3,"276":3,"277":2,"278":4,"281":1,"289":1,"290":1,"291":2,"294":3,"295":3,"299":4,"304":3,"306":4,"307":2,"310":7,"311":2,"312":3,"314":1,"317":1,"318":3,"322":1,"329":1,"330":1,"331":6,"332":2,"333":1,"339":2,"340":4,"341":2,"342":1,"343":1,"344":1,"345":9,"346":1,"347":1,"350":3,"352":6,"353":2,"354":5,"355":1,"356":1,"357":4,"358":2,"359":2,"360":1,"361":1,"362":3,"363":5,"364":2,"365":3,"367":1,"368":2,"369":4,"372":3,"373":4,"375":1,"376":2,"377":3,"378":1,"382":1,"383":1,"384":1,"389":1,"391":1,"393":1,"394":1,"395":2,"399":1,"400":1,"405":3,"407":1,"408":2,"409":1,"410":1,"411":3,"412":1,"413":2,"414":1,"415":4,"416":1,"417":6,"420":6,"421":3,"422":1},"2":{"20":2,"49":1,"202":1,"259":1}}],["b=30",{"1":{"295":1}}],["bj9aqpscfx>`",{"1":{"124":1}}],["bp",{"1":{"81":4,"202":2}}],["bd``",{"1":{"255":1}}],["bd",{"0":{"82":1,"83":1,"84":1},"1":{"81":5,"82":1,"83":1,"84":1,"179":1,"184":2,"202":6,"243":2}}],["b5",{"1":{"76":1}}],["bézier",{"1":{"76":1,"303":5,"421":1}}],["bb",{"1":{"67":7}}],["bbox",{"1":{"21":2,"243":8,"357":3}}],["bit",{"1":{"371":1}}],["big",{"1":{"189":2}}],["bicycle",{"0":{"60":1},"1":{"59":1,"60":2,"73":3}}],["bisect",{"1":{"59":1,"74":2,"80":1,"157":2,"161":1,"179":1,"182":1,"281":1,"282":1,"287":2,"289":1}}],["binds",{"1":{"185":1,"352":1}}],["bind",{"0":{"360":1},"1":{"184":2}}],["bin",{"1":{"15":1}}],["binary",{"1":{"10":1}}],["bridge",{"1":{"279":1}}],["broadly",{"1":{"271":1}}],["browsers",{"1":{"123":2}}],["browser",{"1":{"95":1,"104":2},"2":{"104":1}}],["bracket",{"0":{"281":1,"284":1},"1":{"281":1,"284":1,"291":2,"334":2,"335":2,"336":1,"338":1,"339":4,"340":2,"341":1,"344":6,"345":14,"346":6}}],["brackets",{"1":{"185":1}}],["bracelet",{"0":{"61":1},"1":{"60":1,"61":16,"73":3}}],["branches",{"1":{"141":2,"312":2,"315":1,"319":1,"320":1,"326":1,"330":1,"331":2}}],["branching",{"1":{"141":2}}],["branch",{"1":{"129":4,"206":1,"315":1,"319":1,"329":1,"331":1,"333":1}}],["brake",{"1":{"49":1,"238":1,"239":1,"278":4},"2":{"49":1,"238":1,"239":1,"278":1}}],["brep",{"0":{"112":1,"135":1,"416":1},"1":{"56":1,"59":1,"106":1,"107":1,"112":3,"124":1,"135":7,"250":1,"408":2,"409":2,"410":3,"413":1,"416":2,"420":1,"421":2},"2":{"56":1,"106":1,"107":1,"112":1,"409":1,"410":1,"421":1}}],["breaks",{"1":{"304":1}}],["breaking",{"1":{"134":1,"200":1}}],["break",{"1":{"53":1,"134":1,"160":1,"382":1}}],["bspline",{"1":{"49":1,"218":1,"225":1,"241":1},"2":{"49":1,"218":1,"225":1}}],["bspline`",{"1":{"49":1,"218":1}}],["bl",{"1":{"281":1,"289":1,"296":1}}],["blue",{"1":{"80":1,"108":8,"109":1,"208":1,"395":1,"401":1}}],["blob",{"1":{"102":1}}],["blowing",{"0":{"62":1},"1":{"62":1,"73":1}}],["blocks",{"1":{"367":1,"371":1,"376":2}}],["block``",{"1":{"190":1}}],["block",{"1":{"3":1,"4":1,"5":1,"6":1,"7":5,"11":3,"13":1,"14":3,"23":1,"25":1,"26":1,"28":3,"30":1,"31":1,"32":1,"34":1,"37":1,"39":3,"42":1,"51":4,"52":2,"59":1,"60":1,"61":1,"62":2,"63":1,"64":2,"65":2,"66":1,"67":2,"68":2,"69":2,"70":2,"71":1,"72":2,"73":1,"74":2,"75":1,"76":1,"77":1,"78":2,"80":1,"81":5,"108":1,"109":2,"110":1,"118":1,"124":1,"142":2,"143":2,"144":2,"145":2,"146":2,"147":2,"148":2,"149":2,"150":2,"151":2,"152":2,"153":2,"154":2,"155":2,"156":2,"157":2,"158":2,"159":2,"160":2,"161":2,"162":2,"163":2,"164":2,"165":2,"166":2,"167":2,"168":2,"169":2,"170":2,"171":2,"172":2,"173":2,"174":2,"175":2,"176":2,"177":2,"179":1,"180":1,"182":1,"184":3,"185":1,"187":4,"188":8,"189":3,"190":3,"191":3,"192":1,"193":2,"195":2,"198":3,"199":2,"201":2,"202":2,"206":1,"208":3,"209":5,"210":1,"211":2,"213":4,"215":2,"216":2,"217":2,"221":2,"222":1,"224":2,"230":3,"238":2,"240":2,"243":1,"245":1,"251":2,"256":1,"262":2,"263":1,"267":1,"268":1,"270":1,"272":6,"273":2,"275":1,"276":3,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"292":1,"295":2,"296":1,"298":1,"299":1,"304":1,"307":2,"311":1,"314":1,"317":1,"319":2,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"331":1,"332":1,"336":1,"340":1,"341":1,"344":2,"345":3,"346":2,"349":1,"350":1,"352":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":5,"368":11,"369":14,"370":2,"371":2,"372":4,"373":5,"374":5,"375":7,"376":7,"377":7,"380":1,"381":1,"382":1,"385":1,"388":1,"389":1,"395":2,"397":1,"398":1,"399":1,"400":1,"401":1,"409":1,"410":1,"417":3,"420":7},"2":{"190":1}}],["blends",{"1":{"403":1,"417":1,"421":1}}],["blending",{"1":{"218":1,"303":2},"2":{"303":1}}],["blender",{"1":{"85":1,"135":1,"137":1}}],["blendquery>`",{"1":{"85":1}}],["blendquery",{"0":{"85":1}}],["blend",{"1":{"218":1,"303":2,"304":1},"3":{"49":1,"71":1,"72":1,"73":1,"158":1,"190":1,"229":1,"235":1,"236":1,"238":1,"239":1,"252":1,"285":1}}],["blendcurve",{"1":{"225":1,"304":1},"2":{"49":1,"218":1,"225":1,"303":1,"304":1,"310":1}}],["blendcurve`",{"1":{"49":1,"218":1,"303":2,"310":1}}],["b0",{"1":{"26":2,"76":4,"222":2}}],["buffer",{"0":{"280":1},"1":{"280":1,"291":2}}],["bunch",{"1":{"257":1}}],["bundle",{"1":{"69":4}}],["bug",{"1":{"141":1}}],["bugs",{"1":{"134":6}}],["budgets",{"1":{"140":1}}],["bumper",{"1":{"80":8}}],["bulged",{"1":{"61":1}}],["built",{"1":{"20":1,"51":1,"61":1,"99":1,"124":1,"135":1,"181":1,"189":1,"194":1,"295":1,"317":1,"352":1}}],["builds",{"1":{"172":1,"243":1,"303":1}}],["buildsketches",{"1":{"158":1}}],["buildsketch`",{"1":{"49":1,"144":1,"164":1,"167":1,"168":1,"172":1,"382":1}}],["buildsketch",{"0":{"26":1,"38":1,"144":1,"262":1,"263":1},"1":{"3":1,"4":2,"7":1,"24":1,"25":2,"26":6,"34":2,"37":2,"38":2,"41":1,"42":2,"49":3,"59":2,"60":2,"62":3,"63":1,"64":1,"65":2,"67":5,"68":1,"69":2,"70":3,"71":3,"72":1,"74":2,"76":11,"77":1,"78":2,"80":10,"81":2,"124":2,"144":2,"145":1,"147":1,"148":1,"149":2,"150":1,"151":1,"152":2,"154":1,"155":2,"156":1,"157":1,"158":2,"159":4,"161":1,"162":1,"163":2,"164":1,"165":1,"166":1,"167":1,"168":2,"169":3,"170":1,"171":2,"172":1,"173":1,"174":1,"175":1,"176":1,"179":2,"182":5,"184":1,"190":1,"191":1,"193":2,"194":2,"195":1,"202":4,"221":2,"222":1,"224":1,"230":1,"235":1,"238":2,"240":1,"241":4,"250":1,"262":2,"263":1,"270":1,"278":2,"279":2,"280":6,"281":4,"282":3,"283":3,"284":8,"285":4,"286":1,"287":6,"288":3,"289":3,"290":1,"299":1,"340":2,"341":1,"345":3,"346":2,"350":2,"368":1,"369":2,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"382":1,"385":1,"388":1,"389":1,"420":1},"2":{"3":1,"4":1,"7":1,"25":1,"26":1,"34":1,"37":1,"39":1,"41":1,"42":1,"49":1,"59":1,"60":1,"62":1,"63":1,"64":1,"65":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"74":1,"76":1,"77":1,"78":1,"80":1,"81":1,"124":1,"144":1,"145":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"179":1,"182":1,"184":1,"190":1,"191":1,"193":1,"195":1,"201":1,"202":1,"221":1,"222":1,"224":1,"230":1,"238":1,"240":1,"250":1,"262":1,"263":1,"270":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"299":1,"340":1,"341":1,"345":1,"346":1,"350":1,"368":1,"369":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"382":1,"385":1,"388":1,"389":1,"420":1}}],["build",{"0":{"272":1,"399":1},"1":{"29":1,"35":1,"41":1,"42":2,"44":1,"45":4,"46":5,"47":3,"60":1,"61":4,"67":33,"69":2,"70":2,"77":1,"90":1,"91":1,"99":1,"157":1,"164":1,"172":2,"178":1,"196":1,"231":1,"233":1,"239":10,"240":1,"252":1,"270":1,"272":1,"299":1,"366":1,"396":2,"420":1,"421":1,"422":1},"2":{"45":1,"46":1}}],["builder``",{"1":{"195":2}}],["builder",{"0":{"43":1,"190":1,"194":1,"195":1,"197":1,"200":1,"211":1,"296":1,"297":1,"370":1,"371":1},"1":{"26":1,"46":5,"49":12,"59":1,"60":1,"62":7,"63":1,"64":2,"65":1,"67":2,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"76":13,"78":1,"80":2,"81":2,"118":2,"126":2,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"178":2,"181":2,"184":4,"189":12,"190":1,"192":4,"193":1,"194":4,"195":7,"196":1,"197":3,"198":1,"199":1,"200":2,"211":2,"214":1,"218":1,"222":2,"223":1,"224":1,"230":1,"238":16,"254":2,"270":1,"272":1,"273":1,"274":1,"278":1,"311":1,"319":1,"333":1,"350":2,"352":1,"355":2,"357":2,"358":1,"359":2,"369":2,"370":1,"371":3,"388":1},"2":{"194":1,"195":2}}],["builders",{"0":{"47":1,"191":1,"254":1},"1":{"4":1,"31":1,"43":1,"47":1,"54":1,"126":1,"191":3,"194":1,"196":1,"198":1,"202":1,"242":1,"254":2}}],["building",{"0":{"172":1},"1":{"19":1,"27":1,"30":1,"61":1,"62":1,"77":1,"99":1,"156":1,"168":1,"194":1,"206":1,"229":1,"234":1,"236":1,"242":1,"310":1,"383":1,"420":1,"421":2}}],["buildline`",{"1":{"49":1,"170":1,"172":1}}],["buildline",{"0":{"24":1,"25":1,"26":1,"263":1},"1":{"5":1,"23":3,"24":2,"25":4,"26":11,"28":4,"29":1,"30":3,"31":6,"34":2,"42":1,"49":3,"56":1,"60":1,"62":1,"65":1,"67":3,"68":1,"71":1,"74":2,"76":4,"78":2,"80":2,"81":1,"105":1,"124":2,"145":1,"147":1,"148":2,"157":1,"163":1,"165":1,"170":2,"172":1,"176":1,"184":1,"191":1,"194":2,"218":1,"222":2,"235":3,"238":1,"241":3,"263":1,"278":3,"279":1,"280":1,"281":1,"282":2,"286":1,"288":1,"289":1,"290":2,"296":1,"298":1,"299":1,"307":1,"317":1,"319":1,"331":1,"332":1,"340":2,"341":1,"346":1,"350":1,"369":1,"420":1},"2":{"5":1,"23":1,"25":1,"26":2,"28":1,"29":1,"30":1,"31":1,"34":1,"42":1,"49":1,"56":1,"60":1,"62":1,"65":1,"67":1,"68":1,"71":1,"74":1,"76":1,"78":1,"80":1,"81":1,"105":1,"124":1,"145":1,"147":1,"148":1,"157":1,"163":1,"165":1,"170":1,"172":1,"176":1,"184":1,"191":1,"222":1,"263":1,"270":1,"278":1,"279":1,"280":1,"281":1,"282":1,"286":1,"288":1,"289":1,"290":1,"296":1,"298":1,"299":1,"307":1,"317":1,"319":1,"331":1,"332":1,"340":1,"341":1,"346":1,"350":1,"420":1}}],["buildpart`",{"1":{"49":1,"164":1,"181":1,"184":1,"357":1,"359":1,"381":1,"383":1}}],["buildpart",{"0":{"25":1,"33":1,"381":1},"1":{"4":1,"7":1,"24":1,"25":4,"31":2,"32":2,"33":2,"34":2,"35":1,"38":1,"42":1,"49":3,"51":5,"59":1,"63":1,"64":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"74":1,"75":1,"76":2,"77":2,"78":1,"80":4,"81":2,"118":1,"124":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":3,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"179":2,"182":2,"184":1,"189":2,"190":1,"191":1,"193":2,"194":2,"195":2,"198":1,"199":1,"201":2,"202":2,"224":1,"230":1,"235":1,"238":2,"241":5,"250":1,"251":1,"255":1,"256":1,"272":6,"278":3,"279":1,"280":2,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":2,"289":1,"290":1,"341":2,"343":1,"346":1,"350":4,"357":1,"359":1,"368":1,"369":3,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"381":1,"382":1,"385":1,"388":1,"389":1,"420":1},"2":{"4":1,"7":1,"25":1,"32":1,"34":1,"35":1,"42":1,"49":1,"59":1,"63":1,"64":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"74":1,"76":1,"77":1,"78":1,"80":1,"81":1,"118":1,"124":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"179":1,"181":1,"182":1,"184":1,"189":1,"190":1,"191":1,"193":1,"195":1,"198":1,"199":1,"201":1,"202":1,"224":1,"230":1,"238":1,"250":1,"251":1,"255":1,"256":1,"270":1,"272":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"341":1,"346":1,"350":1,"357":1,"359":1,"368":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"381":1,"382":1,"383":1,"385":1,"388":1,"389":1,"420":1}}],["build123d>`",{"1":{"87":1,"97":1}}],["build123d",{"0":{"67":1,"79":1,"128":1,"129":1,"131":1,"237":1,"251":1,"255":1,"334":1},"1":{"2":1,"3":1,"4":2,"5":1,"6":1,"7":2,"10":1,"11":3,"12":1,"13":1,"14":3,"16":1,"17":2,"19":2,"20":2,"23":1,"25":1,"26":1,"28":3,"30":1,"31":1,"32":1,"34":2,"36":1,"37":1,"39":3,"42":1,"47":1,"50":1,"51":4,"52":2,"55":1,"56":1,"58":1,"59":1,"60":3,"61":4,"62":2,"63":2,"64":2,"65":5,"66":3,"67":5,"68":4,"69":4,"70":4,"71":1,"72":4,"73":4,"74":4,"75":2,"76":2,"77":1,"78":4,"80":3,"81":7,"84":1,"85":1,"86":1,"89":1,"91":1,"93":1,"94":2,"95":1,"97":3,"98":2,"99":2,"104":3,"108":1,"109":1,"110":1,"118":2,"122":1,"124":9,"128":4,"129":8,"130":3,"131":1,"135":1,"137":1,"142":2,"143":2,"144":2,"145":2,"146":2,"147":3,"148":2,"149":2,"150":2,"151":2,"152":2,"153":2,"154":2,"155":2,"156":2,"157":2,"158":2,"159":2,"160":2,"161":2,"162":2,"163":3,"164":2,"165":2,"166":2,"167":2,"168":2,"169":2,"170":2,"171":2,"172":2,"173":2,"174":2,"175":2,"176":2,"177":2,"178":6,"179":2,"182":2,"184":4,"185":1,"186":1,"187":4,"188":8,"189":3,"190":1,"191":3,"192":1,"193":2,"195":3,"197":2,"198":2,"199":2,"200":1,"201":3,"202":4,"203":1,"204":2,"206":13,"208":3,"209":5,"210":1,"211":1,"213":4,"214":1,"215":2,"216":2,"217":2,"221":2,"222":1,"224":2,"229":2,"230":9,"231":1,"232":1,"233":7,"234":2,"235":2,"236":1,"237":1,"238":2,"240":2,"241":1,"243":3,"251":8,"252":1,"254":1,"255":8,"256":2,"258":1,"260":1,"262":2,"263":1,"267":1,"268":1,"270":1,"272":6,"273":2,"275":1,"276":4,"277":1,"278":2,"279":2,"280":2,"281":2,"282":2,"283":2,"284":2,"285":2,"286":2,"287":2,"288":2,"289":2,"290":2,"291":2,"292":1,"295":6,"296":1,"298":1,"299":2,"302":1,"304":1,"307":2,"310":2,"311":1,"314":1,"317":1,"319":2,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"331":1,"332":1,"334":1,"336":1,"339":1,"340":3,"341":2,"344":2,"345":2,"346":3,"349":3,"350":1,"352":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"362":1,"363":1,"364":1,"365":1,"367":5,"368":1,"369":2,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"380":3,"381":2,"382":2,"385":2,"388":2,"389":2,"395":2,"396":1,"397":2,"398":1,"399":1,"400":1,"401":1,"409":2,"410":2,"413":2,"415":2,"416":1,"417":4,"419":1,"420":8,"421":2,"422":1},"2":{"176":1,"346":1}}],["butt",{"1":{"350":1}}],["button",{"1":{"53":1,"415":1}}],["but",{"1":{"19":1,"20":1,"24":1,"28":1,"31":1,"34":2,"38":1,"39":1,"40":1,"71":2,"97":1,"99":1,"135":1,"141":1,"153":1,"160":1,"172":1,"188":1,"192":1,"198":1,"202":1,"221":1,"222":1,"230":1,"236":1,"254":1,"255":1,"258":1,"261":1,"262":1,"272":2,"273":1,"279":1,"295":2,"303":1,"310":1,"343":1,"354":1,"358":1,"367":1,"368":1,"374":1,"413":1,"416":1,"417":1,"420":1}}],["b4",{"1":{"16":3,"76":2}}],["b3d",{"1":{"251":7}}],["b3",{"1":{"16":3,"26":1,"76":3,"222":1}}],["b2",{"1":{"16":3,"26":2,"76":6,"81":2,"222":2}}],["b123d",{"1":{"251":2}}],["b1",{"1":{"16":3,"26":2,"76":6,"222":2}}],["barrel",{"1":{"350":14,"352":1,"353":5,"356":2},"2":{"350":1}}],["bars",{"0":{"82":1},"1":{"82":3,"368":1,"369":1,"374":3,"375":1,"376":1,"377":1}}],["band",{"1":{"276":1}}],["bad",{"0":{"255":1},"1":{"257":1,"367":1}}],["balljoint",{"1":{"179":2,"184":1},"2":{"179":1,"181":1}}],["balljoint`",{"1":{"179":1,"181":1}}],["ball",{"0":{"179":1},"1":{"179":9}}],["balance",{"1":{"75":1}}],["background",{"1":{"250":2}}],["backlinks",{"1":{"178":1}}],["backup",{"1":{"141":2}}],["back",{"1":{"15":1,"182":1,"190":1,"191":1,"344":2,"377":1}}],["baseline",{"1":{"290":2}}],["baselineobject",{"1":{"225":1},"2":{"222":1,"225":1}}],["baselineobject`",{"1":{"222":1}}],["basesketchobject`",{"1":{"222":3}}],["basesketchobject",{"1":{"76":5,"222":1,"226":1},"2":{"222":1,"226":1}}],["basepartobject`",{"1":{"222":1}}],["basepartobject",{"1":{"75":1,"77":1,"227":1},"2":{"222":1,"227":1}}],["base",{"0":{"283":1,"381":1,"382":1},"1":{"57":1,"80":3,"191":1,"193":2,"206":1,"217":1,"222":2,"241":1,"279":3,"283":1,"290":2,"291":1,"350":1,"355":1,"367":2,"368":2,"369":1,"377":1,"414":1}}],["based",{"0":{"162":1},"1":{"6":1,"54":1,"61":1,"81":1,"86":1,"87":1,"94":1,"98":1,"104":1,"123":2,"124":1,"129":1,"134":1,"135":16,"141":1,"163":1,"186":1,"214":1,"230":1,"233":1,"234":1,"267":2,"268":1,"275":1,"344":1,"345":2,"381":1,"421":1}}],["bash",{"1":{"51":1,"52":1}}],["basis",{"1":{"42":1,"278":1}}],["basics",{"0":{"420":1}}],["basicconfig",{"1":{"51":1},"2":{"51":1}}],["basic",{"0":{"23":1,"32":1,"37":1},"1":{"10":1,"77":1,"182":1}}],["boat",{"1":{"421":1}}],["board",{"0":{"64":1,"74":1},"1":{"62":1,"64":2,"72":1,"73":6,"74":1}}],["boss",{"1":{"414":1}}],["bool",{"1":{"350":2}}],["boolean",{"1":{"61":1,"66":1,"135":1,"184":1,"204":1,"206":2,"232":1,"410":1}}],["border=",{"1":{"243":1}}],["border=vis",{"1":{"243":1}}],["border=perimeter",{"1":{"243":2}}],["border",{"1":{"243":5,"245":1}}],["bore",{"1":{"146":5,"220":2,"289":2},"3":{"10":1,"11":1,"32":1,"37":1,"49":1,"51":1,"60":1,"61":1,"63":1,"64":1,"65":1,"66":1,"73":1,"76":1,"84":1,"135":1,"143":1,"144":1,"146":1,"153":1,"156":1,"162":1,"179":1,"180":1,"182":1,"192":1,"220":1,"227":1,"240":1,"256":1,"258":1,"265":1,"278":1,"279":1,"280":1,"281":1,"283":1,"287":1,"289":1,"299":1,"336":1,"345":1,"346":1,"350":1,"354":1,"357":1,"359":1,"365":1,"385":1,"387":1,"388":1,"391":1,"414":1,"420":1}}],["boms",{"1":{"139":1}}],["body",{"1":{"78":1,"80":28,"151":2,"243":2,"278":1,"286":3}}],["bolt",{"1":{"63":2,"179":1}}],["bolditalic",{"1":{"49":1}}],["bold",{"1":{"49":1,"65":2}}],["bounded",{"1":{"206":1,"421":1}}],["boundaries",{"1":{"206":2,"421":2}}],["boundary",{"0":{"135":1},"1":{"61":3,"112":1,"135":1,"340":2,"419":1,"420":3,"421":3}}],["bound",{"1":{"181":1,"184":1,"360":2,"361":1}}],["bounds",{"1":{"61":1}}],["boundbox",{"1":{"55":1},"2":{"55":1}}],["bounding",{"1":{"15":1,"21":4,"48":2,"49":2,"61":1,"67":2,"76":5,"110":1,"222":1,"238":2,"239":1,"243":3,"357":1,"410":1,"421":1},"2":{"21":1,"49":1,"61":1,"67":1,"76":1,"110":1,"222":1,"238":1,"239":1,"243":1,"357":1}}],["bowl",{"1":{"34":6,"78":14,"124":6}}],["bottle",{"0":{"163":1},"1":{"163":2}}],["bottom",{"1":{"34":2,"42":1,"49":2,"59":1,"61":1,"70":8,"72":5,"74":2,"78":4,"124":2,"202":1,"243":2,"249":1,"262":1,"276":1,"278":2,"368":1,"369":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"419":1,"420":7},"2":{"202":1}}],["bottoms",{"1":{"22":1}}],["both``",{"1":{"315":1}}],["both=true",{"1":{"42":1,"80":4,"156":2,"279":1,"281":1,"288":2,"420":1}}],["both",{"0":{"185":1},"1":{"11":1,"25":1,"30":1,"34":1,"42":1,"49":2,"61":1,"66":1,"74":4,"77":1,"80":2,"108":1,"109":1,"112":1,"119":1,"121":1,"129":1,"135":1,"141":1,"156":1,"160":1,"161":1,"165":1,"169":1,"180":1,"184":2,"188":1,"197":2,"201":1,"238":1,"251":2,"262":1,"270":1,"273":1,"278":1,"292":1,"296":1,"315":1,"319":1,"326":1,"330":1,"352":1,"354":1,"376":2},"2":{"315":1}}],["box`",{"1":{"49":2,"142":1,"153":2,"220":1,"238":1}}],["boxes",{"1":{"15":1,"48":1,"198":1,"201":1,"202":2,"257":3},"2":{"257":1}}],["box",{"0":{"357":1,"358":1,"362":1,"417":1},"1":{"4":4,"7":1,"13":3,"14":7,"16":4,"17":4,"21":4,"32":2,"42":1,"48":1,"49":1,"51":1,"61":1,"67":2,"76":15,"81":4,"110":1,"118":4,"131":1,"142":2,"143":2,"144":2,"151":2,"153":3,"154":2,"156":2,"158":2,"160":2,"161":3,"169":2,"170":2,"177":2,"179":1,"182":2,"185":1,"187":8,"188":16,"195":2,"198":1,"199":1,"201":3,"202":2,"204":9,"209":28,"210":2,"211":1,"220":2,"222":3,"227":1,"238":1,"239":1,"240":1,"243":3,"251":4,"256":1,"272":11,"273":7,"276":3,"286":2,"290":1,"347":3,"348":1,"350":1,"352":1,"356":1,"357":9,"358":4,"359":2,"362":3,"363":2,"364":1,"368":3,"369":2,"410":1,"417":5},"2":{"4":1,"7":1,"10":1,"16":1,"17":1,"21":1,"32":1,"49":2,"61":1,"67":1,"76":1,"81":1,"110":1,"118":1,"131":1,"142":1,"143":1,"144":1,"151":1,"153":1,"154":1,"156":1,"158":1,"160":1,"161":1,"169":1,"170":1,"177":1,"179":1,"182":1,"185":1,"187":1,"188":1,"195":1,"198":1,"199":1,"201":1,"202":1,"204":2,"209":2,"211":1,"220":1,"222":2,"227":1,"238":1,"239":1,"240":1,"243":1,"251":2,"256":1,"272":1,"273":1,"276":1,"286":1,"290":1,"357":2,"359":1,"362":1,"368":1,"369":1,"417":1}}],["b`",{"1":{"10":2}}],["b^2",{"1":{"10":1}}],["b",{"0":{"323":1,"324":1},"1":{"9":3,"10":17,"81":4,"102":1,"138":1,"146":6,"147":6,"148":4,"150":2,"151":7,"163":7,"166":12,"167":6,"168":4,"173":6,"174":10,"175":4,"185":1,"187":1,"189":1,"204":2,"218":1,"224":4,"295":1},"2":{"294":2,"295":1}}],["by|",{"1":{"266":3,"267":2,"268":2,"269":1,"271":3,"275":1}}],["bytes",{"1":{"189":2},"2":{"189":1}}],["byte",{"1":{"92":1}}],["by=axis",{"1":{"202":2}}],["by=plane",{"1":{"74":2,"80":1,"157":2,"161":1,"179":1,"182":1,"281":1,"282":1,"287":2,"289":1}}],["by=",{"1":{"70":1,"243":1}}],["by=height",{"1":{"62":1,"76":4,"222":1}}],["by=roof",{"1":{"59":1}}],["by``",{"1":{"384":1}}],["by`",{"1":{"49":5,"152":2,"177":1,"240":1,"266":3}}],["by",{"0":{"6":1,"392":1},"1":{"4":1,"6":1,"7":1,"12":1,"14":1,"15":1,"20":1,"22":1,"23":1,"25":3,"26":1,"28":4,"31":2,"32":2,"34":1,"36":2,"37":2,"39":2,"40":1,"42":2,"49":3,"51":4,"53":2,"55":1,"58":1,"59":9,"60":1,"61":1,"62":1,"63":2,"67":5,"68":2,"69":7,"70":7,"71":1,"72":3,"74":3,"75":1,"76":4,"78":4,"80":16,"81":10,"91":1,"93":1,"97":2,"99":1,"102":2,"108":1,"110":1,"111":2,"112":1,"113":1,"117":2,"119":2,"123":3,"124":2,"129":1,"134":5,"135":1,"138":8,"139":2,"143":2,"144":9,"146":2,"150":2,"151":6,"152":8,"154":2,"156":2,"158":3,"160":2,"161":4,"162":3,"163":4,"166":1,"169":5,"170":2,"176":1,"177":6,"182":9,"183":1,"184":2,"188":3,"189":4,"190":1,"191":2,"192":1,"193":1,"194":1,"196":1,"197":1,"199":1,"200":1,"201":4,"202":3,"217":1,"218":26,"219":13,"220":9,"224":1,"230":6,"231":1,"232":1,"233":2,"237":1,"238":4,"240":1,"241":15,"243":10,"245":1,"250":2,"251":1,"252":1,"253":2,"254":1,"255":1,"256":2,"257":1,"258":1,"262":6,"263":1,"266":4,"267":2,"268":4,"269":2,"271":7,"272":4,"273":2,"274":1,"275":3,"276":6,"278":12,"280":7,"281":3,"282":3,"284":6,"285":1,"286":1,"287":4,"289":7,"290":4,"291":1,"292":1,"296":1,"299":1,"307":3,"308":1,"310":3,"311":1,"312":1,"317":1,"319":2,"320":3,"331":5,"335":2,"339":1,"340":2,"341":2,"342":1,"343":1,"344":8,"345":9,"346":4,"348":1,"350":3,"357":1,"366":1,"368":4,"369":5,"370":1,"377":1,"378":2,"379":3,"382":3,"384":2,"385":1,"387":1,"388":1,"389":4,"391":1,"392":3,"393":2,"394":4,"395":1,"400":1,"405":1,"406":1,"408":1,"410":1,"417":10,"419":2,"420":5,"421":3,"422":1},"2":{"6":1,"34":1,"42":2,"49":4,"59":3,"60":1,"63":2,"67":1,"69":3,"70":1,"72":1,"76":1,"78":1,"80":2,"81":3,"124":1,"143":1,"144":3,"146":1,"150":2,"151":3,"152":2,"154":2,"156":1,"158":2,"160":1,"161":1,"162":1,"163":1,"169":1,"170":1,"177":2,"182":3,"193":1,"202":1,"230":1,"240":1,"241":1,"243":2,"256":2,"262":2,"266":5,"267":1,"268":1,"272":1,"273":1,"275":1,"276":2,"278":3,"280":2,"281":3,"282":2,"284":3,"285":1,"286":1,"287":2,"289":3,"290":2,"292":1,"296":1,"299":1,"311":1,"319":2,"320":2,"331":1,"344":2,"345":1,"346":3,"350":2,"357":1,"368":1,"369":1,"382":1,"384":1,"385":1,"388":1,"389":2,"391":1,"392":2,"393":2,"394":2,"395":1,"400":1,"417":1}}],["belong",{"1":{"256":1,"406":2}}],["below",{"1":{"11":1,"17":1,"55":1,"56":1,"57":1,"58":1,"98":1,"100":1,"110":2,"118":1,"124":1,"178":2,"179":1,"180":1,"189":1,"204":1,"206":1,"214":1,"250":1,"291":1,"312":1,"350":1,"357":1},"2":{"110":1}}],["better",{"1":{"134":2,"135":1,"138":1,"229":1,"230":2,"236":1,"405":1,"416":1}}],["between",{"1":{"5":1,"15":1,"18":1,"28":1,"48":1,"54":1,"102":1,"111":1,"112":1,"113":1,"120":1,"123":1,"133":2,"139":1,"147":1,"235":1,"236":1,"262":1,"272":1,"279":1,"295":1,"303":1,"337":1,"340":1}}],["behaviour",{"1":{"254":1}}],["behavior",{"1":{"134":2,"144":2,"310":3,"312":1,"313":1,"331":1},"2":{"313":1}}],["behaves",{"1":{"189":1}}],["behave",{"1":{"134":2,"158":1}}],["bend",{"1":{"336":1,"340":1,"346":1}}],["benefit",{"1":{"134":1}}],["benchy",{"0":{"59":1},"1":{"59":16,"73":4}}],["bernhard",{"1":{"94":1,"130":1,"181":1,"299":1}}],["beam",{"1":{"176":1}}],["beams",{"0":{"82":1},"1":{"82":3}}],["bearings",{"1":{"261":1}}],["bearing",{"0":{"63":1,"281":1,"286":1},"1":{"63":8,"67":1,"73":3,"238":1,"281":1,"286":1,"291":2}}],["because",{"1":{"61":1,"75":1,"129":1,"134":1,"139":1,"189":2,"250":1,"262":1,"299":1,"306":1,"330":1,"331":1,"417":1}}],["becomes",{"1":{"230":1,"421":1}}],["become",{"1":{"19":1,"60":1,"310":1,"378":1,"414":1}}],["beyond",{"0":{"231":1},"1":{"52":1,"71":1,"102":1,"233":3,"240":1,"345":1}}],["before",{"0":{"250":1},"1":{"39":1,"69":4,"80":1,"128":1,"134":1,"143":1,"157":2,"189":2,"211":1,"250":2,"272":1,"273":4,"334":2,"349":1,"367":1,"380":1,"388":1,"415":2}}],["best",{"0":{"260":1},"1":{"34":1,"52":1,"127":1,"178":1,"197":1,"250":1,"403":1,"417":1,"420":1}}],["bed",{"1":{"21":1,"80":1}}],["begin",{"1":{"233":1,"409":1}}],["beginners",{"1":{"140":1}}],["beginning",{"1":{"5":3,"25":1,"28":1,"34":1,"78":2,"124":1}}],["begins",{"1":{"15":1,"235":1}}],["bezier`",{"1":{"49":1,"165":1,"218":1}}],["bezier",{"0":{"165":1},"1":{"26":4,"49":1,"60":20,"76":13,"165":3,"218":1,"222":4,"225":1,"241":1,"420":1,"421":1},"2":{"10":1,"26":1,"49":1,"60":1,"76":1,"165":1,"218":1,"222":1,"225":1,"420":1,"421":1}}],["being",{"1":{"5":1,"9":2,"23":1,"32":1,"37":1,"39":1,"42":1,"62":2,"189":1,"194":1,"238":1,"250":1,"255":2,"270":1,"324":1,"352":1,"354":1}}],["bevel",{"1":{"177":1,"232":1,"238":1},"3":{"4":1,"7":1,"10":1,"34":1,"42":1,"49":1,"51":1,"63":1,"65":1,"68":1,"69":1,"70":1,"71":1,"76":1,"78":1,"80":1,"81":1,"124":1,"135":1,"143":1,"144":1,"149":1,"151":1,"163":1,"177":1,"179":1,"182":1,"190":1,"199":1,"218":1,"225":1,"230":1,"232":1,"233":1,"238":1,"239":1,"250":1,"253":1,"256":1,"272":1,"273":1,"278":1,"281":1,"282":1,"284":1,"286":1,"287":1,"289":1,"290":1,"314":1,"336":1,"340":1,"341":1,"344":1,"346":1,"350":1,"389":1,"404":1,"414":1,"417":1}}],["be",{"1":{"2":2,"3":1,"4":1,"7":2,"10":1,"11":1,"12":1,"13":2,"14":1,"17":1,"19":2,"20":2,"26":1,"28":3,"31":5,"34":3,"36":2,"39":2,"42":3,"50":1,"51":1,"53":1,"58":1,"60":1,"62":2,"74":1,"75":2,"77":2,"91":2,"97":2,"98":1,"99":1,"102":2,"110":4,"113":1,"122":1,"123":2,"124":2,"128":1,"133":6,"134":6,"135":3,"138":5,"139":3,"140":1,"141":2,"144":6,"147":1,"149":1,"152":2,"154":1,"158":1,"159":3,"160":4,"166":1,"171":1,"172":1,"177":2,"178":1,"181":4,"182":4,"183":1,"184":2,"185":1,"187":3,"188":4,"189":1,"190":2,"191":1,"192":4,"194":1,"197":4,"198":1,"199":1,"201":4,"202":4,"204":1,"206":1,"210":2,"211":1,"218":1,"221":2,"222":3,"235":1,"236":1,"238":3,"240":1,"241":1,"250":1,"252":3,"255":1,"256":1,"257":1,"258":4,"259":2,"261":1,"262":2,"263":5,"267":3,"268":5,"274":1,"275":3,"276":3,"291":1,"299":1,"306":1,"307":1,"310":1,"312":2,"313":1,"325":3,"336":2,"338":1,"339":2,"340":1,"342":1,"343":2,"344":2,"345":6,"347":1,"353":2,"356":1,"357":1,"358":1,"360":2,"361":1,"362":1,"363":1,"367":1,"368":2,"369":1,"370":1,"371":2,"372":2,"373":4,"374":3,"375":2,"376":2,"377":1,"379":1,"381":1,"382":2,"392":1,"405":1,"412":1,"415":2,"416":1,"417":2,"420":4,"421":1}}],["been",{"1":{"1":1,"5":1,"6":2,"12":1,"25":1,"53":2,"123":1,"138":1,"189":1,"212":1,"240":1,"344":1,"350":1,"361":1,"379":1,"410":1,"416":1,"420":1}}],["eight",{"1":{"312":1,"417":1}}],["either",{"1":{"4":1,"12":1,"14":1,"110":1,"161":1,"182":1,"221":1,"222":1,"254":1,"278":1,"306":1,"350":2,"353":1}}],["egg",{"1":{"331":3}}],["eg",{"1":{"271":2}}],["ergonomics",{"1":{"255":1}}],["error",{"1":{"147":1,"236":1,"312":1}}],["errors",{"1":{"129":1,"139":1,"253":1}}],["ecosystem",{"1":{"140":1}}],["eyes",{"1":{"138":1}}],["established",{"1":{"236":1}}],["establish",{"1":{"146":2}}],["essentially",{"1":{"340":1,"344":1}}],["essential",{"1":{"134":1,"204":1,"206":2}}],["especially",{"1":{"22":1,"31":1,"128":1,"253":1,"306":1}}],["epub",{"1":{"124":1,"133":1}}],["episode",{"1":{"92":1}}],["effort",{"1":{"133":2,"139":2,"140":1}}],["effectively",{"1":{"236":1,"262":1,"345":2}}],["effective",{"1":{"139":2}}],["effect",{"1":{"91":1,"189":1}}],["efficient",{"1":{"66":1,"111":1,"117":1,"121":1,"135":2,"139":1,"172":1,"174":1,"204":1,"230":1,"231":1,"233":1,"234":1,"237":1,"346":1}}],["efficiently",{"1":{"15":1,"416":1}}],["efficiency",{"1":{"15":1,"77":3,"117":1,"230":1,"236":1,"260":1}}],["eurostyle",{"1":{"102":1}}],["eu",{"1":{"73":1}}],["embark",{"1":{"291":1}}],["embracing",{"1":{"229":1}}],["embodying",{"1":{"75":1}}],["embossing",{"1":{"61":1,"71":1}}],["emboss",{"1":{"61":1,"71":1}}],["embossed",{"0":{"169":1},"1":{"61":5,"71":1,"169":2},"2":{"169":1}}],["emphasizes",{"1":{"230":1,"237":1}}],["empowering",{"1":{"229":1}}],["empty",{"1":{"10":3,"11":1,"172":1}}],["eq",{"1":{"55":3,"58":1}}],["equations",{"1":{"123":1,"197":1,"279":3,"295":3}}],["equally",{"1":{"243":1}}],["equality",{"1":{"49":2}}],["equal",{"1":{"5":1,"30":1,"345":2}}],["equidistance",{"0":{"313":1,"314":1},"1":{"313":1}}],["equivalency",{"1":{"233":2}}],["equivalents",{"1":{"233":1}}],["equivalent",{"1":{"31":1,"181":1,"188":2,"209":1,"233":1,"236":1}}],["equipped",{"1":{"135":1}}],["equipment",{"1":{"74":1}}],["etc",{"1":{"19":1,"84":1,"206":1,"261":1,"421":1}}],["evolves",{"1":{"310":1}}],["ever",{"1":{"262":1}}],["everyone",{"1":{"92":1}}],["every",{"1":{"11":1,"134":1,"187":1,"255":1}}],["eventually",{"1":{"419":1}}],["events",{"1":{"99":1}}],["event",{"1":{"94":1}}],["evenly",{"1":{"61":1}}],["even",{"1":{"28":1,"61":1,"71":1,"137":1,"139":1,"259":2,"261":1,"312":1,"415":2}}],["evaluation",{"1":{"11":1}}],["elongated",{"1":{"345":1}}],["elevated",{"1":{"420":1}}],["elevation",{"1":{"243":4,"246":2},"2":{"246":1}}],["elements",{"1":{"10":1,"206":3,"230":1,"414":1,"420":1},"2":{"206":1}}],["element",{"1":{"9":2,"135":1,"206":1}}],["eliminate",{"1":{"310":1}}],["eliminating",{"1":{"195":1}}],["elif",{"1":{"76":3}}],["elsewhere",{"1":{"299":1}}],["else",{"1":{"67":1,"68":2,"76":4,"243":1,"353":1}}],["elliptic",{"1":{"396":1,"397":1,"400":2}}],["ellipticalstartarc",{"1":{"225":1},"2":{"218":1,"225":1,"306":1,"307":1,"310":1}}],["ellipticalstartarc`",{"1":{"218":1,"306":1,"307":1,"310":1}}],["elliptical",{"1":{"61":1,"80":1,"102":1,"218":4}}],["ellipticalcenterarc`",{"1":{"49":1,"218":1,"306":1,"307":1,"310":1}}],["ellipticalcenterarc",{"1":{"61":2,"80":1,"225":1,"307":1,"395":2,"397":2},"2":{"10":1,"49":1,"61":1,"80":1,"218":1,"225":1,"306":1,"307":1,"310":1,"395":1,"397":1}}],["ellipses",{"1":{"310":1}}],["ellipse`",{"1":{"49":1,"219":1}}],["ellipse",{"1":{"49":1,"61":1,"219":2,"226":1,"241":1,"282":2,"307":1},"2":{"10":1,"49":1,"219":1,"226":1,"282":1}}],["e",{"0":{"328":1},"1":{"9":2,"12":1,"19":1,"23":1,"32":1,"37":1,"75":1,"91":1,"128":1,"135":2,"178":4,"188":1,"198":1,"199":1,"219":1,"222":1,"230":4,"240":1,"241":1,"243":4,"271":2,"352":1,"369":1}}],["edgs",{"1":{"281":2}}],["edge`",{"1":{"49":4,"58":1,"206":1,"238":1,"293":1,"330":1,"402":1,"421":1}}],["edge",{"0":{"145":1,"389":1,"394":1},"1":{"5":2,"49":1,"58":1,"61":4,"80":3,"81":1,"145":1,"177":1,"199":3,"206":9,"208":1,"238":4,"239":1,"241":1,"243":6,"272":2,"276":5,"278":2,"280":3,"289":3,"290":1,"292":1,"296":1,"303":1,"308":3,"311":1,"313":1,"319":1,"320":1,"324":1,"328":1,"331":2,"344":1,"352":1,"389":2,"391":1,"394":1,"395":8,"396":2,"397":3,"398":2,"399":1,"400":4,"401":1,"417":13,"421":1},"2":{"28":1,"49":1,"58":1,"61":1,"206":1,"208":1,"238":1,"239":1,"270":1,"271":1,"289":1,"290":1,"293":1,"330":1,"389":1,"402":1,"417":1,"421":1},"3":{"4":2,"7":2,"10":2,"34":2,"42":2,"49":2,"51":2,"63":2,"65":2,"68":2,"69":2,"70":2,"71":2,"76":2,"78":2,"80":2,"81":2,"124":2,"135":2,"143":2,"144":2,"149":2,"151":2,"163":2,"177":2,"179":2,"182":2,"190":2,"199":2,"218":2,"225":2,"230":2,"232":2,"233":2,"238":2,"239":2,"250":2,"253":2,"256":2,"272":2,"273":2,"278":2,"281":2,"282":2,"284":2,"286":2,"287":2,"289":2,"290":2,"314":2,"336":2,"340":2,"341":2,"344":2,"346":2,"350":2,"389":2,"404":2,"414":2,"417":2}}],["edges``",{"1":{"190":1,"273":3}}],["edges`",{"1":{"49":3,"238":1,"266":1}}],["edges",{"0":{"273":1,"390":1,"391":1},"1":{"4":2,"7":1,"20":2,"26":1,"34":2,"42":2,"46":1,"60":1,"61":1,"62":1,"63":1,"68":2,"69":4,"70":4,"71":2,"74":1,"78":5,"80":17,"81":14,"104":1,"110":5,"112":1,"124":2,"135":1,"143":10,"144":7,"147":1,"151":4,"160":1,"163":2,"170":4,"177":9,"182":4,"190":1,"199":3,"206":6,"230":3,"231":1,"232":1,"233":1,"238":3,"239":1,"241":3,"242":1,"243":4,"245":1,"253":1,"256":6,"266":3,"268":3,"270":4,"271":1,"272":23,"273":10,"274":1,"276":5,"278":3,"279":1,"280":4,"281":1,"282":1,"284":3,"286":1,"287":1,"289":4,"290":1,"292":1,"299":1,"303":3,"319":4,"320":8,"333":1,"344":16,"346":1,"350":1,"389":1,"390":2,"391":3,"392":1,"393":2,"394":2,"395":5,"397":2,"398":1,"400":5,"417":2,"420":7,"421":2},"2":{"4":1,"7":1,"34":1,"42":1,"49":1,"60":1,"62":1,"63":1,"69":1,"70":1,"71":1,"74":1,"78":1,"80":1,"81":1,"124":1,"143":2,"144":1,"151":1,"163":1,"170":1,"177":1,"182":1,"199":1,"230":1,"238":1,"239":1,"241":1,"243":1,"256":1,"266":1,"268":1,"270":1,"271":1,"272":1,"273":2,"276":1,"278":1,"279":1,"280":1,"281":1,"282":1,"284":1,"286":1,"287":1,"289":1,"290":1,"292":1,"319":1,"344":1,"346":1,"350":1,"378":1,"389":1,"390":1,"391":1,"392":1,"393":1,"394":1,"395":1,"400":1,"417":1}}],["ed",{"1":{"176":1}}],["edits",{"1":{"299":1,"310":1}}],["edit",{"1":{"139":1}}],["editable",{"1":{"123":1}}],["editing",{"1":{"104":1}}],["editors",{"0":{"88":1},"1":{"123":2,"255":1}}],["editor>`",{"1":{"86":1}}],["editor",{"0":{"86":1},"1":{"7":1,"51":1,"86":2,"93":1,"178":1}}],["executed",{"1":{"362":1}}],["execution",{"1":{"53":1}}],["examine",{"0":{"335":1,"404":1,"405":1,"406":1}}],["examples>`",{"1":{"73":1}}],["examples",{"0":{"79":1,"178":1,"264":1,"265":1,"266":1,"318":1},"1":{"31":1,"32":1,"48":1,"59":6,"60":2,"61":2,"62":4,"63":2,"64":2,"65":1,"66":1,"67":2,"68":1,"69":1,"70":1,"71":1,"72":1,"73":32,"74":1,"75":1,"76":1,"77":1,"78":1,"80":2,"81":4,"104":1,"126":1,"178":2,"188":1,"222":1,"224":1,"255":1,"264":1,"265":1,"266":1,"318":1,"422":1}}],["example",{"0":{"16":1,"193":1,"230":1,"299":1,"417":1},"1":{"5":1,"11":1,"17":1,"19":1,"23":4,"25":5,"26":5,"28":5,"30":3,"31":4,"32":2,"34":1,"36":1,"37":2,"39":2,"42":1,"51":2,"59":4,"60":1,"62":4,"63":1,"64":3,"66":1,"67":3,"68":1,"69":1,"70":1,"71":1,"72":1,"73":6,"75":1,"76":1,"77":1,"78":2,"80":1,"81":10,"100":1,"108":3,"109":2,"110":1,"118":1,"124":2,"142":1,"143":4,"145":1,"147":1,"151":1,"156":1,"163":1,"167":1,"168":1,"172":2,"174":1,"176":1,"177":1,"179":1,"181":1,"184":1,"189":1,"190":2,"191":1,"192":2,"193":4,"194":1,"195":1,"198":2,"202":4,"208":2,"209":6,"210":1,"211":1,"218":28,"219":13,"220":10,"221":1,"222":3,"224":1,"230":1,"233":1,"238":2,"240":2,"241":2,"244":1,"248":1,"255":1,"256":1,"257":1,"259":1,"262":3,"272":1,"276":3,"278":1,"295":2,"299":3,"307":1,"310":1,"312":1,"313":1,"318":1,"329":1,"331":2,"334":1,"338":1,"341":1,"342":1,"343":1,"345":1,"346":1,"350":1,"353":1,"365":1,"378":1,"381":1,"382":2,"385":2,"388":2,"389":4,"409":1,"414":1,"417":2,"418":1},"2":{"23":1,"202":1,"383":1,"384":1,"390":1,"393":1}}],["exactly",{"1":{"325":1,"354":1,"403":1}}],["exact",{"1":{"298":1,"308":2,"310":1,"409":1}}],["ex9",{"1":{"177":9}}],["ex8",{"1":{"176":6}}],["ex7",{"1":{"175":4}}],["ex6",{"1":{"174":4}}],["ex5",{"1":{"173":4}}],["ex4",{"1":{"172":5}}],["ex36",{"1":{"171":9}}],["ex35",{"1":{"170":15}}],["ex34",{"1":{"169":14},"2":{"169":1}}],["ex33",{"1":{"168":5}}],["ex32",{"1":{"167":8}}],["ex31",{"1":{"166":7}}],["ex30",{"1":{"165":9}}],["ex3",{"1":{"164":4}}],["ex",{"1":{"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":3,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"178":1,"298":2,"299":1,"304":1,"307":2,"314":1,"317":2,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"331":1,"332":2}}],["ex19",{"1":{"152":15}}],["ex18",{"1":{"151":12}}],["ex17",{"1":{"150":9}}],["ex16",{"1":{"149":14}}],["ex15",{"1":{"148":6,"178":6}}],["ex14",{"1":{"147":6},"2":{"147":1}}],["ex13",{"1":{"146":7}}],["ex12",{"1":{"145":5}}],["ex11",{"1":{"144":18}}],["ex10",{"1":{"143":8}}],["ex1",{"1":{"142":3}}],["exchanged",{"1":{"113":1}}],["exchange",{"1":{"112":1,"113":1,"120":2,"123":1}}],["exchanger",{"0":{"69":1},"1":{"68":1,"69":27,"73":3}}],["exchanging",{"1":{"111":1,"123":1}}],["excluded",{"1":{"392":1}}],["exclude",{"1":{"80":1,"179":1,"180":1,"182":1,"183":1,"184":1,"267":1}}],["excluding",{"1":{"80":1}}],["exception",{"1":{"182":1,"197":1,"233":1}}],["except",{"1":{"19":1,"67":1,"70":2,"75":1,"278":1}}],["expanding",{"1":{"276":1}}],["expand",{"1":{"238":1}}],["express",{"1":{"278":1,"310":1}}],["expression",{"1":{"420":1}}],["expressions",{"1":{"240":1}}],["expressive",{"1":{"124":1}}],["expressed",{"1":{"210":1,"295":1,"421":1}}],["explanation",{"1":{"340":1,"345":1}}],["explored",{"1":{"419":1}}],["explore",{"1":{"233":1,"252":1,"277":1,"367":1}}],["exploring",{"1":{"233":1}}],["exploration",{"0":{"277":1},"1":{"139":2}}],["explicitly",{"1":{"36":1,"80":1,"238":1,"333":1,"420":1,"421":1}}],["explicit",{"1":{"36":1,"42":1,"124":1,"295":1,"310":3,"317":1,"318":1,"319":1,"329":2}}],["exposed",{"1":{"331":1}}],["exponentially",{"1":{"236":1}}],["exponent",{"1":{"102":1}}],["exports",{"1":{"123":1,"248":1}}],["exportsvg",{"0":{"115":1},"1":{"67":2,"76":1,"110":1,"115":1,"123":1,"243":1},"2":{"67":1,"76":1,"110":1,"115":1,"243":1}}],["exportdxf",{"0":{"114":1},"1":{"114":1,"123":1},"2":{"114":1}}],["exporters3d",{"1":{"106":1}}],["exporters",{"0":{"106":1},"1":{"108":1,"110":1,"114":1,"115":1,"119":1,"123":2}}],["exporter",{"1":{"76":6,"108":8,"110":6,"243":10}}],["exported",{"1":{"12":1,"119":1,"124":1,"135":1,"369":1}}],["exporting",{"1":{"36":1,"56":1,"118":1,"178":1}}],["export",{"0":{"56":1,"108":1,"118":1},"1":{"19":2,"36":1,"51":1,"67":1,"98":1,"99":2,"106":4,"108":1,"109":1,"118":1,"126":1,"178":2,"245":1,"409":1},"2":{"19":1,"67":1,"106":4,"108":1,"118":1,"178":1,"409":1}}],["experimentation",{"1":{"416":1}}],["experimentslabs",{"1":{"82":1}}],["experience",{"1":{"260":1}}],["experts",{"1":{"201":1}}],["expect",{"1":{"192":1,"195":1,"254":1,"262":2,"412":1}}],["expected",{"0":{"263":1},"1":{"39":1,"98":1,"312":1,"330":1,"404":1}}],["expensive",{"1":{"66":1,"134":1}}],["ex29",{"1":{"163":17}}],["ex28",{"1":{"162":7}}],["ex27",{"1":{"161":11}}],["ex26",{"1":{"160":7}}],["ex25",{"1":{"159":6}}],["ex24",{"1":{"158":9}}],["ex23",{"1":{"157":5}}],["ex22",{"1":{"156":7}}],["ex21",{"1":{"155":5}}],["ex20",{"1":{"154":6}}],["ex2",{"1":{"32":2,"153":4},"2":{"32":1}}],["exists",{"1":{"306":1}}],["existed",{"1":{"272":1}}],["existing",{"1":{"5":1,"20":1,"62":1,"91":1,"134":1,"192":1,"194":1,"199":1,"210":1,"233":2,"303":1,"308":1,"310":1,"329":1,"342":1,"373":1}}],["exiting",{"1":{"51":2}}],["exits",{"1":{"26":1,"190":2}}],["exit",{"1":{"25":1,"181":1,"377":1}}],["ext",{"1":{"67":6}}],["exterior",{"1":{"206":1,"331":4}}],["external",{"0":{"89":1},"1":{"20":1,"36":1,"39":1,"89":1,"126":1,"295":1,"312":1,"350":2}}],["extent",{"0":{"306":1,"307":1},"1":{"306":1,"307":1,"310":1}}],["extensive",{"1":{"233":1}}],["extensibility",{"1":{"124":1}}],["extensible",{"1":{"111":1}}],["extension",{"0":{"98":1},"1":{"67":11,"69":6,"73":1,"81":2,"94":1,"219":1,"243":1}}],["extensionline",{"1":{"226":1,"243":4},"2":{"49":1,"219":1,"226":1,"243":1}}],["extensionline`",{"1":{"49":1,"219":1}}],["extensions",{"0":{"2":1}}],["extends",{"1":{"235":1,"345":1}}],["extend",{"1":{"12":1,"60":1,"71":1,"89":1,"243":5,"280":1,"341":1},"2":{"60":1,"243":1}}],["extending",{"1":{"2":1,"159":1}}],["extreme",{"1":{"290":1,"345":1}}],["extra",{"1":{"183":1}}],["extraction",{"1":{"196":1,"241":5,"270":5,"383":1}}],["extracting",{"1":{"194":1}}],["extracted",{"1":{"42":1,"167":1,"180":1,"378":1}}],["extracts",{"1":{"5":2}}],["extract",{"0":{"383":1,"390":1},"1":{"5":2,"42":1,"61":1,"148":1,"194":1,"204":1,"238":1,"242":1,"272":1,"274":1,"368":1,"383":1,"401":1,"415":1}}],["extrinsic",{"2":{"49":1}}],["extrinsic`",{"1":{"49":1}}],["extruding",{"0":{"377":1},"1":{"61":1,"230":1,"236":1,"341":1,"343":1,"345":1,"388":1,"420":1,"421":1}}],["extrudes",{"1":{"190":1}}],["extruded",{"0":{"164":1},"1":{"66":1,"156":1,"165":1,"166":1,"230":1,"238":1,"250":1,"371":1,"377":1}}],["extrude`",{"1":{"34":1,"38":1,"49":1,"144":2,"164":2,"167":1,"171":1,"238":2,"250":1,"388":1}}],["extrude",{"0":{"171":1},"1":{"4":2,"7":1,"34":3,"42":3,"59":2,"61":1,"63":2,"64":2,"66":2,"67":2,"69":4,"70":13,"71":3,"76":6,"77":1,"80":15,"81":2,"144":3,"145":2,"148":2,"149":2,"150":2,"151":3,"152":4,"154":2,"155":4,"156":2,"159":2,"161":2,"162":2,"163":4,"164":2,"165":2,"166":2,"167":2,"168":2,"169":4,"170":2,"171":4,"172":2,"173":2,"174":2,"175":2,"176":2,"182":5,"190":1,"193":2,"202":1,"224":2,"230":2,"238":3,"239":1,"250":1,"278":2,"279":4,"280":6,"281":4,"283":3,"284":8,"285":1,"286":1,"287":6,"288":3,"289":5,"290":1,"341":3,"345":3,"346":2,"350":2,"368":2,"369":2,"377":2,"388":1,"389":1,"417":12,"420":2},"2":{"4":1,"7":1,"34":1,"38":1,"42":1,"49":1,"59":1,"61":1,"63":1,"64":1,"66":1,"67":1,"69":1,"70":1,"71":1,"76":1,"77":1,"80":1,"81":1,"144":1,"145":1,"148":1,"149":1,"150":1,"151":1,"152":1,"154":1,"155":1,"156":1,"159":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"182":1,"190":1,"193":1,"202":1,"224":1,"230":1,"238":1,"239":1,"250":1,"278":1,"279":1,"280":1,"281":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"341":1,"345":1,"346":1,"350":1,"368":1,"369":1,"377":2,"388":1,"389":1,"417":1,"420":1}}],["extrusions",{"1":{"80":1,"182":1,"334":1,"341":1,"414":1}}],["extrusion",{"0":{"341":1},"1":{"49":1,"164":1,"167":1,"229":1,"235":1,"241":1,"344":1,"345":2,"420":1}}],["environment",{"1":{"349":1,"367":1,"380":1}}],["enforcing",{"1":{"314":1}}],["enforces",{"1":{"308":1,"313":1}}],["enforce",{"1":{"61":1,"302":1,"303":1}}],["engaging",{"1":{"291":1}}],["engines",{"1":{"117":1}}],["engineers",{"1":{"119":1}}],["engineering",{"1":{"112":1,"113":1,"119":1,"120":2,"139":1,"204":1},"2":{"112":1,"120":1}}],["engineer",{"1":{"92":1}}],["enough",{"1":{"255":1,"415":1}}],["enclosing",{"1":{"331":3},"2":{"312":1,"331":2}}],["enclosing``",{"1":{"312":1,"331":2}}],["encloses",{"1":{"331":1,"421":1}}],["enclosed",{"1":{"312":1,"331":1},"2":{"312":1,"331":2}}],["enclosed``",{"1":{"312":1,"331":1}}],["enclose",{"1":{"312":1}}],["encoded",{"1":{"332":1}}],["encompasses",{"1":{"206":1}}],["encourages",{"1":{"231":1,"234":1,"310":1}}],["encourage",{"1":{"61":1}}],["encountered",{"1":{"53":1}}],["encapsulates",{"1":{"204":1,"206":1}}],["entity",{"1":{"206":2}}],["entities",{"1":{"112":1,"204":1,"206":1,"231":1,"236":1,"299":1,"308":1,"310":1,"312":1,"326":1}}],["entirely",{"1":{"194":1,"255":1,"290":1,"345":1}}],["entire",{"1":{"66":1,"120":1,"143":1,"267":1,"340":1,"346":1}}],["entry",{"1":{"94":1,"178":1}}],["entertainment",{"1":{"135":1}}],["enter",{"1":{"53":1}}],["entering",{"1":{"51":1}}],["entered",{"1":{"31":2}}],["enabling",{"1":{"54":1,"111":1,"112":1,"204":1,"206":1,"236":1,"237":1}}],["enable",{"1":{"27":1,"91":1,"120":1,"181":1,"410":1}}],["enables",{"1":{"27":1,"37":1,"117":1,"204":1,"240":1}}],["enabled",{"1":{"7":1}}],["enumerate",{"1":{"65":1,"68":2,"75":1,"76":1,"77":1,"167":2,"168":3,"350":1,"354":1}}],["enum",{"1":{"48":1,"119":1,"192":2,"221":1,"223":1,"241":1}}],["enums",{"0":{"1":1,"44":1},"1":{"44":1,"48":2,"49":32,"54":1,"143":1,"153":1,"159":1,"162":1,"167":1,"169":2,"171":1,"241":2,"271":3,"272":2}}],["enhanced",{"1":{"236":1}}],["enhances",{"1":{"230":1}}],["enhance",{"1":{"26":1,"232":1,"249":1,"291":1}}],["en",{"1":{"20":1,"70":1,"84":1,"87":1,"97":2,"124":2,"128":1,"178":1,"251":1,"255":1,"339":1}}],["ensure",{"1":{"22":1,"30":1,"119":1,"134":2,"139":1,"337":1,"344":1,"345":2,"402":1}}],["ensures",{"1":{"11":1,"108":1,"134":1,"139":1,"179":1,"189":1,"211":1,"230":1,"236":1,"340":1}}],["ensuring",{"1":{"15":2,"18":1,"133":1,"196":1,"236":1,"341":1,"421":1}}],["endpoint",{"1":{"303":3,"304":1,"332":1}}],["endpoints",{"1":{"206":1,"303":3}}],["end1",{"1":{"77":2}}],["end0",{"1":{"77":4}}],["ended",{"1":{"28":1}}],["ends",{"1":{"23":2,"28":1,"30":1,"61":1,"69":1,"77":1,"182":1,"184":2,"306":1}}],["end",{"1":{"5":3,"24":1,"28":2,"30":3,"33":1,"34":1,"38":1,"61":10,"67":1,"69":2,"78":2,"99":1,"124":1,"157":1,"178":2,"179":8,"182":5,"184":2,"189":1,"194":1,"218":1,"219":2,"253":1,"261":1,"278":1,"279":1,"284":1,"295":1,"298":1,"395":2,"397":2},"2":{"30":1,"61":1}}],["earlier",{"1":{"144":1,"151":1,"156":1,"340":2,"422":1}}],["early",{"1":{"134":2}}],["ease",{"1":{"121":1,"236":1,"237":1,"346":1}}],["easier",{"1":{"86":1,"119":1,"133":2,"134":2,"139":1,"141":1,"147":1,"197":1,"256":1,"299":1,"406":1}}],["easily",{"1":{"4":1,"21":1,"51":1,"99":1,"113":1,"123":1,"135":2,"139":2,"141":2,"171":1,"222":1,"240":1,"255":1,"295":1,"336":1,"421":1}}],["east",{"1":{"62":10}}],["easy",{"1":{"26":1,"99":1,"101":1,"133":2,"135":2,"139":2,"140":3,"141":4,"198":1,"230":1}}],["each",{"1":{"3":1,"10":3,"15":2,"17":2,"19":1,"25":1,"47":1,"57":1,"66":2,"75":2,"110":1,"158":1,"168":1,"175":2,"181":2,"182":1,"184":1,"189":1,"191":1,"194":3,"196":1,"200":1,"221":1,"245":1,"246":1,"257":1,"267":1,"268":1,"299":1,"303":2,"304":1,"307":1,"312":1,"318":2,"345":2,"347":1,"352":1,"353":1,"369":1,"398":1,"402":2,"403":2,"421":1}}],["dy",{"1":{"325":1}}],["dynamic",{"1":{"196":1,"230":1,"233":1}}],["dynamically",{"1":{"194":1,"230":1}}],["dx",{"1":{"325":1}}],["dxf",{"0":{"113":1},"1":{"36":1,"105":2,"110":1,"113":3,"119":1,"123":3},"2":{"105":1,"113":1,"123":1}}],["d4",{"1":{"243":3}}],["d3",{"1":{"243":3,"284":2}}],["d2",{"1":{"243":3,"284":2}}],["d1",{"1":{"243":3,"284":10}}],["duplicated",{"1":{"261":1,"402":1}}],["due",{"1":{"113":1,"255":1}}],["during",{"1":{"4":1,"31":1,"122":1,"139":1,"179":1,"183":1,"211":1,"273":1}}],["dl4to>`",{"1":{"87":1}}],["dl4to",{"1":{"87":1}}],["dl4to4ocp",{"0":{"87":1},"1":{"87":1}}],["db2",{"1":{"63":2}}],["d",{"0":{"327":1},"1":{"48":1,"58":4,"67":11,"173":4,"219":1,"224":2,"278":1}}],["drives",{"1":{"101":1}}],["driven",{"1":{"91":1,"124":1,"230":1,"233":1,"310":1}}],["drill",{"3":{"10":1,"11":1,"32":1,"37":1,"49":1,"51":1,"60":1,"61":1,"63":1,"64":1,"65":1,"66":1,"73":1,"76":1,"84":1,"135":1,"143":1,"144":1,"146":1,"153":1,"156":1,"162":1,"179":1,"180":1,"182":1,"192":1,"220":1,"227":1,"240":1,"256":1,"258":1,"265":1,"278":1,"279":1,"280":1,"281":1,"283":1,"287":1,"289":1,"299":1,"336":1,"345":1,"346":1,"350":1,"354":1,"357":1,"359":1,"365":1,"385":1,"387":1,"388":1,"391":1,"414":1,"420":1}}],["dropdown",{"1":{"59":2,"60":1,"61":1,"62":3,"63":1,"64":3,"65":2,"66":1,"67":2,"68":2,"69":2,"70":2,"71":1,"72":2,"74":2,"75":1,"76":1,"77":1,"78":2,"80":1,"81":5,"124":1,"278":2,"279":2,"280":2,"281":2,"282":2,"283":2,"284":2,"285":2,"286":2,"287":2,"288":2,"289":2,"290":2}}],["draft=drafting",{"1":{"243":4}}],["drafted",{"1":{"63":2}}],["draft",{"1":{"63":2,"238":1,"239":1,"243":1},"2":{"49":1,"63":1,"238":1,"239":1,"243":1}}],["draft`",{"1":{"49":1,"238":1}}],["drafting",{"1":{"42":1,"226":5,"243":2}}],["drawn",{"1":{"310":1,"345":1}}],["draw",{"0":{"386":1},"1":{"71":1,"80":1,"151":1,"238":1,"310":1,"368":1,"369":1,"371":2,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1}}],["drawer",{"1":{"68":1}}],["drawings",{"1":{"113":2,"119":6,"139":2,"291":1}}],["drawing",{"0":{"248":1,"299":1,"305":1},"1":{"42":1,"81":1,"110":1,"113":1,"119":1,"123":1,"219":2,"243":5,"245":2,"246":1,"247":2,"248":1,"262":1,"263":1,"291":1,"299":1,"310":1,"334":1,"340":1,"382":1,"422":1}}],["draws",{"1":{"42":1,"340":1,"345":1}}],["darker",{"1":{"262":1}}],["date=date",{"1":{"243":1}}],["datetime",{"1":{"243":1}}],["date",{"1":{"128":1,"133":3,"196":1,"243":1,"278":1}}],["databases",{"1":{"140":1}}],["datasets",{"1":{"135":2}}],["data",{"1":{"34":1,"49":1,"108":2,"111":1,"112":2,"113":1,"120":4,"123":1,"140":3,"141":1,"206":3,"218":1,"399":1},"2":{"108":1}}],["danish",{"1":{"102":1}}],["dashed",{"1":{"30":1,"48":1}}],["domain",{"1":{"255":1}}],["doc",{"1":{"418":1,"420":1}}],["doctest",{"1":{"128":3,"129":5,"130":1,"131":1,"204":2}}],["documenting",{"1":{"134":2}}],["documents",{"1":{"123":1,"139":1}}],["document",{"1":{"123":2,"139":1}}],["documentation",{"0":{"133":1},"1":{"1":1,"90":1,"119":1,"124":1,"133":21,"134":1,"139":1,"233":2},"2":{"119":1}}],["docs",{"1":{"90":1,"91":3,"159":1}}],["dot",{"1":{"76":1,"110":1,"243":1}}],["dodecahedron",{"1":{"75":3},"2":{"75":1}}],["double",{"1":{"75":1,"218":1}}],["doubletangentarc",{"1":{"71":1,"225":1},"2":{"49":1,"71":1,"218":1,"225":1}}],["doubletangentarc`",{"1":{"49":1,"71":1,"218":1}}],["doubly",{"1":{"61":5}}],["doing",{"1":{"20":1,"42":1,"190":1,"415":1}}],["downward",{"1":{"61":1}}],["downloads",{"1":{"124":2}}],["download",{"1":{"59":1,"222":1,"360":1}}],["down",{"1":{"19":1,"53":1,"202":1,"243":1,"246":1,"382":1}}],["do",{"1":{"17":1,"61":1,"134":2,"135":1,"255":1,"267":1,"272":1,"369":1,"394":1,"404":2}}],["don1>`",{"1":{"100":1}}],["done",{"1":{"14":1,"28":1,"128":1,"141":1,"262":1,"263":4,"345":1,"368":1,"373":1,"375":1}}],["don",{"0":{"254":1},"1":{"13":1,"39":1,"61":1,"194":1,"223":1,"257":2,"272":2,"280":1,"369":1}}],["doesn",{"0":{"262":1},"1":{"110":1,"189":1,"192":1,"223":1}}],["does",{"1":{"10":1,"19":1,"28":1,"91":1,"129":1,"179":1,"184":2,"188":2,"189":1,"262":1,"272":1,"281":1,"310":1,"340":1,"345":1,"417":1}}],["dict=true",{"1":{"279":1,"295":1}}],["dive",{"1":{"233":1}}],["divide",{"1":{"49":1,"238":1}}],["digit",{"1":{"218":1}}],["digits=0",{"1":{"59":1}}],["digits=2",{"1":{"59":2}}],["disk",{"1":{"224":2}}],["dissimilar",{"1":{"158":1}}],["disaster",{"1":{"141":1}}],["distinct",{"1":{"192":1,"230":1,"417":3}}],["distributed",{"1":{"141":1,"146":1,"278":2}}],["distribute",{"1":{"138":1,"140":1}}],["dist",{"1":{"124":1,"396":1,"420":1}}],["distances",{"1":{"276":1}}],["distance``",{"1":{"271":1}}],["distance`",{"1":{"266":1}}],["distance|",{"1":{"266":1,"271":1,"275":1}}],["distance",{"0":{"276":1},"1":{"49":1,"75":3,"151":1,"171":1,"219":1,"241":1,"250":1,"264":3,"266":2,"271":2,"276":12,"279":1,"295":1,"310":1,"313":1,"319":1,"320":2,"340":1,"345":1,"354":1,"395":1,"397":1,"419":1,"420":1},"2":{"266":2,"276":1,"319":1,"320":1}}],["discrete",{"1":{"370":1}}],["discarded",{"1":{"189":1}}],["discussed",{"1":{"261":1,"350":1}}],["discusses",{"1":{"92":1}}],["discussion",{"1":{"187":1}}],["discover",{"1":{"233":1}}],["discovered",{"1":{"91":1,"268":1}}],["discord",{"1":{"124":1}}],["disciplines",{"1":{"120":1}}],["dish",{"1":{"71":1}}],["dished",{"1":{"70":2}}],["displacement",{"1":{"62":2}}],["displaying",{"1":{"181":1}}],["displayed",{"1":{"123":1,"181":1,"190":1,"347":1}}],["display",{"1":{"14":1,"39":3,"42":7,"51":1,"68":1,"117":1,"206":1,"243":1,"369":1,"379":1},"2":{"39":1,"42":1}}],["diagnostic",{"1":{"304":1}}],["diagram",{"1":{"55":1,"58":1,"119":1,"221":1,"299":1}}],["diagonal",{"1":{"49":1}}],["dia",{"1":{"32":2,"153":4,"256":2}}],["diamonds",{"1":{"76":7}}],["diamond",{"1":{"76":6},"2":{"76":1}}],["diameter=4",{"1":{"356":2}}],["diameter=1",{"1":{"356":2}}],["diameter=6",{"1":{"179":1}}],["diameter",{"1":{"60":3,"69":30,"71":3,"75":3,"336":1,"345":6,"346":3,"350":21,"352":1,"353":5,"367":3,"368":2,"369":3,"376":2,"377":2},"2":{"75":1,"350":2}}],["diam",{"1":{"11":5}}],["dir",{"1":{"61":1,"155":1,"241":3,"276":2},"2":{"241":3}}],["dir=path",{"1":{"184":1}}],["dir=display",{"1":{"42":1}}],["dir=",{"1":{"42":1,"61":2,"69":2,"72":2,"80":1,"155":2,"289":2,"357":1}}],["dir=l1",{"1":{"25":1}}],["directory",{"1":{"90":1}}],["directly",{"1":{"42":1,"66":1,"104":1,"128":1,"152":2,"188":1,"189":1,"190":1,"215":1,"216":1,"236":1,"243":1,"246":1,"262":1,"276":1,"295":1,"302":1,"310":1,"369":1}}],["directed",{"1":{"32":1,"37":1,"345":1}}],["directions",{"1":{"61":1,"80":1,"303":1},"2":{"61":1}}],["direction=vector",{"1":{"278":1}}],["direction=d",{"1":{"278":1}}],["direction=l1",{"1":{"317":1}}],["direction=l6",{"1":{"74":2}}],["direction=l4",{"1":{"74":2}}],["direction=l2",{"1":{"74":2}}],["direction=",{"1":{"34":1,"78":2,"124":1,"243":1,"290":1,"299":1,"325":1}}],["direction",{"1":{"9":1,"34":3,"39":1,"49":2,"52":2,"61":1,"80":1,"144":3,"147":1,"149":1,"150":1,"152":1,"154":1,"156":1,"182":2,"184":1,"204":1,"218":2,"241":4,"243":1,"245":1,"267":2,"303":1,"306":1,"307":1,"308":1,"317":1,"331":2,"332":1,"354":1},"2":{"149":1,"316":1,"325":1}}],["direct",{"0":{"54":1,"212":1},"1":{"3":1,"54":2,"126":1,"191":1,"212":1,"214":1,"292":1,"299":1,"332":1,"421":1}}],["differ",{"1":{"135":1,"229":1}}],["difference",{"1":{"198":1,"230":1,"261":1},"2":{"230":1}}],["differences",{"1":{"48":1,"234":2}}],["different",{"1":{"19":2,"37":1,"48":1,"51":1,"110":1,"112":1,"113":1,"120":1,"123":1,"133":2,"138":2,"139":5,"140":1,"141":3,"143":1,"152":1,"159":1,"182":1,"231":1,"252":1,"307":1,"310":1,"348":1,"395":1,"396":1,"399":2}}],["difficult",{"1":{"4":1,"26":1,"99":1,"147":1,"236":1,"258":1,"310":1}}],["dimensionline",{"1":{"226":1},"2":{"49":1,"219":1,"226":1}}],["dimensionline`",{"1":{"49":1,"219":1}}],["dimension",{"1":{"36":1,"76":2,"110":2,"177":1,"219":1,"243":1,"334":1}}],["dimensions",{"0":{"397":1},"1":{"36":1,"75":1,"147":1,"230":1,"233":1,"236":1,"243":1,"245":1,"249":1,"258":2,"278":1,"295":1,"310":1,"336":2,"367":1,"372":1,"396":1,"412":1}}],["dimensional",{"1":{"24":1,"33":1,"36":1,"38":1,"75":1,"77":1,"201":1,"229":1,"231":1,"234":1,"237":1,"310":1,"370":1,"371":2,"377":1}}],["dim",{"1":{"10":6,"67":6},"2":{"10":1}}],["din",{"1":{"6":1,"240":2}}],["densc",{"1":{"281":1,"282":2,"283":1,"284":1,"285":2,"286":1,"287":1,"288":1,"289":1,"290":2}}],["densb",{"1":{"281":1,"282":1,"283":2,"284":1,"285":1,"286":1,"287":2,"288":1,"289":2,"290":1}}],["density",{"1":{"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["densa",{"1":{"281":2,"282":1,"283":1,"284":2,"285":1,"286":2,"287":1,"288":2,"289":1,"290":1}}],["derive",{"1":{"310":1}}],["derived",{"1":{"57":1}}],["derivatives",{"1":{"303":2}}],["derivative",{"1":{"303":1}}],["deriving",{"1":{"258":1}}],["dealing",{"1":{"236":1}}],["deals",{"1":{"206":1}}],["deboss",{"1":{"169":2},"2":{"169":1}}],["debossed",{"0":{"169":1}}],["debugability",{"1":{"299":1}}],["debugger",{"0":{"53":1},"1":{"53":2}}],["debugging",{"0":{"50":1},"1":{"0":1,"50":1,"52":1,"53":1,"141":1,"192":1}}],["debug",{"1":{"50":1,"53":1,"236":1}}],["deliberately",{"1":{"415":1}}],["delivery",{"1":{"134":2},"2":{"134":1}}],["delay",{"0":{"253":1}}],["deleted",{"1":{"160":1}}],["delta=",{"1":{"72":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["delta",{"1":{"72":2,"230":7,"278":2,"279":2,"280":2,"281":2,"282":2,"283":2,"284":2,"285":2,"286":2,"287":2,"288":2,"289":2,"290":2}}],["departs",{"1":{"303":1,"304":1}}],["depend",{"1":{"409":1}}],["depends",{"1":{"244":1,"299":1}}],["depending",{"1":{"124":1,"194":1,"254":1,"312":1,"369":1}}],["dependencies",{"0":{"244":1},"1":{"95":1,"129":1}}],["deploying",{"1":{"117":1}}],["deployment",{"1":{"104":1}}],["depths",{"1":{"220":1}}],["depth=4",{"1":{"289":1}}],["depth=width",{"1":{"162":1}}],["depth=10",{"1":{"146":2}}],["depth=b",{"1":{"146":2}}],["depth=thickness",{"1":{"143":1,"144":1}}],["depth",{"1":{"71":1,"77":6,"220":2,"246":1,"345":1,"367":1,"368":2,"369":2,"375":2,"376":2,"377":2},"2":{"20":1,"77":1,"143":1}}],["demand",{"1":{"84":1}}],["demonstrate",{"1":{"272":1}}],["demonstrated",{"1":{"61":1,"124":1,"230":1}}],["demonstrates",{"1":{"60":1,"62":1,"63":1,"64":1,"66":1,"68":1,"70":1,"72":1,"77":1,"78":1,"80":1,"81":1,"248":1}}],["demo",{"1":{"16":3}}],["decorators",{"1":{"90":1,"91":2}}],["deck",{"1":{"76":3}}],["decimal",{"1":{"49":1,"243":1}}],["decide",{"1":{"34":1,"404":1}}],["deciding",{"1":{"34":1}}],["dev``",{"1":{"129":1}}],["developer",{"1":{"255":1}}],["developers",{"1":{"123":1,"134":2,"138":4,"140":6,"141":8}}],["developed",{"1":{"111":1,"113":1,"117":1,"138":1}}],["development",{"0":{"128":1},"1":{"120":1,"128":3,"134":2,"139":1,"140":1,"141":2}}],["devices",{"1":{"111":1,"117":1}}],["dev",{"1":{"70":1,"85":1,"104":1,"129":1}}],["de",{"1":{"70":1}}],["degree",{"1":{"27":1,"181":1,"279":3,"295":3,"347":1}}],["degrees",{"1":{"9":1,"61":1,"201":1,"217":1,"279":2,"290":6,"310":1,"317":1,"352":1}}],["deflection=1",{"1":{"276":1}}],["deflection=0",{"1":{"276":1}}],["deformations",{"1":{"206":1}}],["def",{"1":{"62":4,"67":1,"75":1,"76":5,"77":2,"168":2,"199":1,"208":2,"222":1,"243":1,"350":1}}],["defaults",{"1":{"75":3,"77":7,"243":1,"254":1,"350":1}}],["default",{"1":{"23":1,"31":1,"32":1,"37":1,"66":2,"80":1,"110":1,"129":1,"166":1,"192":2,"201":2,"202":2,"257":1,"262":1,"263":1,"272":3,"310":1,"331":1,"339":1,"363":1},"2":{"66":1}}],["definitely",{"1":{"255":1}}],["definition`",{"1":{"187":1}}],["definitions",{"1":{"9":1,"10":1,"111":1}}],["definition",{"0":{"8":1},"1":{"0":1,"10":2,"75":1,"139":1,"187":1,"199":1}}],["defining",{"0":{"145":1},"1":{"40":1,"61":1,"74":1,"206":3,"230":1,"235":1,"343":1,"421":1}}],["defines",{"1":{"59":1,"65":1,"110":2,"119":1,"145":1,"184":1,"188":1,"206":4,"331":1,"340":1,"353":1,"420":2}}],["define",{"1":{"25":1,"60":1,"61":5,"74":1,"77":2,"80":2,"119":1,"123":1,"135":1,"202":1,"210":2,"211":1,"218":2,"243":1,"245":1,"279":1,"295":1,"310":1,"339":1,"344":1,"353":1,"374":1,"396":1,"398":1,"420":4,"421":1}}],["defined",{"1":{"10":1,"36":1,"40":1,"51":1,"55":2,"56":1,"57":1,"58":2,"61":1,"69":1,"71":1,"110":1,"118":1,"119":1,"124":1,"152":1,"179":1,"183":1,"192":1,"206":1,"211":2,"218":21,"219":13,"220":10,"224":1,"235":1,"241":1,"290":1,"299":1,"310":1,"312":1,"336":1,"340":1,"345":2,"361":1,"374":2,"420":2,"421":1}}],["deepcopy",{"1":{"19":2,"55":6,"58":1},"2":{"19":1}}],["deep",{"0":{"19":1},"1":{"124":1}}],["deterministic",{"1":{"310":1,"312":1,"315":1,"329":1}}],["deterministically",{"1":{"310":1,"331":1}}],["determined",{"1":{"184":1,"201":1,"238":1,"310":1,"339":1}}],["determines",{"1":{"28":1,"195":1}}],["determine",{"1":{"15":1,"21":1,"34":1,"42":1,"59":2,"78":2,"124":1,"306":1,"368":1}}],["detectors",{"1":{"410":1}}],["detector",{"1":{"404":1}}],["detection",{"1":{"135":1}}],["detecting",{"1":{"134":1}}],["detect",{"1":{"122":3,"134":2,"408":1,"410":1,"413":1,"415":2},"2":{"122":1,"408":1,"409":1,"410":1,"411":1,"413":1,"415":1,"417":1}}],["detents",{"1":{"71":3}}],["detail",{"1":{"92":1,"181":1,"183":1,"350":1}}],["details",{"1":{"73":1,"81":1,"140":1,"188":1,"232":1,"343":1}}],["detailed",{"0":{"15":1},"1":{"65":1,"80":1,"112":1,"117":1,"139":1,"345":1}}],["detached",{"1":{"20":1}}],["desired",{"1":{"201":1,"232":1,"252":1,"319":1}}],["designing",{"0":{"334":1},"1":{"42":1,"233":1,"257":1,"291":1,"334":1}}],["designers",{"1":{"119":1,"123":1,"250":2,"252":1,"260":1}}],["designer",{"1":{"27":1,"31":1,"42":2,"48":1,"413":1}}],["designed",{"1":{"18":1,"117":1,"124":1,"234":1,"243":1,"415":1}}],["design",{"0":{"235":1,"345":1,"415":1},"1":{"15":1,"26":1,"27":2,"28":1,"30":2,"42":1,"50":1,"65":1,"70":1,"80":1,"98":1,"102":1,"111":1,"112":1,"113":1,"119":1,"120":1,"121":1,"123":1,"124":1,"133":1,"134":2,"135":1,"139":7,"141":2,"178":2,"222":1,"229":1,"230":2,"231":1,"232":1,"233":1,"234":1,"235":2,"236":2,"243":1,"252":1,"253":5,"256":1,"258":1,"261":2,"295":1,"306":1,"310":2,"313":1,"334":1,"335":2,"336":2,"337":1,"339":1,"340":1,"341":2,"346":1,"382":1,"408":1,"413":1,"414":1,"415":1,"417":1,"422":1},"2":{"112":1,"113":1,"119":1,"120":1,"121":1}}],["designs",{"1":{"12":1,"27":1,"30":1,"94":1,"97":2,"113":1,"139":1,"230":1,"233":1,"236":2,"237":1}}],["desc",{"1":{"278":1}}],["describing",{"1":{"123":1}}],["describes",{"1":{"181":1,"192":1,"241":1,"303":1,"353":1,"415":1}}],["described",{"1":{"55":1,"110":2,"144":1,"206":1,"218":1,"241":1,"252":1,"263":1,"278":1,"299":1,"350":1,"382":1,"387":1,"389":1,"408":1,"420":1}}],["describe",{"1":{"27":1,"47":1,"50":1,"89":1,"121":1,"137":1,"224":1,"352":1,"354":1,"368":1,"385":1}}],["descriptions",{"1":{"219":1}}],["description",{"0":{"15":1},"1":{"49":5,"57":1,"238":2,"241":4,"260":1,"270":1,"271":1}}],["descendants",{"2":{"20":1}}],["pnt",{"1":{"323":1,"327":1,"395":4,"398":4,"420":2}}],["png",{"1":{"34":1,"53":1,"59":3,"60":1,"61":1,"62":3,"63":1,"64":2,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":21,"74":1,"75":1,"76":1,"77":1,"78":1,"80":1,"81":1,"124":1,"179":1,"182":3,"184":1,"208":2,"209":5,"225":1,"230":1,"240":1,"262":2,"264":4,"265":3,"266":6,"267":1,"268":1,"272":5,"273":2,"275":1,"276":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"291":14,"299":2,"335":1,"339":1,"340":1,"346":1,"396":1,"401":1,"420":5}}],["ppp0110",{"1":{"289":1,"290":4,"291":2}}],["ppp0109",{"1":{"288":1,"289":1,"291":2}}],["ppp0108",{"1":{"287":1,"288":1,"291":2}}],["ppp0107",{"1":{"286":1,"287":1,"291":2}}],["ppp0106",{"1":{"285":1,"286":1,"291":2}}],["ppp0105",{"1":{"284":1,"285":1,"291":2}}],["ppp0104",{"1":{"283":1,"284":1,"291":2}}],["ppp0103",{"1":{"282":1,"283":4,"291":2}}],["ppp0102",{"1":{"281":1,"282":2,"291":2}}],["ppp0101",{"1":{"281":1,"291":3}}],["ppp109",{"1":{"289":7}}],["p2",{"1":{"288":1}}],["phase",{"1":{"253":1}}],["physical",{"1":{"181":1}}],["philosophies",{"1":{"234":1}}],["philosophy",{"1":{"231":1,"235":1}}],["philosopher",{"1":{"75":1}}],["phi",{"1":{"75":10}}],["pts",{"1":{"145":4,"157":4,"165":6,"176":4,"218":1,"282":2},"2":{"165":1}}],["pdf",{"1":{"124":1,"133":1}}],["pdm",{"1":{"98":1}}],["pg",{"1":{"104":2}}],["pln2",{"1":{"287":2}}],["pln",{"1":{"156":2,"284":3,"287":8}}],["please",{"1":{"128":1,"129":1,"147":1}}],["plm",{"1":{"98":1}}],["play",{"1":{"206":1}}],["playground",{"1":{"104":1}}],["playingcard",{"1":{"76":26},"2":{"76":1}}],["playing",{"0":{"76":1},"1":{"73":3,"75":1,"76":5,"222":3}}],["plastic",{"1":{"84":1}}],["platforms",{"1":{"113":1,"117":1,"138":1,"140":1}}],["platform",{"1":{"99":1,"121":1,"140":1}}],["plato",{"1":{"75":1}}],["platonicsolid",{"1":{"75":4},"2":{"75":1}}],["platonic",{"0":{"75":1},"1":{"73":3,"74":1,"75":15}}],["plate",{"0":{"142":1,"153":1,"288":1},"1":{"69":10,"77":10,"256":4,"286":1,"288":1,"291":1}}],["plates",{"1":{"22":1,"69":1,"77":3,"102":1}}],["places",{"1":{"144":1,"156":1,"173":1,"245":1,"410":1}}],["placed",{"1":{"51":1,"61":1,"169":2,"189":1,"257":1,"262":2,"339":1,"344":1,"345":1,"373":1}}],["placements",{"1":{"414":1}}],["placement",{"0":{"188":1},"1":{"42":1,"61":1,"147":1,"169":2,"185":1,"186":1,"188":4,"189":1,"201":1,"210":1,"214":1,"406":1}}],["place",{"0":{"382":1},"1":{"15":1,"21":1,"42":1,"64":1,"144":1,"173":1,"184":1,"245":1,"257":1,"339":1,"365":1,"399":1}}],["placing",{"1":{"9":2,"52":1,"64":1,"169":2}}],["plant",{"1":{"331":3}}],["planar",{"1":{"38":1,"60":2,"61":6,"62":27,"66":1,"78":1,"144":1,"171":1,"235":1,"253":1,"315":1,"382":2,"396":1,"401":1,"404":1,"406":1,"410":2,"411":1,"419":1,"420":6,"421":2}}],["plane=plane",{"1":{"52":1}}],["plane=",{"1":{"52":1}}],["plane`",{"1":{"49":5,"150":1,"204":1,"241":1,"306":1}}],["plane",{"0":{"144":1,"208":1,"209":1,"257":1,"262":1},"1":{"9":3,"15":2,"22":1,"23":1,"25":3,"31":4,"34":3,"37":1,"39":3,"42":5,"49":2,"51":1,"52":3,"55":1,"59":9,"60":1,"61":2,"62":9,"63":1,"67":3,"69":5,"70":2,"71":3,"72":6,"74":6,"78":5,"80":9,"81":3,"108":1,"110":1,"124":3,"144":8,"146":6,"147":2,"148":1,"149":9,"150":1,"151":1,"154":7,"155":5,"156":6,"157":2,"158":4,"159":4,"161":3,"162":1,"163":2,"169":4,"170":3,"176":3,"179":1,"182":2,"184":1,"185":2,"188":25,"193":1,"198":2,"202":5,"208":12,"209":8,"210":1,"238":2,"241":6,"262":5,"263":2,"266":2,"278":4,"279":1,"280":6,"281":2,"282":4,"283":3,"284":4,"285":2,"287":5,"288":1,"289":2,"290":2,"308":1,"310":1,"339":1,"340":1,"341":1,"357":1,"395":2,"399":2,"406":2,"409":2,"414":1,"417":19,"420":5,"421":1},"2":{"9":1,"25":1,"31":1,"39":1,"42":1,"49":1,"51":1,"52":1,"55":1,"59":1,"62":1,"67":1,"69":1,"70":1,"72":1,"74":1,"81":1,"144":2,"146":1,"150":1,"151":1,"154":2,"155":1,"156":2,"158":1,"161":1,"162":1,"163":1,"169":1,"170":1,"184":1,"188":1,"193":1,"201":1,"204":1,"208":1,"209":1,"210":1,"241":1,"262":1,"271":1,"287":1,"289":1,"306":1,"340":1,"357":1,"406":1}}],["planes`",{"1":{"262":1}}],["planes",{"0":{"9":1,"31":1,"42":1},"1":{"9":1,"25":1,"31":2,"34":1,"37":1,"42":1,"61":1,"104":1,"122":1,"149":2,"210":1,"335":1,"339":3,"398":1,"404":1,"405":1,"408":2,"409":1,"410":1,"411":1,"413":1,"414":2,"415":2,"417":2}}],["plan",{"0":{"336":1},"1":{"3":1,"7":2,"63":1,"69":4,"70":4,"76":9,"80":2,"190":2,"243":2,"246":1,"279":1,"368":1,"369":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1},"2":{"246":1,"371":1}}],["pulls",{"1":{"299":1}}],["put",{"1":{"202":1,"420":2}}],["putting",{"1":{"77":1,"184":1}}],["push",{"1":{"141":1,"190":1,"376":1,"415":1}}],["pushing",{"1":{"51":3,"201":1}}],["purpose",{"1":{"140":1,"310":1}}],["public",{"0":{"100":1},"1":{"138":1}}],["published",{"1":{"100":1}}],["publish",{"1":{"97":1}}],["p1",{"1":{"67":2,"307":1}}],["pcb",{"1":{"64":14}}],["ped",{"1":{"284":2}}],["people",{"1":{"255":1}}],["pep",{"1":{"124":1}}],["pep8",{"1":{"54":1}}],["pentagons",{"1":{"144":1}}],["pentagonal",{"1":{"75":1}}],["pending",{"0":{"190":1},"1":{"25":2,"34":1,"68":5,"147":3,"158":1,"172":1,"190":7},"2":{"190":1}}],["pegd",{"1":{"74":6}}],["pegboard",{"1":{"74":1}}],["peg",{"0":{"74":1},"1":{"72":1,"73":3,"74":1}}],["perceived",{"1":{"303":1}}],["permissions",{"1":{"278":1}}],["perspective",{"1":{"246":1}}],["perpendicular",{"0":{"317":1},"1":{"155":1,"310":1,"317":3}}],["per",{"1":{"104":1}}],["perimeter",{"0":{"372":1,"389":1},"1":{"37":1,"42":1,"66":5,"80":2,"243":1,"299":4,"314":1,"331":1,"368":2,"369":2,"371":1,"372":1,"373":2,"374":2,"375":2,"376":2,"377":2,"389":1,"392":1,"393":1,"394":1,"419":1,"420":8},"2":{"372":1,"373":1}}],["perform",{"1":{"22":1,"87":1,"135":1,"139":1,"141":1,"143":2,"253":1}}],["performance`",{"1":{"172":1,"174":1,"187":1}}],["performance",{"0":{"11":1},"1":{"0":1,"187":1,"261":1}}],["perfectly",{"1":{"22":1}}],["pypa",{"1":{"128":1}}],["pylance",{"1":{"124":1}}],["pylint",{"1":{"124":1}}],["py>`",{"1":{"102":1,"222":1}}],["pyqt",{"1":{"86":1}}],["py",{"0":{"101":1},"1":{"18":1,"29":1,"35":1,"41":1,"44":1,"55":1,"56":1,"57":1,"58":1,"101":1,"104":1,"105":2,"106":1,"181":1,"222":1,"225":1,"226":1,"227":1,"278":1}}],["python3",{"1":{"128":3,"129":2},"2":{"128":1}}],["pythonic",{"1":{"124":1}}],["python",{"0":{"7":1,"53":1,"140":1,"167":1,"168":1},"1":{"3":1,"6":2,"7":5,"16":3,"17":1,"19":1,"20":1,"21":1,"24":1,"33":1,"36":1,"38":1,"49":1,"50":1,"51":4,"53":3,"65":1,"90":1,"91":1,"97":1,"124":3,"129":2,"131":1,"140":9,"167":1,"168":1,"180":1,"185":1,"189":4,"224":1,"238":1,"241":2,"250":1,"251":1,"347":3,"367":1,"383":1,"393":1},"2":{"128":1}}],["p=",{"1":{"14":11,"51":5,"198":8,"204":1}}],["p0",{"2":{"10":1}}],["p`",{"1":{"9":3}}],["p",{"1":{"9":9,"61":4,"162":2,"280":5,"281":4,"282":4,"284":6,"285":4,"286":4,"287":5,"288":3,"290":8},"2":{"10":1}}],["pivot",{"1":{"353":1}}],["pivots",{"1":{"353":1}}],["pixels=",{"1":{"299":1}}],["pixel",{"1":{"256":1}}],["pitch",{"1":{"218":1,"354":1}}],["pitch=1",{"1":{"179":1}}],["piece",{"1":{"189":1,"200":1,"230":1,"255":1}}],["piet",{"1":{"102":1}}],["pin",{"1":{"179":1,"181":1,"350":15,"352":1,"356":2},"2":{"350":1}}],["pips",{"0":{"369":1},"1":{"367":1,"369":3,"376":1}}],["pip",{"1":{"128":6,"129":6,"130":1,"367":5,"368":1,"369":2,"374":1,"375":1,"376":1,"377":1},"2":{"367":1,"374":1}}],["pipeline",{"1":{"134":1}}],["pipe",{"1":{"4":2,"84":1,"184":14}}],["pipesection",{"1":{"184":2},"2":{"184":1}}],["pipes",{"1":{"4":2,"84":1,"199":2,"201":2},"2":{"199":1}}],["picture",{"1":{"80":1}}],["pi",{"1":{"62":4,"72":4,"290":3}}],["pillow",{"1":{"7":2,"190":2},"2":{"190":1}}],["poor",{"0":{"412":1}}],["potential",{"1":{"229":1,"233":1,"253":1}}],["potentially",{"1":{"217":1}}],["port",{"1":{"110":2}}],["ports",{"1":{"95":1}}],["poetry",{"1":{"129":6}}],["poet",{"1":{"102":1}}],["pod",{"1":{"92":1}}],["podcast",{"1":{"92":2}}],["popularly",{"1":{"140":1}}],["popular",{"1":{"123":1,"124":1,"140":1}}],["popularity",{"1":{"113":1,"121":1}}],["popularized",{"1":{"102":1}}],["populated",{"1":{"66":1}}],["popping",{"1":{"51":3}}],["power",{"1":{"334":1}}],["powerful",{"1":{"53":1,"147":1,"158":1,"200":1,"233":1,"236":1,"237":1,"258":1,"277":1,"403":1}}],["pow",{"1":{"55":1}}],["pointing",{"1":{"152":1}}],["pointed",{"1":{"110":1}}],["pointarctangentline",{"1":{"225":1},"2":{"49":1,"218":1,"225":1}}],["pointarctangentline`",{"1":{"49":1,"218":1}}],["pointarctangentarc",{"1":{"225":1},"2":{"49":1,"218":1,"225":1}}],["pointarctangentarc`",{"1":{"49":1,"218":1}}],["point",{"0":{"173":1,"174":1,"323":1},"1":{"28":4,"30":2,"53":1,"61":2,"135":1,"147":1,"175":1,"202":1,"206":1,"218":7,"219":1,"262":1,"276":1,"279":1,"290":1,"293":1,"295":1,"306":1,"307":1,"308":1,"316":1,"320":1,"323":1,"329":2,"339":2,"347":1,"388":1,"409":1,"419":1,"420":5},"2":{"290":1}}],["points`",{"1":{"420":1,"421":1}}],["points",{"1":{"5":1,"28":1,"31":1,"34":2,"51":4,"61":1,"62":2,"77":1,"78":4,"124":2,"144":2,"145":1,"146":1,"152":1,"156":1,"174":1,"176":1,"198":1,"201":2,"218":9,"219":2,"220":1,"238":1,"262":1,"279":1,"290":1,"295":1,"303":2,"310":1,"340":1,"345":1,"374":1},"2":{"34":1,"62":1,"78":1,"124":1,"201":1,"420":1,"421":1},"3":{"5":1,"10":1,"25":1,"34":1,"49":1,"61":1,"62":1,"68":1,"78":1,"81":1,"124":1,"145":1,"218":1,"225":1,"241":1,"304":1,"310":1}}],["pollute",{"1":{"255":1}}],["polar",{"1":{"218":1}}],["polarlocations",{"0":{"146":1},"1":{"45":1,"65":6,"71":1,"76":1,"146":4,"166":2,"167":2,"168":2,"287":2},"2":{"40":1,"49":1,"65":1,"71":1,"76":1,"146":1,"166":1,"167":1,"168":1,"198":1,"211":1,"287":1}}],["polarlocations`",{"1":{"40":1,"49":1,"65":1,"146":1,"166":1,"211":1}}],["polarline`",{"1":{"49":1,"218":1,"306":1,"307":1,"310":1}}],["polarline",{"1":{"74":6,"225":1,"278":2,"281":1,"282":1,"290":1,"299":2,"307":2,"317":1},"2":{"10":1,"49":1,"74":1,"218":1,"225":1,"278":1,"281":1,"282":1,"290":1,"299":1,"306":1,"307":1,"310":1,"317":1}}],["poly",{"1":{"59":5}}],["polyhedron",{"1":{"32":1,"75":1,"220":2}}],["polygon`",{"1":{"49":1,"219":1}}],["polygons",{"0":{"175":1},"1":{"11":1,"75":2,"144":2,"175":2}}],["polygon",{"1":{"59":1,"75":1,"219":3,"226":1,"282":1},"2":{"10":1,"49":1,"59":1,"75":1,"219":1,"226":1,"282":1}}],["polylines",{"0":{"176":1},"1":{"299":1,"340":1}}],["polyline`",{"1":{"49":1,"157":1,"165":1,"176":1,"218":1}}],["polyline",{"1":{"5":2,"34":1,"42":1,"62":12,"71":1,"78":2,"81":2,"124":1,"157":2,"165":2,"176":3,"218":2,"225":1,"263":1,"278":1,"279":1,"280":1,"288":1,"289":1,"299":2,"340":4},"2":{"5":1,"10":1,"34":1,"42":1,"49":1,"62":1,"71":1,"78":1,"81":1,"124":1,"157":1,"165":1,"176":1,"218":1,"225":1,"263":1,"278":1,"279":1,"280":1,"288":1,"289":1,"299":1}}],["possibilities",{"1":{"233":1}}],["possible",{"1":{"2":1,"39":1,"48":1,"54":1,"142":1,"147":1,"156":1,"251":1,"261":1,"334":2,"336":1,"378":1,"402":1,"420":1}}],["post",{"0":{"282":1},"1":{"156":1,"282":1,"291":1,"292":1}}],["poster=",{"1":{"124":1,"396":1,"420":1}}],["pos``",{"1":{"406":1}}],["pos`",{"1":{"152":1,"173":1,"210":1}}],["positive",{"1":{"110":1,"144":1,"149":1,"156":1,"290":2,"354":1,"365":1}}],["position|",{"1":{"266":1,"267":1,"271":1}}],["position=12",{"1":{"182":1}}],["position=5",{"1":{"180":1,"365":1}}],["positioning",{"0":{"209":1},"1":{"155":1,"198":1,"208":2}}],["positionmode",{"2":{"49":1}}],["positionmode`",{"1":{"49":1}}],["position`",{"1":{"49":1,"266":1}}],["positional",{"1":{"27":1,"303":1,"312":1,"320":1}}],["positioned",{"1":{"22":1,"40":1,"61":1,"202":1,"209":1,"211":1,"224":2,"262":1,"369":1,"376":1}}],["positions",{"1":{"15":2,"64":2,"65":1,"69":1,"152":2,"184":1,"198":2,"201":1,"202":1,"310":1,"344":2,"368":1,"374":4}}],["position",{"0":{"147":1,"208":1,"216":1},"1":{"5":2,"11":4,"28":2,"42":1,"49":2,"57":1,"59":2,"61":2,"62":2,"65":1,"69":2,"70":4,"77":3,"80":1,"81":4,"147":2,"152":2,"154":1,"173":1,"177":1,"180":1,"181":1,"182":5,"183":1,"184":5,"201":2,"202":2,"204":7,"206":1,"209":3,"210":3,"211":1,"216":7,"217":1,"238":1,"241":2,"243":3,"246":1,"262":1,"275":1,"289":1,"303":2,"304":1,"308":1,"312":1,"339":1,"345":1,"352":1,"354":3,"358":1,"359":1,"364":1,"365":2,"368":1,"369":1,"376":1,"384":2},"2":{"28":1,"42":1,"49":2,"59":1,"61":1,"70":1,"81":1,"147":1,"180":1,"182":1,"204":1,"241":1,"266":1,"289":1}}],["pos",{"1":{"55":1,"60":2,"61":1,"64":2,"67":5,"70":1,"75":1,"76":7,"77":2,"78":1,"124":1,"152":2,"157":1,"171":1,"173":2,"185":1,"188":6,"209":6,"210":1,"224":2,"243":3,"278":1,"395":1,"399":1,"417":26,"420":3},"2":{"55":1,"60":1,"61":1,"64":1,"67":1,"70":1,"75":1,"76":1,"77":1,"78":1,"124":1,"152":1,"157":1,"171":1,"173":1,"185":1,"188":1,"209":1,"210":1,"224":1,"243":1,"278":1,"395":1,"399":1,"417":1,"420":1}}],["paste",{"0":{"285":1},"1":{"285":1,"291":1}}],["passing",{"1":{"316":1,"329":1}}],["passed",{"1":{"34":1,"39":1,"42":3,"66":1,"152":3,"257":1}}],["pass",{"1":{"34":1,"98":1,"177":1}}],["pair",{"1":{"218":1,"374":1}}],["pairs",{"1":{"181":1}}],["paper",{"0":{"189":1},"1":{"189":1,"200":1,"243":1}}],["pandas",{"1":{"140":1}}],["payment",{"1":{"138":2}}],["page",{"1":{"133":1,"178":1,"243":14,"245":1,"246":1},"2":{"243":1}}],["pagesize",{"2":{"49":1}}],["pagesize`",{"1":{"49":1}}],["packaged",{"1":{"98":1,"100":1}}],["packages>`",{"1":{"97":1}}],["packages",{"1":{"90":1,"98":1,"235":1,"244":1}}],["package",{"1":{"20":1,"91":1,"97":1,"98":1,"100":1,"202":1,"258":1},"2":{"91":1}}],["pack`",{"1":{"18":1,"257":2}}],["packed",{"1":{"16":2,"257":3}}],["pack",{"0":{"18":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1},"1":{"16":9,"18":2,"20":1,"21":2,"281":1,"282":2,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"291":10},"2":{"15":1,"16":1,"18":1,"108":1,"257":1}}],["pack2d",{"2":{"15":1}}],["pack2d``",{"1":{"15":1}}],["packing",{"0":{"257":1},"1":{"15":1,"257":1}}],["padding=5",{"1":{"16":2}}],["padding",{"1":{"15":1,"257":2},"2":{"257":1}}],["parent``",{"1":{"276":1}}],["parents",{"1":{"254":1}}],["parent",{"1":{"14":1,"20":5,"51":1,"144":2,"190":1,"254":1,"358":1,"361":1},"2":{"12":1,"14":1,"20":1,"276":1}}],["paradigms",{"1":{"230":1}}],["paradigm",{"0":{"200":1},"1":{"196":1,"200":1,"230":1,"231":1}}],["parallel",{"1":{"158":1,"241":1,"310":1,"313":1,"340":1}}],["parabolic",{"1":{"218":2}}],["paraboliccenterarc`",{"1":{"49":1,"218":1,"306":1,"307":1,"310":1}}],["paraboliccenterarc",{"1":{"225":1,"307":1},"2":{"10":1,"49":1,"218":1,"225":1,"306":1,"307":1,"310":1}}],["parabola",{"1":{"49":1,"241":1,"307":1}}],["parametrized",{"1":{"139":8}}],["parametric",{"0":{"336":1},"1":{"28":2,"69":1,"84":4,"99":1,"124":2,"135":1,"139":2,"229":1,"310":1,"336":1,"366":1,"413":1,"415":1,"421":1},"2":{"124":1}}],["parameterize",{"0":{"258":1}}],["parameterized",{"0":{"139":1},"1":{"258":1}}],["parameters",{"0":{"34":1},"1":{"25":1,"30":1,"34":2,"42":1,"55":1,"61":2,"71":1,"98":1,"139":4,"180":1,"183":1,"219":1,"222":3,"224":1,"294":1,"295":2,"306":1,"310":1},"2":{"294":1}}],["parameter",{"1":{"5":1,"22":1,"28":1,"32":1,"37":1,"49":1,"61":1,"110":1,"160":1,"163":1,"181":1,"183":1,"188":1,"192":2,"196":1,"201":2,"202":2,"217":1,"221":1,"222":1,"223":2,"258":1,"363":1,"364":1,"367":2,"373":3,"374":1},"2":{"202":1}}],["partial",{"1":{"341":1}}],["particular",{"1":{"152":1,"406":1}}],["particularly",{"1":{"15":1,"307":1,"342":1}}],["party",{"0":{"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1},"1":{"281":1,"282":2,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"291":10}}],["partomatic>`",{"1":{"99":1}}],["partomatic",{"0":{"99":1},"1":{"99":1}}],["partcad",{"0":{"97":1,"98":1,"100":1},"1":{"97":3,"100":2},"2":{"98":1,"100":1}}],["part=pipe",{"1":{"184":1}}],["part=platonic",{"1":{"75":1}}],["part=stud",{"1":{"77":1}}],["part``",{"1":{"32":1,"181":1,"184":1,"194":2,"352":2,"368":1,"369":2}}],["parts",{"0":{"343":1},"1":{"12":2,"33":1,"36":2,"42":2,"55":1,"58":1,"77":1,"84":2,"97":1,"98":1,"100":2,"133":2,"139":1,"160":1,"164":1,"178":2,"183":1,"184":2,"223":1,"238":1,"252":1,"258":2,"261":1,"278":1,"291":1,"310":1,"334":1,"337":2,"340":1,"341":2,"342":2,"343":2,"345":1,"346":1,"359":1,"406":1}}],["part",{"0":{"96":1,"160":1,"334":1,"335":1,"370":1,"383":1},"1":{"10":1,"12":1,"13":1,"14":1,"17":3,"24":1,"31":1,"34":3,"35":1,"38":2,"42":1,"47":1,"49":17,"51":3,"58":1,"63":1,"64":2,"66":2,"67":2,"68":2,"69":2,"70":1,"72":1,"75":2,"76":5,"77":3,"78":3,"80":8,"81":3,"108":1,"110":5,"118":1,"124":2,"134":1,"142":1,"143":4,"144":4,"147":1,"149":5,"150":1,"151":1,"152":4,"153":4,"155":2,"158":1,"164":3,"167":2,"168":1,"171":1,"177":1,"178":2,"179":5,"181":2,"182":6,"184":8,"189":1,"191":3,"192":2,"193":7,"195":3,"199":1,"201":2,"202":1,"206":2,"220":10,"221":1,"222":2,"224":1,"227":1,"233":1,"238":13,"239":8,"240":1,"243":12,"244":1,"245":2,"248":1,"249":1,"250":4,"251":1,"252":1,"258":2,"259":2,"262":3,"267":1,"268":1,"272":20,"273":5,"275":1,"277":1,"278":6,"279":1,"280":3,"281":2,"282":1,"283":1,"284":4,"285":2,"286":1,"287":3,"288":1,"289":1,"290":1,"291":2,"334":1,"335":1,"336":1,"337":1,"339":1,"340":3,"341":3,"342":1,"343":1,"344":4,"345":12,"350":4,"352":1,"355":2,"357":1,"358":1,"359":2,"369":6,"370":1,"371":3,"378":2,"379":1,"381":3,"383":3,"384":1,"387":1,"388":5,"390":1,"393":1,"404":1,"405":1,"409":4,"410":1,"411":1,"412":2,"413":2,"414":1,"416":1,"420":1,"421":1},"2":{"10":1,"11":1,"32":1,"58":1,"143":1,"144":1,"151":1,"167":1,"168":1,"177":1,"181":1,"184":1,"186":1,"188":1,"192":1,"195":1,"243":1,"245":1,"250":1,"344":1,"345":1,"352":2,"368":1,"369":1}}],["patience",{"1":{"252":1}}],["patterns",{"1":{"310":1,"329":1,"406":1}}],["patterned",{"1":{"60":1}}],["pattern",{"1":{"60":4,"66":3,"71":1,"143":1,"144":2,"148":1,"173":1,"211":2,"295":1,"306":1,"307":2,"314":1},"3":{"9":1,"11":1,"19":1,"31":1,"34":1,"40":1,"42":1,"45":1,"49":1,"51":1,"60":1,"61":1,"63":1,"64":1,"65":1,"66":1,"67":1,"69":1,"70":1,"71":1,"76":1,"77":1,"78":1,"80":1,"124":1,"144":1,"146":1,"149":1,"152":1,"156":1,"157":1,"162":1,"166":1,"167":1,"168":1,"171":1,"173":1,"174":1,"175":1,"179":1,"182":1,"184":1,"185":1,"189":1,"198":1,"201":1,"204":1,"211":1,"218":1,"224":1,"238":1,"256":1,"262":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"286":1,"287":1,"288":1,"289":1,"345":1,"346":1,"350":1,"354":1,"357":1,"359":1,"368":1,"369":1,"374":1,"375":1,"376":1,"377":1,"414":1}}],["pathlib",{"1":{"276":1}}],["path=l1",{"1":{"282":1}}],["path=ex14",{"1":{"147":1}}],["path=path",{"1":{"78":1}}],["path=wire",{"1":{"74":1}}],["path=stub",{"1":{"74":2}}],["path=sprof",{"1":{"74":1}}],["path=handle",{"1":{"68":1}}],["path``",{"1":{"34":1}}],["paths",{"1":{"25":1,"26":1,"31":1,"123":1}}],["path",{"1":{"20":3,"24":1,"25":5,"34":6,"60":3,"61":1,"68":5,"74":1,"78":11,"124":5,"147":5,"184":2,"219":1,"235":3,"238":1,"276":5,"421":1},"2":{"20":2,"34":1,"147":1,"276":1},"3":{"4":1,"10":1,"16":1,"25":1,"31":1,"32":1,"34":1,"37":1,"42":1,"49":2,"51":1,"59":1,"60":1,"61":1,"62":1,"64":1,"65":1,"68":1,"69":1,"70":1,"71":1,"74":1,"76":1,"78":1,"80":1,"124":1,"144":1,"147":1,"149":1,"151":1,"152":1,"153":1,"156":1,"161":1,"164":1,"169":1,"170":1,"173":1,"174":1,"175":1,"179":1,"182":1,"184":1,"192":1,"193":1,"218":1,"224":1,"225":1,"229":1,"235":1,"236":1,"238":1,"239":1,"252":1,"259":1,"278":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"299":1,"345":1,"346":1,"350":1,"357":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"385":1,"387":1,"388":1,"389":1,"420":1}}],["patch`",{"1":{"421":1}}],["patching",{"1":{"2":1,"124":1}}],["patch",{"1":{"2":1,"410":1,"421":2},"2":{"421":1}}],["practical",{"0":{"318":1},"1":{"302":1,"310":1,"331":1,"415":1}}],["practice>`",{"1":{"367":1}}],["practice",{"0":{"255":1},"1":{"250":1,"257":1,"315":1,"420":1}}],["practices",{"0":{"260":1},"1":{"230":1}}],["prioritise",{"1":{"255":1}}],["priority",{"1":{"255":1}}],["prior",{"1":{"190":1,"201":1,"211":1}}],["prismatic",{"0":{"164":1,"341":1},"1":{"164":1,"172":1,"341":1}}],["prism",{"1":{"162":2}}],["principal",{"1":{"417":1}}],["principles",{"1":{"119":2,"194":1}}],["printed",{"1":{"268":1,"337":1}}],["printers",{"1":{"111":1}}],["printable",{"1":{"74":2}}],["printables",{"1":{"59":1}}],["printing",{"0":{"52":1},"1":{"22":1,"61":2,"74":1,"108":2,"111":1,"121":2,"124":1,"248":1,"257":1}}],["print",{"1":{"3":1,"14":2,"21":3,"22":2,"52":2,"66":1,"109":6,"131":1,"198":1,"257":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"410":1}}],["primitive",{"0":{"414":1},"1":{"234":1,"410":1,"414":1,"417":1}}],["primitives",{"0":{"404":1},"1":{"122":1,"235":1,"255":1,"295":1,"299":1,"408":1,"410":4,"411":1,"413":1,"421":1},"2":{"122":1,"404":1,"408":2,"409":1,"410":2,"411":1,"413":1,"415":1,"417":1}}],["primitives``",{"1":{"408":1,"409":1,"411":1,"413":1,"417":1}}],["primitives`",{"1":{"122":1,"408":1,"413":1,"415":2}}],["primarily",{"1":{"113":1}}],["primary",{"1":{"25":1,"26":1,"54":1,"197":1,"243":1,"310":1}}],["prime",{"1":{"60":3}}],["private``",{"1":{"162":1,"167":1,"192":1,"299":1}}],["private",{"1":{"49":1,"67":1,"74":2,"162":1,"167":1,"168":1,"170":2,"192":1,"194":1,"279":1,"282":1,"286":1,"287":3,"289":1,"299":4,"307":1,"331":2},"2":{"37":1,"192":1,"223":1,"299":1}}],["preparation",{"1":{"415":1,"420":1}}],["preparing",{"0":{"409":1},"1":{"257":1}}],["predict",{"1":{"310":1}}],["predictably",{"1":{"302":1}}],["predefines",{"1":{"184":1}}],["predefined",{"1":{"10":1,"31":1,"182":1,"240":1,"241":1}}],["preference",{"1":{"331":1},"2":{"331":1}}],["prefer",{"1":{"127":1,"197":2,"296":1,"319":1,"320":1,"333":1}}],["preserves",{"1":{"314":1}}],["preserve",{"1":{"310":1}}],["preserved",{"1":{"206":1,"257":1}}],["preserve=false",{"1":{"108":1}}],["present",{"1":{"183":2,"404":1}}],["presented",{"1":{"119":1,"222":1,"291":1}}],["presentation",{"1":{"119":2}}],["pressing",{"1":{"53":1}}],["preview",{"1":{"80":1,"244":1}}],["previous",{"1":{"17":1,"20":1,"28":1,"49":1,"141":1,"168":1,"268":1,"272":1,"344":1}}],["previously",{"1":{"5":1,"25":1,"26":1,"182":1}}],["precision=1",{"1":{"243":1}}],["precision",{"1":{"135":1,"230":3,"233":1,"236":1}}],["precisionmode",{"2":{"49":1}}],["precisionmode`",{"1":{"49":1}}],["precise",{"1":{"111":1,"112":1,"124":1,"135":1,"194":1,"196":1,"204":1,"206":1,"230":1,"233":1,"236":1,"237":1,"310":1,"421":1}}],["precisely",{"1":{"67":2,"310":1,"345":1}}],["pre",{"1":{"36":1}}],["probably",{"1":{"413":1}}],["problematic",{"1":{"217":1}}],["problem",{"1":{"140":1,"279":1,"295":1,"312":1,"378":1}}],["problems",{"1":{"50":1,"280":1,"310":1,"329":1,"330":1}}],["proud",{"1":{"365":1}}],["proficiency",{"1":{"291":1}}],["profile``",{"1":{"250":1}}],["profile",{"1":{"42":1,"60":3,"61":5,"71":2,"78":2,"81":5,"145":1,"176":1,"194":1,"218":1,"230":5,"233":1,"235":4,"250":1,"278":1,"279":2,"299":1,"313":1,"314":1,"331":1,"338":1,"340":9,"341":1,"342":1,"346":1,"350":3,"400":1,"402":1,"403":1,"421":1},"2":{"250":1}}],["profiles=ex36",{"1":{"171":1}}],["profiles=",{"1":{"61":1}}],["profiles",{"0":{"172":1,"340":1,"399":1},"1":{"38":1,"61":1,"172":1,"235":1,"236":5,"334":1,"340":4,"341":1,"395":6,"396":2,"399":1,"400":7,"403":2},"2":{"399":1},"3":{"49":1,"71":1,"72":1,"73":1,"158":1,"190":1,"229":1,"235":1,"236":1,"238":1,"239":1,"252":1,"285":1}}],["proven",{"1":{"260":1}}],["prove",{"1":{"258":1}}],["provided",{"1":{"108":1,"109":1,"123":1,"147":2,"173":1,"178":1,"197":1,"199":2,"202":1,"254":1,"262":2,"276":1,"291":1,"295":1,"306":1,"325":1,"345":1}}],["provide",{"1":{"39":1,"52":1,"99":1,"121":1,"133":1,"134":1,"138":2,"139":1,"141":1,"181":1,"195":1,"214":1,"230":1,"236":1,"269":1,"274":1,"310":1,"329":1,"333":1,"389":1}}],["provides",{"1":{"19":1,"91":1,"98":1,"99":1,"108":1,"112":1,"119":1,"124":1,"141":2,"189":1,"197":1,"200":1,"206":1,"233":1,"235":1,"302":1,"310":2,"348":1,"366":1,"379":1,"408":1,"421":2}}],["providing",{"1":{"31":1,"111":1,"204":1,"206":1,"278":1,"420":1}}],["proof",{"1":{"255":1}}],["progressively",{"1":{"167":1,"168":1,"233":1}}],["programmatic",{"1":{"310":1,"345":1}}],["programmatically",{"1":{"78":1}}],["programming",{"0":{"140":1},"1":{"3":1,"7":1,"140":3}}],["prone",{"1":{"147":1,"236":1,"250":1}}],["prototyping",{"1":{"121":1}}],["properly",{"1":{"421":1}}],["proper",{"1":{"345":1}}],["properties",{"1":{"99":1,"123":1,"135":1,"204":1,"206":1,"265":3,"266":3,"268":1,"271":1}}],["property",{"1":{"24":1,"28":1,"33":1,"38":1,"39":2,"181":1,"204":1,"271":3,"358":1,"368":1}}],["proprietary",{"1":{"137":1,"138":12}}],["proportionally",{"1":{"75":1}}],["produce",{"1":{"304":1,"312":2,"326":1}}],["produces",{"1":{"19":2,"417":1}}],["producing",{"1":{"189":1,"303":1,"308":1,"403":1}}],["production",{"1":{"310":1,"311":1,"318":1}}],["product",{"1":{"64":2,"119":1,"120":4,"369":1},"2":{"64":1}}],["projects",{"1":{"84":1,"99":2,"113":1,"140":1}}],["projection",{"0":{"110":1},"1":{"71":1,"110":3,"238":1,"243":1,"246":1}}],["projecting",{"1":{"61":3,"62":1}}],["projected",{"1":{"61":3,"62":4}}],["project",{"1":{"60":1,"61":5,"62":12,"67":1,"71":1,"76":1,"95":1,"110":2,"140":1,"141":2,"238":2,"239":2,"243":7,"245":1},"2":{"49":1,"61":2,"62":2,"67":1,"71":1,"76":1,"110":1,"238":2,"239":2,"243":2}}],["project`",{"1":{"49":3,"238":1}}],["proceed",{"1":{"34":1,"53":1}}],["processor",{"1":{"413":1}}],["processing",{"1":{"191":1,"253":1,"377":1}}],["processes",{"1":{"81":1,"124":1}}],["process",{"1":{"12":1,"22":1,"108":1,"117":1,"120":1,"134":2,"139":3,"194":1,"200":1,"206":1,"211":1,"235":1,"334":1,"339":1,"415":1,"416":1,"420":1}}],["prompt",{"1":{"1":1,"131":1}}],["w3",{"1":{"284":2}}],["w2",{"1":{"284":4}}],["w1",{"1":{"284":3}}],["wts",{"1":{"165":2},"2":{"165":1}}],["w",{"1":{"163":8,"176":10,"189":1}}],["writing",{"1":{"133":1,"134":1,"255":2,"278":1}}],["written",{"1":{"110":1,"123":1,"406":1}}],["writes",{"1":{"189":1}}],["write",{"1":{"67":1,"76":1,"108":3,"110":1,"140":2,"189":3,"243":2,"276":1},"2":{"67":1,"76":1,"108":1,"110":1,"189":1,"243":1,"276":1}}],["wrist",{"1":{"61":1}}],["wrapper",{"1":{"98":1,"251":1,"293":1},"2":{"251":1}}],["wrapped``",{"1":{"369":1}}],["wrapped",{"1":{"10":3,"60":1,"64":1,"81":1,"251":4,"341":1,"355":1,"369":1},"2":{"10":1,"251":1}}],["wrap",{"1":{"60":3},"2":{"60":1}}],["www",{"1":{"59":1,"70":1,"94":1,"278":1,"291":1}}],["warranties",{"1":{"278":1}}],["warning",{"1":{"128":1,"415":1}}],["warehouse`",{"1":{"244":1}}],["warehouse",{"0":{"84":1},"1":{"84":2,"179":1,"184":2,"243":1}}],["water",{"1":{"420":1,"421":1}}],["watertight",{"1":{"61":1,"206":1,"421":1}}],["watch",{"1":{"94":2}}],["wants",{"1":{"262":1}}],["want=1028",{"1":{"278":1}}],["want=",{"1":{"72":1}}],["want",{"1":{"72":3,"128":1,"129":1,"171":1,"177":1,"178":2,"257":1,"268":1,"275":1,"278":3,"279":4,"280":3,"281":3,"282":3,"283":3,"284":3,"285":3,"286":3,"287":3,"288":3,"289":3,"290":3,"295":1,"304":1,"311":1,"387":1}}],["wave",{"1":{"62":2}}],["waiting",{"1":{"53":1}}],["walks",{"1":{"299":1}}],["walk",{"1":{"53":1}}],["walls",{"0":{"373":1,"377":1},"1":{"76":3,"77":1,"160":1,"368":8,"369":4,"373":2,"374":2,"375":2,"376":2,"377":3}}],["wall",{"0":{"77":1},"1":{"34":6,"69":6,"73":3,"76":11,"77":11,"78":12,"124":6,"160":4,"313":1,"314":1,"367":1,"368":4,"369":4,"373":1,"374":1,"375":3,"376":3,"377":5},"3":{"34":1,"42":1,"49":1,"52":1,"61":1,"62":1,"71":1,"72":1,"76":1,"78":1,"80":1,"81":1,"124":1,"149":1,"152":1,"154":1,"158":1,"159":1,"160":1,"161":1,"163":1,"182":1,"238":1,"239":1,"241":1,"243":1,"278":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"287":1,"290":1,"310":1,"313":1,"314":1,"340":1,"341":1,"346":1,"357":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"406":1,"417":1,"419":1,"420":1}}],["wasm>`",{"1":{"95":1}}],["wasm",{"0":{"95":1},"1":{"95":1}}],["washers",{"1":{"84":1}}],["was",{"1":{"26":1,"28":1,"39":2,"67":1,"129":1,"133":1,"189":2,"190":1,"201":1,"254":2,"262":1,"339":1,"344":1,"357":1,"383":1,"408":2,"414":1,"420":1}}],["ways",{"1":{"110":1,"138":1,"139":1,"238":1,"260":1,"417":1}}],["way",{"1":{"11":2,"19":1,"75":1,"121":1,"129":1,"135":1,"138":1,"139":1,"141":1,"147":1,"178":1,"184":2,"192":1,"198":1,"200":1,"221":1,"262":1,"267":2,"268":1,"272":1,"307":1,"374":1,"422":1}}],["wealth",{"1":{"233":1}}],["weights=wts",{"1":{"165":2}}],["weights",{"1":{"113":1,"119":1,"218":1}}],["weight=1",{"1":{"67":2}}],["web",{"1":{"99":2,"104":1,"117":1,"123":3,"140":2}}],["wevolver",{"1":{"92":1}}],["welcome",{"1":{"233":1,"234":1}}],["weld",{"1":{"286":1}}],["weldneckflange",{"1":{"184":2},"2":{"184":1}}],["welding",{"1":{"69":1}}],["welded",{"1":{"69":1}}],["wells",{"1":{"80":1}}],["well",{"1":{"27":1,"31":1,"61":1,"80":3,"91":1,"98":1,"100":1,"108":1,"113":1,"124":1,"131":1,"133":1,"202":1,"206":1,"254":1,"310":1,"353":1,"403":1,"404":1,"405":1}}],["west",{"1":{"62":14}}],["we",{"1":{"12":1,"13":1,"61":5,"80":1,"144":1,"146":2,"150":1,"151":3,"153":2,"157":1,"158":1,"161":1,"162":3,"163":1,"164":2,"169":3,"170":2,"172":1,"173":2,"177":1,"214":1,"267":1,"268":2,"275":1,"279":2,"295":2,"334":1,"335":1,"339":2,"341":3,"344":1,"345":1,"348":1,"362":1,"367":2,"368":5,"369":2,"370":1,"371":3,"373":1,"374":1,"377":1,"378":3,"379":1,"381":1,"382":3,"383":1,"385":1,"386":1,"387":2,"388":2,"389":2,"390":1,"391":3,"392":1,"393":2,"394":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"403":1,"419":4,"420":9}}],["wedge`",{"1":{"49":1,"220":1}}],["wedge",{"1":{"220":2,"227":1},"2":{"10":1,"49":1,"220":1,"227":1}}],["were",{"1":{"4":1,"31":1,"34":1,"61":1,"76":1,"102":1,"141":1,"158":1,"222":1,"291":1,"410":2}}],["won",{"1":{"367":1}}],["world",{"1":{"78":1,"108":1,"169":5,"208":1,"209":1,"291":1,"337":1}}],["worked",{"0":{"417":1}}],["workaround",{"1":{"284":2}}],["workflows",{"1":{"230":1,"236":1,"329":1}}],["workflow",{"0":{"193":1,"235":1},"1":{"91":1,"122":1,"189":1,"229":1,"230":1,"234":1,"236":1,"237":1,"310":2,"346":1,"407":1,"408":1,"413":1,"415":1}}],["workshops",{"1":{"74":1}}],["works",{"0":{"194":1,"245":1},"1":{"34":1,"186":1,"189":1,"200":1,"221":2,"307":1,"310":1,"374":1}}],["work",{"0":{"262":1},"1":{"31":2,"42":2,"80":1,"129":2,"139":1,"140":1,"141":3,"178":1,"181":1,"189":1,"202":3,"250":1,"255":1,"262":3,"272":1,"281":1,"334":1,"394":1,"403":1,"409":2,"410":1,"412":1,"415":1}}],["working",{"0":{"31":1,"173":1,"263":1,"416":1},"1":{"31":2,"128":1,"141":1,"178":1,"201":2,"202":1,"236":1,"290":1,"299":1,"339":1,"345":1,"405":2,"410":2,"415":1,"422":1}}],["workplane`",{"1":{"238":1}}],["workplanelist",{"1":{"51":2}}],["workplanes",{"0":{"151":1,"155":1,"156":1,"202":1},"1":{"39":1,"42":4,"51":2,"162":1,"202":3}}],["workplane",{"0":{"152":1,"154":1,"254":1},"1":{"7":2,"31":5,"39":2,"40":1,"42":6,"80":1,"152":2,"156":3,"198":1,"201":1,"202":6,"238":1,"239":1,"254":2,"262":2,"369":4},"2":{"7":2,"39":1,"40":1,"191":1,"202":1,"238":1,"239":1}}],["would",{"1":{"4":1,"26":1,"31":2,"39":1,"40":1,"50":1,"61":1,"152":2,"169":1,"173":1,"175":1,"190":1,"192":1,"222":1,"255":1,"262":3,"345":1,"354":2}}],["why",{"0":{"236":1,"237":1,"262":1,"263":1,"416":1},"1":{"137":1,"189":2,"255":1,"262":1,"352":1}}],["whose",{"1":{"310":1,"329":1}}],["who",{"1":{"102":1,"138":2,"140":4,"141":2,"163":1,"221":1,"250":1}}],["whole",{"1":{"60":1,"143":1,"258":1}}],["whatever",{"1":{"354":1}}],["what",{"1":{"34":1,"42":1,"141":1,"189":1,"197":1,"240":1,"263":1,"272":1,"311":1,"340":1,"345":1,"363":1,"404":1,"405":1,"408":2}}],["wheel",{"1":{"60":3,"80":4}}],["whether",{"1":{"21":1,"343":1}}],["whenever",{"1":{"420":1}}],["when",{"0":{"254":1},"1":{"19":1,"22":1,"25":1,"26":1,"31":2,"34":1,"36":1,"39":1,"40":1,"42":2,"61":2,"129":1,"133":1,"134":1,"139":1,"141":2,"145":1,"158":1,"179":1,"183":1,"184":1,"189":2,"190":2,"194":1,"195":1,"198":1,"199":1,"201":2,"202":1,"211":1,"236":1,"250":1,"254":2,"255":1,"256":2,"257":3,"258":1,"262":2,"263":1,"272":1,"275":1,"276":1,"295":2,"299":2,"306":2,"307":1,"310":1,"320":1,"322":1,"324":1,"325":1,"331":1,"333":1,"343":1,"347":1,"358":1,"359":1,"378":1,"402":1,"403":1,"411":1,"412":2,"414":1,"415":1,"420":2,"421":1}}],["wherever",{"1":{"336":1}}],["where",{"1":{"4":1,"15":1,"19":3,"34":1,"36":1,"39":1,"42":1,"61":2,"74":1,"77":1,"78":2,"110":1,"124":2,"171":1,"184":1,"188":1,"198":1,"202":2,"206":1,"243":1,"255":1,"259":2,"261":1,"262":2,"272":2,"273":1,"289":1,"299":3,"304":2,"306":1,"312":1,"334":1,"339":1,"340":1,"345":1,"350":1,"357":1,"369":1,"410":1,"413":1}}],["white",{"1":{"62":2,"76":5}}],["while",{"1":{"5":1,"18":1,"28":1,"39":1,"42":1,"70":3,"77":1,"98":1,"124":1,"138":9,"141":1,"195":1,"224":1,"229":1,"231":1,"234":1,"258":1,"272":1,"306":1,"310":1,"314":1,"329":1,"343":1,"408":1}}],["which",{"1":{"1":1,"2":1,"5":1,"6":1,"12":1,"14":1,"17":1,"19":3,"22":1,"23":1,"25":2,"26":1,"30":1,"31":2,"32":1,"34":2,"36":1,"37":2,"39":1,"42":2,"51":1,"52":1,"57":1,"61":1,"66":1,"71":1,"75":1,"76":1,"77":1,"78":2,"81":1,"92":1,"98":1,"119":1,"131":1,"133":5,"134":5,"135":6,"138":1,"139":1,"140":4,"141":5,"143":1,"147":1,"174":1,"176":1,"177":1,"183":1,"184":3,"189":2,"191":2,"192":1,"194":1,"195":1,"197":1,"198":2,"201":2,"202":4,"210":2,"217":2,"221":1,"230":1,"235":2,"238":1,"240":1,"254":1,"255":2,"257":1,"259":1,"272":2,"274":1,"303":1,"304":1,"311":1,"329":1,"331":1,"340":2,"341":1,"344":1,"345":2,"352":2,"353":1,"363":1,"364":1,"368":1,"373":1,"374":1,"385":1,"389":1,"394":1,"406":3,"420":1}}],["wing",{"0":{"403":1},"1":{"278":5,"395":30,"396":4,"397":16,"398":1,"399":2,"400":8,"401":8,"403":1,"418":2,"421":1},"2":{"397":1}}],["wings",{"1":{"278":1}}],["winning",{"1":{"102":1}}],["windows",{"1":{"80":1,"102":1,"128":1,"129":1,"140":1}}],["window",{"1":{"80":6}}],["wind",{"0":{"62":1},"1":{"62":9,"73":1}}],["widespread",{"1":{"117":1}}],["widely",{"1":{"112":2,"113":1,"120":1,"121":2,"123":3}}],["wide",{"1":{"101":1,"140":1,"230":1,"235":1,"307":1}}],["widthwise",{"1":{"368":1,"369":1,"374":1,"375":1,"376":1,"377":1}}],["width=ridge",{"1":{"368":1,"369":1,"374":1,"375":1,"376":1,"377":1}}],["width=block",{"1":{"368":3,"369":3,"372":1,"373":1,"374":2,"375":2,"376":2,"377":2}}],["width=5",{"1":{"356":2}}],["width=length",{"1":{"37":1}}],["widths",{"1":{"286":1}}],["widths=110",{"1":{"278":1}}],["widths=",{"1":{"278":1}}],["width",{"1":{"3":1,"6":2,"7":2,"32":2,"48":2,"61":8,"62":10,"64":2,"67":12,"76":18,"77":6,"124":1,"139":1,"142":4,"143":3,"144":6,"149":14,"151":4,"153":4,"154":7,"155":6,"156":6,"158":4,"160":4,"161":9,"162":2,"164":6,"169":4,"170":14,"172":14,"177":4,"182":2,"190":2,"219":3,"220":1,"230":7,"240":2,"247":1,"256":3,"257":1,"290":1,"336":1,"339":1,"345":1,"346":1,"350":11,"352":1,"353":3,"367":2,"368":6,"369":6,"372":1,"373":1,"374":4,"375":5,"376":5,"377":5,"396":1,"420":1},"2":{"61":1,"77":1,"350":1}}],["wiki",{"1":{"87":1,"255":1,"339":1}}],["wikipedia",{"1":{"87":1,"255":1,"339":1}}],["wireframe",{"1":{"194":1,"235":1}}],["wire`",{"1":{"49":4,"58":1,"206":1,"238":1}}],["wires`",{"1":{"49":3,"238":1,"266":1}}],["wires",{"1":{"46":1,"66":4,"74":3,"206":3,"238":1,"239":1,"240":2,"241":2,"242":1,"274":1,"394":1,"421":1},"2":{"49":1,"74":1,"238":1,"239":1,"240":1,"241":1,"266":1}}],["wire",{"1":{"5":2,"49":1,"58":1,"59":1,"61":2,"66":4,"74":2,"75":1,"80":1,"147":1,"206":3,"238":1,"239":1,"241":1,"264":3,"266":3,"304":1,"313":1,"395":1,"400":1,"420":4},"2":{"28":1,"49":1,"58":1,"61":1,"66":1,"74":1,"80":1,"206":1,"238":1,"239":1,"270":1,"271":1,"304":1,"395":1,"400":1,"420":1}}],["will",{"1":{"2":1,"11":1,"13":1,"19":2,"20":1,"22":1,"23":1,"26":1,"30":1,"31":3,"32":1,"34":2,"37":1,"39":1,"42":1,"60":1,"73":1,"77":3,"91":1,"128":1,"129":1,"134":1,"171":1,"172":1,"177":1,"178":1,"181":1,"182":4,"184":2,"188":3,"190":3,"192":1,"197":1,"201":5,"202":2,"203":1,"206":1,"221":2,"229":1,"238":1,"241":1,"254":1,"257":2,"259":1,"261":1,"262":1,"263":2,"268":1,"272":1,"334":1,"340":2,"345":2,"347":1,"350":1,"353":1,"357":3,"358":1,"359":1,"362":1,"368":1,"370":1,"371":2,"372":1,"373":3,"374":2,"375":1,"376":2,"379":1,"381":1,"382":1,"383":1,"384":1,"396":1,"420":2}}],["within",{"0":{"263":1},"1":{"13":1,"15":2,"17":1,"18":1,"23":1,"26":1,"30":1,"32":1,"37":1,"40":2,"69":1,"179":2,"181":1,"182":1,"184":2,"192":1,"197":1,"198":4,"202":1,"204":3,"206":3,"211":1,"238":2,"255":1,"263":2,"276":2,"295":1,"299":1,"337":1,"340":1,"341":1,"345":1,"368":1,"378":2}}],["without",{"1":{"1":1,"2":1,"5":1,"7":1,"15":1,"123":1,"134":1,"139":1,"147":1,"184":1,"199":1,"230":1,"238":1,"263":1,"268":1,"278":1,"298":1,"303":1,"310":1,"358":1}}],["with",{"0":{"64":1,"145":1,"147":1,"153":1,"305":1,"381":1,"403":1},"1":{"1":1,"2":1,"3":3,"4":3,"5":2,"6":2,"7":3,"9":6,"10":10,"11":1,"13":1,"17":1,"20":1,"23":2,"24":1,"25":5,"26":3,"27":1,"28":5,"30":2,"31":4,"32":3,"33":1,"34":8,"36":3,"37":7,"38":1,"39":1,"40":1,"42":7,"48":1,"50":1,"51":4,"53":1,"54":2,"59":5,"60":7,"61":2,"62":4,"63":5,"64":5,"65":7,"66":1,"67":13,"68":3,"69":6,"70":7,"71":7,"72":2,"73":2,"74":5,"75":1,"76":25,"77":5,"78":11,"80":21,"81":6,"86":1,"91":1,"94":1,"99":1,"102":1,"108":1,"109":1,"112":1,"118":1,"121":1,"123":1,"124":13,"128":4,"129":3,"133":5,"134":1,"138":1,"140":1,"141":5,"142":1,"143":1,"144":5,"145":3,"146":4,"147":3,"148":4,"149":5,"150":2,"151":4,"152":4,"153":2,"154":3,"155":3,"156":3,"157":6,"158":3,"159":7,"160":2,"161":2,"162":4,"163":5,"164":3,"165":3,"166":4,"167":4,"168":4,"169":3,"170":4,"171":5,"172":4,"173":6,"174":3,"175":3,"176":3,"177":1,"178":2,"179":7,"181":3,"182":13,"183":2,"184":7,"187":1,"188":2,"189":4,"190":4,"191":3,"192":3,"193":3,"194":2,"195":3,"197":2,"198":4,"199":2,"201":4,"202":10,"204":2,"206":2,"210":3,"211":1,"218":1,"219":4,"221":2,"222":5,"223":6,"224":6,"229":1,"230":4,"231":1,"233":3,"234":1,"235":2,"236":5,"237":2,"238":2,"240":4,"241":2,"242":1,"249":2,"250":4,"251":1,"255":5,"256":3,"257":1,"259":1,"260":2,"262":7,"263":2,"265":3,"267":3,"268":3,"270":1,"272":8,"275":3,"276":2,"278":9,"279":7,"280":13,"281":10,"282":8,"283":10,"284":12,"285":5,"286":6,"287":10,"288":11,"289":9,"290":5,"291":3,"295":3,"296":1,"298":1,"299":6,"303":1,"304":1,"306":1,"307":3,"308":1,"310":3,"312":2,"315":1,"316":1,"317":1,"318":1,"319":1,"328":1,"329":2,"331":2,"332":1,"333":1,"334":1,"335":1,"339":2,"340":6,"341":3,"342":1,"344":1,"345":7,"346":6,"347":2,"348":1,"350":14,"353":2,"354":1,"357":5,"358":1,"359":3,"367":1,"368":10,"369":9,"370":2,"371":2,"372":4,"373":4,"374":5,"375":6,"376":7,"377":6,"378":1,"381":1,"382":2,"384":1,"385":3,"386":2,"388":3,"389":2,"390":1,"391":1,"392":1,"393":1,"394":3,"396":1,"397":1,"398":1,"399":1,"404":1,"406":1,"408":1,"409":1,"410":1,"413":1,"414":1,"416":1,"417":3,"420":9,"421":2},"2":{"23":1,"32":1,"37":2}}],["`operators`",{"1":{"274":1,"277":1}}],["`ocp",{"1":{"87":1,"93":1,"94":1,"95":1,"130":1,"181":1,"244":1,"251":1,"299":1}}],["`27",{"1":{"238":1}}],["`23",{"1":{"238":1}}],["`25",{"1":{"238":1}}],["`24",{"1":{"238":1}}],["`14",{"1":{"238":1}}],["`15",{"1":{"238":1}}],["`16",{"1":{"238":1}}],["`4",{"1":{"238":1}}],["`3",{"1":{"238":1}}],["`9",{"1":{"238":2}}],["`geometry",{"1":{"173":2}}],["`genindex`",{"1":{"125":1}}],["`import",{"1":{"178":1}}],["`intersect`",{"1":{"272":1}}],["`in",{"1":{"128":1}}],["`iter`",{"1":{"7":1}}],["`yet",{"1":{"104":1}}],["`tutorial",{"1":{"418":1,"420":1}}],["`true`",{"1":{"257":1}}],["`text`",{"1":{"245":1}}],["`technicaldrawing`",{"1":{"245":1}}],["`ttt",{"1":{"238":1}}],["`toby",{"1":{"291":1}}],["`to",{"1":{"97":1}}],["`topology`",{"1":{"277":1}}],["`topology",{"1":{"87":1,"420":1}}],["`there",{"1":{"367":1}}],["`the",{"1":{"92":1,"100":1}}],["`nething",{"1":{"92":1}}],["`n=2",{"1":{"10":1}}],["`n=1`",{"1":{"10":1}}],["`n=1",{"1":{"9":2,"10":3}}],["`m6",{"1":{"360":1}}],["`master`",{"1":{"129":1}}],["`makerrepo",{"1":{"90":1,"91":3}}],["`modindex`",{"1":{"125":1}}],["`mesher`",{"1":{"59":1}}],["`jdegenstein",{"1":{"86":1}}],["`joints`",{"1":{"57":1}}],["`joint",{"1":{"12":1,"183":1}}],["`b`",{"1":{"187":1}}],["`build123d`",{"1":{"244":1,"248":1}}],["`build123d",{"1":{"87":1,"94":1}}],["`blendquery",{"1":{"85":1}}],["`bd",{"1":{"82":1,"83":1,"84":1,"244":1}}],["`b^1",{"1":{"10":2}}],["`b^2",{"1":{"10":1}}],["`b^3",{"1":{"10":2}}],["`sketching",{"1":{"262":1}}],["`shallow",{"1":{"261":1}}],["`sorted`",{"1":{"240":1}}],["`solid`",{"1":{"59":1}}],["`solids",{"1":{"4":1}}],["`selectors`",{"1":{"277":1}}],["`see",{"1":{"222":1}}],["`search`",{"1":{"125":1}}],["`steppermotor`",{"1":{"244":1}}],["`stl",{"1":{"122":1}}],["`studwall`",{"1":{"77":2}}],["`stud`",{"1":{"77":3}}],["`superellipses",{"1":{"102":1}}],["`right",{"1":{"339":1}}],["`rigidjoints`",{"1":{"77":1}}],["`r`",{"1":{"187":1}}],["`range`",{"1":{"64":1}}],["`reddaugherty`",{"1":{"59":1}}],["`domain",{"1":{"255":1}}],["`discord",{"1":{"124":1}}],["`design",{"1":{"415":1}}],["`dev`",{"1":{"129":1}}],["`demo",{"1":{"104":1}}],["`debug`",{"1":{"7":1}}],["`dl4to4ocp",{"1":{"87":1}}],["`dl4to",{"1":{"87":1}}],["`draft`",{"1":{"63":1}}],["`~joints",{"1":{"179":1,"180":3,"181":11,"182":2,"183":1,"184":1}}],["`~exporters",{"1":{"119":1}}],["`~mesher",{"1":{"108":1,"109":1,"408":1,"416":1}}],["`~drafting",{"1":{"49":5,"219":5}}],["`~objects",{"1":{"49":50,"71":1,"142":1,"143":2,"153":4,"157":3,"164":4,"165":2,"170":5,"175":2,"176":1,"218":28,"219":13,"220":10,"222":6,"224":1,"294":1,"295":1,"299":1,"303":2,"306":7,"307":7,"310":11,"315":1,"316":1,"329":2,"330":2,"381":1,"386":1,"387":2,"388":1}}],["`~operations",{"1":{"25":1,"26":2,"34":3,"38":2,"39":1,"49":35,"110":1,"143":2,"144":2,"147":3,"158":1,"159":2,"160":2,"164":2,"167":1,"170":1,"171":1,"172":2,"176":1,"177":2,"199":1,"238":23,"250":3,"252":2,"308":1,"310":3,"313":1,"314":1,"388":1,"389":1,"419":1,"420":1}}],["`~build123d",{"1":{"122":1,"408":1,"413":1,"415":2}}],["`~build",{"1":{"40":4,"48":2,"49":50,"65":1,"69":1,"143":1,"144":3,"146":2,"152":2,"153":1,"156":1,"159":1,"162":1,"164":2,"166":1,"167":2,"168":1,"169":2,"170":1,"171":1,"172":2,"173":1,"174":1,"181":1,"184":1,"211":4,"238":10,"241":2,"271":2,"272":2,"357":1,"359":1,"381":1,"382":1,"383":1}}],["`~geometry",{"1":{"39":1,"49":26,"147":1,"150":1,"152":1,"156":1,"184":1,"204":4,"210":2,"217":1,"241":2,"293":3,"306":3,"347":1,"352":1,"358":2}}],["`~importers",{"1":{"26":1}}],["`~topology",{"1":{"12":3,"13":1,"14":4,"19":2,"20":3,"49":23,"58":8,"110":1,"147":2,"152":2,"172":1,"177":1,"181":6,"183":1,"184":3,"204":5,"206":9,"240":1,"242":1,"257":1,"259":1,"266":12,"293":1,"299":1,"306":1,"330":2,"347":1,"348":2,"351":4,"352":1,"353":4,"354":3,"357":2,"358":2,"359":1,"360":4,"363":1,"383":1,"396":1,"402":1,"403":1,"410":1,"418":1,"419":4,"420":6,"421":10}}],["`+`",{"1":{"194":1}}],["`+",{"1":{"10":1}}],["`c`",{"1":{"187":1}}],["`cq",{"1":{"93":1}}],["`cadquery",{"1":{"87":1,"251":1}}],["`c^1",{"1":{"10":1}}],["`c^1`",{"1":{"10":1}}],["`c^2",{"1":{"10":1}}],["`c^2`",{"1":{"10":1}}],["`c^3",{"1":{"10":1}}],["`c^3`",{"1":{"10":1}}],["`c",{"1":{"9":2}}],["`plane",{"1":{"399":1}}],["`poetry",{"1":{"129":1}}],["`pdf",{"1":{"124":1}}],["`py",{"1":{"101":1}}],["`publish",{"1":{"97":1}}],["`part",{"1":{"241":12}}],["`partcad",{"1":{"100":1}}],["`partomatic",{"1":{"99":1}}],["`part`",{"1":{"77":1,"249":1}}],["`pack`",{"1":{"257":1}}],["`pack",{"1":{"18":1,"108":1,"257":2}}],["`project",{"1":{"245":2}}],["`product`",{"1":{"64":1}}],["`print`",{"1":{"7":1}}],["`p",{"1":{"9":3}}],["`align",{"1":{"257":1}}],["`algebra",{"1":{"172":1,"174":1,"187":2}}],["`assembly`",{"1":{"184":1}}],["`anytree",{"1":{"20":1}}],["`a",{"1":{"9":1,"10":4}}],["``kind",{"1":{"373":1}}],["``kind``",{"1":{"373":1}}],["``key",{"1":{"268":1}}],["``unqualified``",{"1":{"331":2,"333":1}}],["``until",{"1":{"171":2}}],["``0``",{"1":{"276":1}}],["``new",{"1":{"273":3}}],["``new``",{"1":{"272":1}}],["``node``",{"1":{"20":5}}],["``nodemixin``",{"1":{"20":1}}],["``geomtype``",{"1":{"271":1}}],["``group``",{"1":{"268":1}}],["``groupby``",{"1":{"268":2,"269":1}}],["``gridlocations``",{"1":{"198":2,"374":4,"376":1}}],["``+z``",{"1":{"267":1}}],["``+``",{"1":{"11":1,"144":1,"185":1,"189":1}}],["````",{"1":{"299":1}}],["``a``",{"1":{"294":2,"295":1}}],["``all``",{"1":{"272":1}}],["``align``",{"1":{"221":4,"222":1}}],["``align",{"1":{"22":1}}],["``angle",{"1":{"183":1}}],["``angle``",{"1":{"180":1,"183":1,"316":1,"325":1,"363":1,"364":1}}],["``ancestors``",{"1":{"20":1}}],["``axis``",{"1":{"183":1,"271":6}}],["``axis",{"1":{"152":1,"241":4,"275":1,"384":1}}],["``add``",{"1":{"37":1,"223":1,"263":1}}],["``arc",{"1":{"30":1}}],["``a",{"1":{"10":3}}],["``range``",{"1":{"183":1}}],["``radius``",{"0":{"322":1}}],["``radius=0",{"1":{"30":1}}],["``radiusarc``",{"1":{"10":1}}],["``rigidjoint``",{"1":{"179":1,"180":1,"182":1,"183":1,"184":1}}],["``rotation",{"1":{"201":2}}],["``rotation``",{"1":{"201":3,"222":1}}],["``rot",{"1":{"173":1,"209":2}}],["``root``",{"1":{"20":1}}],["``render",{"1":{"184":1}}],["``revolutejoint``",{"1":{"182":1,"183":1}}],["``replace``",{"1":{"37":1,"223":1}}],["``regularpolygon``",{"1":{"10":1}}],["``rectangle``",{"1":{"10":2,"37":1,"372":1,"374":1,"375":2}}],["``hinge",{"1":{"362":2,"363":1,"364":1}}],["``hinge``",{"1":{"350":1}}],["``handle",{"1":{"34":2}}],["``height``",{"1":{"20":1,"222":1}}],["``helix``",{"1":{"10":1}}],["``hyperboliccenterarc``",{"1":{"10":1}}],["``hole``",{"1":{"10":1,"192":2}}],["``blendcurve",{"1":{"304":1}}],["``b``",{"1":{"294":2,"295":1}}],["``bd",{"1":{"255":1}}],["``box",{"1":{"209":1}}],["``box``",{"1":{"10":1,"32":1,"195":1,"198":1,"362":1,"368":1}}],["``bottom``",{"1":{"202":1}}],["``balljoint``",{"1":{"179":1}}],["``build123d",{"1":{"187":1}}],["``buildsketch",{"1":{"169":1}}],["``buildsketch```",{"1":{"201":1}}],["``buildsketch``",{"1":{"37":2,"39":1,"42":4,"190":2,"191":1,"262":1,"263":2,"270":4,"377":2}}],["``buildpart``",{"1":{"32":2,"189":1,"190":1,"191":1,"201":1,"202":1,"270":5,"370":2,"377":2}}],["``buildline``",{"1":{"23":2,"31":1,"191":1,"263":4,"270":3}}],["``b",{"1":{"10":1}}],["``bezier``",{"1":{"10":1}}],["``tangency``",{"1":{"331":1}}],["``tangency",{"1":{"312":4,"331":6}}],["``tangent=l2",{"1":{"30":1}}],["``tangent",{"0":{"30":1},"1":{"304":1}}],["``tangentarc``",{"1":{"10":1}}],["``true``",{"1":{"259":1}}],["``transform``",{"1":{"217":1}}],["``trapezoid``",{"1":{"10":1}}],["``tuple",{"1":{"124":1}}],["``tuple``",{"1":{"20":1}}],["``to",{"1":{"181":1,"184":1,"352":1}}],["``topo",{"1":{"276":1}}],["``top``",{"1":{"202":1}}],["``topf``",{"1":{"169":4}}],["``top",{"1":{"53":1}}],["``torus``",{"1":{"10":1}}],["``tshape``",{"1":{"19":1}}],["``threepointarc``",{"1":{"10":1,"23":1,"28":3}}],["``text``",{"1":{"10":1}}],["``sagitta",{"1":{"315":3}}],["``sagitta``",{"1":{"315":2}}],["``sagittaarc``",{"1":{"10":1}}],["``sympy``",{"1":{"295":1}}],["``symbol``",{"1":{"181":1}}],["``selector``",{"1":{"311":2,"312":1,"315":1,"319":1,"326":1,"331":1,"333":2}}],["``select",{"1":{"272":12,"273":1}}],["``self``",{"1":{"184":1,"347":1}}],["``sortby``",{"1":{"271":2}}],["``sortby",{"1":{"268":1}}],["``sort",{"1":{"262":1,"368":1,"369":1,"384":1,"394":1}}],["``solid",{"1":{"124":1}}],["``solid``",{"1":{"19":1,"190":2,"270":1}}],["``shapelist``",{"1":{"267":1,"268":5,"269":4,"271":6,"272":1,"275":3}}],["``shape``",{"1":{"186":1,"271":1}}],["``show``",{"1":{"184":1,"347":1}}],["``show",{"1":{"178":5,"347":1,"369":3,"379":2}}],["``snapshot",{"1":{"143":1}}],["``sketch",{"1":{"39":1,"195":1,"262":1}}],["``sketch``",{"1":{"10":3,"11":1,"37":1,"39":1,"168":1,"186":1,"188":1,"262":1}}],["``subtract``",{"1":{"37":1,"223":1}}],["``step``",{"1":{"36":1}}],["``stl``",{"1":{"36":1}}],["``start=l2",{"1":{"30":1}}],["``sweep``",{"1":{"25":2,"31":1}}],["``siblings``",{"1":{"20":1}}],["``split``",{"1":{"157":1}}],["``spline``",{"1":{"10":1}}],["``sphere``",{"1":{"10":1,"198":1}}],["``slotoverall``",{"1":{"10":1}}],["``slotcentertocenter``",{"1":{"10":1}}],["``slotcenterpoint``",{"1":{"10":1}}],["``slotarc``",{"1":{"10":1}}],["``s0",{"1":{"10":3}}],["``s",{"1":{"10":1}}],["``s``",{"1":{"10":1}}],["``perimeter``",{"1":{"372":1,"373":1}}],["``pending",{"1":{"190":2}}],["``plan``",{"1":{"371":1}}],["``plane``",{"1":{"31":1,"39":1,"154":1,"188":3,"201":1,"262":1,"271":2}}],["``plane",{"1":{"9":2,"31":4,"32":1,"39":4,"42":1,"124":1,"144":2,"149":1,"150":1,"157":1,"188":7,"202":4,"209":2,"210":1,"254":1,"262":4,"263":6,"406":2,"414":1,"417":3,"420":1}}],["``pip",{"1":{"367":1,"374":2}}],["``pipes``",{"1":{"199":1}}],["``pillow",{"1":{"190":1}}],["``pts``",{"1":{"165":1}}],["``python``",{"1":{"128":1}}],["``python3``",{"1":{"128":1}}],["``primitives``",{"1":{"404":1,"408":1,"410":1}}],["``print",{"1":{"190":1}}],["``private``",{"1":{"37":1,"223":1}}],["``project",{"1":{"110":1}}],["``pos",{"1":{"173":1,"188":1,"209":2,"210":1}}],["``position``",{"1":{"180":1,"182":1,"204":1}}],["``position",{"0":{"28":1}}],["``polarlocations``",{"1":{"198":1}}],["``polarline``",{"1":{"10":1}}],["``polyline``",{"1":{"10":1}}],["``polygon``",{"1":{"10":1}}],["``path``",{"1":{"20":1}}],["``pack``",{"1":{"15":1}}],["``part",{"1":{"195":1,"250":1}}],["``partcad``",{"1":{"98":1,"100":1}}],["``part``",{"1":{"10":3,"11":1,"32":1,"186":1,"188":1,"192":1}}],["``parent``",{"1":{"12":1,"14":2,"20":1}}],["``paraboliccenterarc``",{"1":{"10":1}}],["``p0",{"1":{"10":3}}],["``p",{"1":{"10":1}}],["``p``",{"1":{"10":1}}],["``curvature",{"1":{"304":1}}],["``curve",{"1":{"148":1,"172":1}}],["``curve``",{"1":{"10":3,"11":1,"186":1,"188":1}}],["``c2``",{"1":{"304":1}}],["``club``",{"1":{"222":2}}],["``clean``",{"1":{"11":3}}],["``center",{"0":{"324":1,"328":1}}],["``center``",{"0":{"327":1},"1":{"221":1}}],["``centerarc``",{"1":{"10":1}}],["``cylinder",{"1":{"189":1}}],["``cylinder``",{"1":{"10":1,"32":1,"189":1,"198":1,"369":1}}],["``cylindricaljoint``",{"1":{"180":1}}],["``circle",{"1":{"37":2}}],["``circle``",{"1":{"10":1,"37":1,"195":1,"376":2,"391":1}}],["``children``",{"1":{"12":1,"14":2,"20":4}}],["``code",{"1":{"406":1,"408":1,"410":1,"414":1}}],["``connect",{"1":{"179":1,"180":1,"182":1,"347":1}}],["``cone``",{"1":{"10":1}}],["``compound``",{"1":{"21":1,"187":1,"191":1,"192":1}}],["``copy",{"1":{"19":4}}],["``copy``",{"1":{"19":1}}],["``countersinkhole``",{"1":{"10":1}}],["``counterborehole``",{"1":{"10":1}}],["``c0",{"1":{"10":3}}],["``c``",{"1":{"10":1,"294":2,"295":1}}],["``c",{"1":{"9":2,"10":1,"299":2}}],["``lid``",{"1":{"364":1}}],["``list``",{"1":{"274":1,"275":1,"383":1}}],["``linearjoint``",{"1":{"182":1}}],["``line1",{"1":{"172":1}}],["``line",{"1":{"31":1}}],["``line``",{"1":{"23":2,"28":1}}],["``l4``",{"1":{"420":1}}],["``l4",{"1":{"148":1}}],["``lambda",{"1":{"271":2}}],["``last``",{"1":{"272":1}}],["``last",{"1":{"143":1}}],["``label``",{"1":{"13":1,"184":1}}],["``loc",{"1":{"209":2}}],["``loc``",{"1":{"209":1}}],["``location``",{"1":{"144":1,"188":3,"201":3,"204":1}}],["``locations``",{"1":{"40":1,"189":1,"198":4,"201":1,"218":1,"224":1,"238":1,"368":2}}],["``location",{"1":{"9":2}}],["``loft``",{"1":{"190":1}}],["``look",{"1":{"110":2}}],["``log",{"1":{"51":1}}],["``l3``",{"1":{"30":2,"147":1,"420":1}}],["``leftovers``",{"1":{"405":2,"408":1,"410":1,"412":1}}],["``lego``",{"1":{"370":1}}],["``lego",{"1":{"368":1,"369":2}}],["``leaf``",{"1":{"362":1}}],["``leaf",{"1":{"352":1}}],["``leaves``",{"1":{"20":1}}],["``length``",{"1":{"28":1}}],["``l2``",{"1":{"28":1,"30":3,"331":1}}],["``l",{"1":{"9":1,"299":1}}],["``l1``",{"1":{"28":3,"298":1,"420":1}}],["``l1",{"1":{"9":1,"28":4,"31":1,"298":1,"317":1,"332":1}}],["``z``",{"1":{"9":1,"208":1,"209":3,"368":1}}],["``",{"0":{"255":1},"1":{"9":7,"10":13,"15":1,"19":6,"28":11,"30":2,"31":20,"36":1,"91":3,"124":3,"129":1,"143":2,"144":4,"148":2,"149":1,"150":1,"151":1,"153":3,"156":2,"162":1,"167":1,"169":1,"172":1,"174":1,"177":5,"178":8,"184":2,"185":6,"187":2,"188":11,"189":8,"190":2,"194":6,"201":2,"204":4,"209":9,"222":4,"224":2,"241":1,"255":2,"262":1,"293":2,"299":3,"304":1,"308":8,"317":1,"363":1,"367":1,"368":2,"369":5,"378":1,"379":2,"382":1,"383":1,"384":2,"390":1,"391":1,"392":1,"393":1,"394":2,"406":1,"417":3,"420":2}}],["`filtered`",{"1":{"240":1}}],["`for`",{"1":{"7":1}}],["`faces",{"1":{"4":1}}],["`with`",{"1":{"7":1,"211":1}}],["`list`",{"1":{"242":1}}],["`literal`",{"1":{"1":1}}],["`launchplatform",{"1":{"90":1,"91":1}}],["`lambda`",{"1":{"7":1}}],["`logo",{"1":{"67":1}}],["`low",{"1":{"59":1}}],["`locations`",{"1":{"64":1}}],["`location",{"1":{"40":1,"188":1}}],["`l",{"1":{"9":3}}],["`l6",{"1":{"5":1}}],["`l5",{"1":{"5":1}}],["`exportsvg`",{"1":{"245":1}}],["`extensionline`",{"1":{"245":1}}],["`external`",{"1":{"127":1}}],["`examples",{"1":{"73":1,"238":1}}],["`epub",{"1":{"124":1}}],["`edges",{"1":{"4":1}}],["`enum`",{"1":{"1":1}}],["`",{"1":{"4":4,"5":4,"9":21,"10":24,"147":4,"188":6,"194":2,"201":2,"241":7,"420":1}}],["`vertices",{"1":{"4":1}}],["r06",{"1":{"417":1}}],["r05",{"1":{"417":1}}],["r00",{"1":{"417":1}}],["r5",{"1":{"62":2,"286":2}}],["r40",{"1":{"290":2}}],["r4",{"1":{"62":2,"286":2}}],["r3",{"1":{"62":2,"286":2}}],["r2",{"1":{"62":2,"286":2}}],["r17",{"1":{"417":1}}],["r12",{"1":{"417":1}}],["r11",{"1":{"417":1}}],["r1",{"1":{"62":2,"286":10}}],["ridges",{"0":{"375":1},"1":{"374":2,"375":2}}],["ridge",{"1":{"367":2,"368":2,"369":2,"375":2,"376":2,"377":2}}],["risk",{"1":{"139":1}}],["rich",{"1":{"108":1,"111":1,"117":1,"124":1}}],["rigid",{"0":{"184":1},"1":{"183":1,"184":2}}],["rigidjoint`",{"1":{"181":6,"182":1,"184":1,"351":2,"352":1,"353":2,"357":1,"359":1,"360":1}}],["rigidjoint",{"1":{"77":5,"80":2,"179":2,"180":1,"182":2,"183":1,"184":5,"350":2,"352":1,"353":2,"357":1,"359":1,"360":1},"2":{"77":1,"80":1,"179":1,"180":1,"181":1,"182":1,"183":1,"184":1,"350":1,"351":1,"352":1,"353":1,"357":1,"359":1,"360":1}}],["right",{"1":{"49":3,"53":1,"221":2,"243":1,"246":2,"257":2,"262":2,"272":1,"278":3,"281":1,"290":2,"304":1,"314":1,"320":1,"331":1,"339":1,"345":1,"420":9},"2":{"246":1}}],["rightarrow",{"1":{"9":4,"10":3}}],["rib",{"1":{"70":4,"280":2}}],["ribs",{"1":{"70":10,"368":1,"369":1,"375":1,"376":1,"377":1}}],["ribbon",{"1":{"61":1}}],["rings",{"1":{"276":10}}],["ring",{"1":{"69":2,"276":3}}],["rshift",{"1":{"58":1}}],["rst",{"1":{"0":5,"47":3,"126":22,"132":1,"205":1,"228":1,"259":1,"421":2,"422":10}}],["rmul",{"1":{"55":1,"58":1}}],["rubric",{"1":{"421":1}}],["rule>`",{"1":{"339":1}}],["rule",{"1":{"31":1,"339":1}}],["rules",{"1":{"31":1,"310":1}}],["running",{"1":{"189":1,"194":3,"200":1,"409":1,"417":1}}],["runs",{"1":{"104":1,"140":2,"340":1}}],["runtimes",{"1":{"66":1}}],["run",{"1":{"19":1,"90":1,"91":1,"95":1,"134":2,"408":1,"413":1},"2":{"19":1}}],["r^3",{"1":{"9":1}}],["rbrace`",{"1":{"9":1,"10":3}}],["rbrace",{"1":{"9":1}}],["rad",{"1":{"159":2,"168":4,"171":6,"190":2,"322":1,"328":1}}],["radians",{"1":{"279":4,"295":4},"2":{"279":1,"295":1}}],["radially",{"1":{"146":1}}],["radial",{"1":{"61":1}}],["radii",{"1":{"61":5,"218":3,"220":4,"224":1,"286":1,"404":1},"2":{"61":1}}],["radius",{"0":{"328":1,"392":1},"1":{"30":3,"31":1,"34":3,"37":1,"40":1,"49":1,"59":5,"65":20,"69":9,"76":2,"78":6,"124":3,"179":5,"199":3,"218":6,"219":4,"220":3,"230":1,"238":3,"241":1,"279":3,"280":3,"287":1,"295":3,"312":1,"315":2,"322":1,"324":1,"328":1,"329":2,"336":2,"340":4,"341":1,"344":4,"345":1,"346":4,"389":2,"392":2,"393":1,"394":1,"414":1},"2":{"30":1,"322":1,"344":1}}],["radius=4",{"1":{"385":1,"388":1,"389":1}}],["radius=support",{"1":{"368":2,"369":2,"376":2,"377":2}}],["radius=pip",{"1":{"369":1}}],["radius=pin",{"1":{"350":2}}],["radius=playingcard",{"1":{"76":1}}],["radius=6",{"1":{"331":1}}],["radius=8",{"1":{"289":1,"290":1,"331":1}}],["radius=7",{"1":{"278":2,"385":1,"388":1,"389":1}}],["radius=hole",{"1":{"256":1}}],["radius=hookd",{"1":{"74":2}}],["radius=f",{"1":{"190":1}}],["radius=fillet",{"1":{"7":1,"34":1,"69":2,"78":2,"124":1}}],["radius=w",{"1":{"163":2}}],["radius=width",{"1":{"143":2,"144":2,"162":4,"170":2}}],["radius=rad",{"1":{"159":6}}],["radius=radius",{"1":{"37":1}}],["radius=length",{"1":{"149":1,"152":4}}],["radius=barrel",{"1":{"350":1}}],["radius=bend",{"1":{"340":2,"341":1,"346":1}}],["radius=b",{"1":{"146":4,"151":1}}],["radius=a",{"1":{"146":4,"147":4,"150":2}}],["radius=arcd",{"1":{"74":4}}],["radius=2",{"1":{"143":1,"144":1,"146":4,"175":2,"182":1}}],["radius=midd",{"1":{"74":2}}],["radius=maind",{"1":{"74":2}}],["radius=10",{"1":{"381":1,"382":1,"385":1,"388":1,"389":1}}],["radius=19",{"1":{"299":1}}],["radius=15",{"1":{"289":1}}],["radius=1",{"1":{"70":2,"332":1,"389":1}}],["radius=exchanger",{"1":{"69":2}}],["radius=thickness",{"1":{"71":1}}],["radius=tube",{"1":{"69":4}}],["radius=true",{"1":{"66":1}}],["radius=card",{"1":{"76":1}}],["radius=clock",{"1":{"65":2}}],["radius=center",{"1":{"32":1,"76":1,"153":1}}],["radius=3",{"1":{"42":1}}],["radius=",{"1":{"34":1,"69":2,"71":1,"78":2,"124":1,"170":2,"322":1,"328":1}}],["radius=0",{"1":{"30":1,"31":1,"68":2,"81":4,"199":1,"314":1}}],["radius=50",{"1":{"146":2}}],["radius=5",{"1":{"11":1,"70":4,"144":3,"177":2,"299":1}}],["radiusarc`",{"1":{"49":1,"170":2,"218":1}}],["radiusarc",{"1":{"25":1,"62":2,"81":4,"170":4,"225":1,"279":2,"350":2},"2":{"10":1,"25":1,"49":1,"62":1,"81":1,"170":1,"218":1,"225":1,"279":1,"350":1}}],["rather",{"1":{"139":1,"268":1,"276":1,"302":1,"304":1,"324":1,"421":2}}],["rationale",{"1":{"188":1}}],["ratio",{"1":{"75":1}}],["rapid",{"1":{"121":1}}],["raw",{"1":{"104":1,"124":1,"179":1,"369":1,"396":1,"420":1}}],["random",{"1":{"262":1}}],["randomly",{"1":{"262":1}}],["ran",{"1":{"169":1}}],["rank=",{"1":{"76":5}}],["ranks",{"1":{"76":2}}],["rank",{"1":{"76":13},"2":{"76":1}}],["ranges",{"1":{"353":2}}],["range=",{"1":{"179":1,"182":1,"353":1,"354":2}}],["range=360",{"1":{"146":2}}],["range",{"1":{"60":1,"61":1,"62":4,"64":4,"65":1,"68":2,"72":2,"81":1,"101":1,"140":1,"235":1,"307":1,"353":1,"354":1,"363":1}}],["raised",{"1":{"169":2,"306":1,"420":1}}],["raise",{"1":{"75":1,"182":1}}],["rails",{"1":{"61":1,"83":1},"2":{"61":1}}],["rail",{"1":{"6":1,"83":1}}],["row",{"1":{"368":1,"369":1,"376":1,"377":1}}],["role",{"1":{"206":1}}],["rod",{"1":{"179":7}}],["roughly",{"1":{"152":1}}],["roundabout",{"1":{"102":1}}],["rounded",{"1":{"102":1,"219":2,"344":2,"345":1,"404":1}}],["rounding",{"1":{"81":2}}],["round`",{"1":{"49":1,"238":1}}],["round",{"1":{"42":1,"49":1,"78":1,"177":1,"182":1,"238":1,"239":1,"280":2,"414":1},"2":{"49":1,"238":1,"239":1,"280":1},"3":{"4":1,"7":1,"10":1,"34":1,"42":1,"49":1,"51":1,"63":1,"65":1,"68":1,"69":1,"70":1,"71":1,"76":1,"78":1,"80":1,"81":1,"124":1,"135":1,"143":1,"144":1,"149":1,"151":1,"163":1,"177":1,"179":1,"182":1,"190":1,"199":1,"218":1,"225":1,"230":1,"232":1,"233":1,"238":1,"239":1,"250":1,"253":1,"256":1,"272":1,"273":1,"278":1,"281":1,"282":1,"284":1,"286":1,"287":1,"289":1,"290":1,"314":1,"336":1,"340":1,"341":1,"344":1,"346":1,"350":1,"389":1,"404":1,"414":1,"417":1}}],["royalty",{"1":{"117":1}}],["robots",{"1":{"100":1}}],["robotics",{"1":{"100":1}}],["robot",{"1":{"100":1}}],["robust",{"0":{"402":1},"1":{"30":1,"135":1,"230":1,"233":1,"310":2,"319":1,"378":1,"421":1}}],["robustness",{"1":{"27":1,"236":2}}],["road",{"1":{"60":3}}],["room",{"1":{"70":2}}],["roof",{"1":{"59":8}}],["root``",{"1":{"20":1}}],["root",{"0":{"398":1,"399":1,"401":1},"1":{"20":3,"395":7,"396":2,"397":1,"399":2,"400":3,"401":2},"2":{"20":2}}],["rot``",{"1":{"188":1}}],["rot`",{"1":{"173":1}}],["rot",{"1":{"55":1,"60":1,"62":2,"67":1,"75":1,"76":5,"81":3,"156":1,"166":1,"185":1,"188":2,"209":6,"278":1},"2":{"55":1,"60":1,"62":1,"67":1,"75":1,"76":1,"81":1,"156":1,"166":1,"173":1,"185":1,"188":1,"209":1,"278":1}}],["rotating",{"0":{"201":1},"1":{"81":1,"262":1}}],["rotational",{"0":{"338":1},"1":{"338":1}}],["rotation`",{"1":{"210":1}}],["rotations",{"1":{"179":1,"201":2}}],["rotationlike",{"1":{"75":2,"77":2,"179":1,"184":1}}],["rotation",{"0":{"217":1},"1":{"55":1,"75":2,"76":7,"77":3,"157":1,"188":1,"201":4,"204":1,"210":2,"217":1,"222":1,"338":2,"353":2,"354":1,"415":1},"2":{"55":1,"75":1,"77":1,"201":2,"210":1,"222":1,"353":1}}],["rotation=90",{"1":{"182":2,"281":1,"288":1}}],["rotation=0",{"1":{"170":2}}],["rotation=30",{"1":{"166":1,"167":2}}],["rotation=45",{"1":{"81":1,"202":1}}],["rotation=suit",{"1":{"76":1}}],["rotation=rotation",{"1":{"75":1,"76":5,"77":1,"222":1}}],["rotation=180",{"1":{"67":1,"76":2}}],["rotation=",{"1":{"4":1,"70":1,"77":1,"179":2,"199":1,"201":2,"350":1}}],["rotates",{"1":{"166":1,"179":1,"183":1,"235":1}}],["rotated`",{"1":{"156":1}}],["rotated",{"0":{"156":1},"1":{"156":3,"188":2,"202":1,"209":2,"210":1,"217":1,"243":1,"262":1,"287":1,"317":1},"2":{"156":1,"262":1,"287":1}}],["rotate=false",{"1":{"65":2}}],["rotate",{"1":{"42":1,"75":1,"77":1,"124":1,"156":1,"173":1,"180":1,"198":1,"209":3,"217":2,"230":1,"278":2,"317":1,"352":1,"396":1,"420":1},"2":{"217":1,"230":1,"278":1,"317":1}}],["r",{"1":{"3":2,"9":2,"11":4,"60":1,"66":3,"187":3}}],["rewritten",{"1":{"417":1}}],["rebuilding",{"1":{"415":1}}],["rebuild",{"1":{"408":1,"412":1,"413":1}}],["renowned",{"1":{"291":1}}],["rendered",{"1":{"135":1}}],["rendering",{"1":{"135":1}}],["render",{"1":{"77":1,"182":3,"184":1,"347":1},"2":{"184":1}}],["remainder",{"1":{"420":1}}],["remain",{"1":{"312":1,"378":1,"412":1}}],["remaining",{"1":{"295":1,"331":1}}],["remains",{"1":{"139":2}}],["remember",{"1":{"252":1,"275":1}}],["remote",{"1":{"141":2}}],["removing",{"1":{"81":2}}],["removed",{"1":{"375":1}}],["removes",{"1":{"194":1,"306":1,"345":1,"391":1}}],["remove",{"1":{"59":1,"192":1,"280":1,"286":1,"409":1}}],["reusing",{"1":{"421":1}}],["reusable",{"1":{"318":1}}],["reusability",{"1":{"139":1}}],["reused",{"1":{"272":3}}],["reuse",{"1":{"80":2,"402":1,"420":1}}],["regrouped",{"1":{"417":1}}],["regressions",{"1":{"134":1}}],["regression",{"1":{"134":1}}],["region",{"1":{"206":1,"408":1,"410":1,"413":2,"421":1}}],["regions",{"1":{"194":1,"405":1,"406":1,"410":2,"412":1}}],["regular",{"1":{"49":1,"75":1,"219":1}}],["regularpolygon`",{"1":{"49":1,"175":2,"219":1,"386":1}}],["regularpolygon",{"1":{"11":1,"66":1,"144":2,"150":2,"152":2,"159":6,"162":2,"166":6,"167":4,"168":2,"175":2,"219":1,"226":1,"385":1,"388":1,"389":1},"2":{"10":1,"11":1,"49":1,"66":1,"144":1,"150":1,"152":1,"159":1,"162":1,"166":1,"167":1,"168":1,"175":1,"219":1,"226":1,"385":1,"386":1,"388":1,"389":1}}],["retrieval",{"1":{"196":1}}],["retrieves",{"1":{"344":1,"345":2}}],["retrieve",{"1":{"189":1,"194":1,"198":1,"268":1}}],["retry",{"1":{"129":1}}],["retain",{"1":{"161":1}}],["returning",{"1":{"268":1}}],["returned",{"1":{"189":2,"312":1,"319":1,"377":1,"404":1,"408":1,"410":1}}],["returns",{"1":{"61":1,"147":1,"168":2,"177":1,"189":1,"243":1,"268":1,"272":2,"273":1,"306":1,"368":1,"410":1}}],["return",{"1":{"4":1,"62":4,"110":1,"131":1,"168":3,"208":2,"241":3,"242":1,"243":1,"262":1,"268":1,"269":1,"274":1,"330":1,"368":1,"384":1},"2":{"208":1}}],["re",{"1":{"128":1,"169":2,"184":1,"234":1,"263":1,"368":1,"382":1,"383":1,"389":1,"391":1}}],["redundant",{"1":{"412":1}}],["reducing",{"1":{"74":2,"134":2,"237":1,"303":1,"335":1}}],["reduced",{"1":{"408":1}}],["reduces",{"1":{"66":1,"236":1,"304":1}}],["reduce",{"1":{"19":1,"61":1,"139":1,"312":1,"315":1,"331":1,"409":1,"415":1}}],["redesign",{"1":{"122":1,"405":1,"408":1,"415":1}}],["red",{"1":{"62":6,"108":6,"109":1,"208":1,"420":1}}],["relax",{"1":{"333":1}}],["related",{"1":{"406":1,"414":1}}],["relate",{"1":{"310":1}}],["relative",{"0":{"208":1,"209":1},"1":{"57":1,"77":1,"144":2,"181":1,"183":1,"184":3,"188":7,"204":4,"209":7,"212":1,"213":2,"215":1,"216":1,"217":1,"221":1,"308":1,"312":2,"317":1,"329":1,"347":1,"358":1,"384":1}}],["relatively",{"1":{"2":1}}],["relationships",{"1":{"112":1,"133":1,"139":2,"204":1,"206":2,"236":1,"295":1,"302":1,"310":2}}],["relationship",{"0":{"308":1,"309":1},"1":{"10":1,"298":1,"306":1,"313":1,"317":1,"318":1}}],["reliable",{"1":{"138":1,"206":1,"415":1}}],["reliability",{"1":{"138":2}}],["relies",{"1":{"138":2,"230":1,"231":1,"234":1}}],["relying",{"1":{"302":1,"421":1}}],["rely",{"1":{"135":1}}],["reload",{"1":{"408":1,"416":1}}],["reloading",{"1":{"104":1}}],["relocated",{"1":{"188":1,"213":2,"217":1}}],["relocate",{"0":{"358":1},"1":{"49":2,"156":1,"358":1}}],["released",{"1":{"129":1,"134":1}}],["release",{"1":{"63":1}}],["reorienting",{"1":{"263":1}}],["reorient",{"1":{"39":1}}],["reoriented",{"1":{"39":2,"263":2}}],["review",{"1":{"415":1}}],["reveal",{"1":{"243":1,"408":1,"417":1}}],["revert",{"1":{"141":1}}],["reverse=true",{"1":{"63":1,"69":1,"282":1}}],["reversed",{"1":{"34":1,"202":1,"304":1,"354":1},"2":{"304":1}}],["reverse",{"1":{"49":2,"74":2,"184":1,"241":1},"2":{"20":1,"74":1}}],["reverse``",{"1":{"20":1}}],["rev",{"1":{"171":6}}],["revolute",{"0":{"183":1},"1":{"183":2}}],["revolutejoint",{"1":{"182":1,"183":1,"184":1,"350":1,"353":1},"2":{"180":1,"181":1,"182":1,"183":1,"350":1,"351":1,"353":1,"354":1,"363":1}}],["revolutejoint`",{"1":{"180":1,"181":2,"183":1,"351":1,"353":2,"354":1,"363":1}}],["revolutions",{"1":{"334":1}}],["revolution",{"1":{"49":1,"171":2,"229":1,"235":1,"241":1,"259":1}}],["revolving",{"1":{"78":1,"81":2,"236":1,"338":1,"342":1,"343":1,"421":1}}],["revolve`",{"1":{"38":1,"49":1,"147":1,"238":1,"250":1}}],["revolve",{"0":{"157":1},"1":{"34":1,"60":2,"71":2,"78":4,"81":2,"124":1,"157":4,"171":2,"179":2,"182":1,"239":1,"282":2,"290":1,"342":1},"2":{"34":1,"38":1,"49":1,"60":1,"71":1,"78":1,"81":1,"124":1,"147":1,"157":1,"171":1,"179":1,"182":1,"238":1,"239":1,"250":1,"282":1,"290":1}}],["revolved",{"0":{"342":1},"1":{"34":1,"78":2,"124":1,"342":2}}],["rear",{"1":{"80":2,"249":1}}],["realm",{"1":{"291":1}}],["realignment",{"1":{"230":1}}],["reality",{"1":{"135":1,"252":1}}],["realistic",{"1":{"60":1}}],["realtime",{"1":{"94":1}}],["real",{"1":{"78":1,"81":1,"92":1,"135":2,"337":1}}],["reasonably",{"1":{"411":1}}],["reasonable",{"1":{"255":1}}],["reason",{"1":{"255":1,"263":1}}],["reasons",{"1":{"25":1,"26":1,"133":1}}],["reassigned",{"1":{"20":1}}],["readily",{"1":{"258":1}}],["reading",{"1":{"133":1,"140":1}}],["readability",{"1":{"140":1,"230":1,"299":1}}],["readable",{"1":{"113":1,"124":2,"310":1}}],["ready",{"1":{"108":1,"141":1}}],["readthedocs",{"1":{"20":1,"83":1,"84":1,"97":2,"124":2,"178":1,"251":1}}],["read",{"1":{"10":1,"59":1,"109":1,"140":1,"276":1,"409":1},"2":{"59":1,"109":1,"276":1,"409":1}}],["requests",{"1":{"258":1}}],["requested",{"1":{"4":1,"51":3,"303":1}}],["requirements",{"1":{"134":1}}],["require",{"1":{"123":1,"138":2,"177":1,"369":1}}],["requires",{"1":{"34":1,"98":2,"134":1,"147":1,"172":1}}],["required",{"1":{"17":1,"42":1,"95":1,"199":1,"252":1,"258":1,"272":1,"277":1,"278":1,"356":1,"410":1},"2":{"199":1}}],["rest",{"1":{"255":1}}],["respect",{"1":{"202":1,"312":1,"331":1,"384":1}}],["respectively",{"1":{"5":1,"58":1,"177":1}}],["resolves",{"1":{"331":1}}],["resolve",{"1":{"310":1}}],["resolution",{"1":{"123":1,"230":2}}],["resources",{"1":{"19":1}}],["resemble",{"1":{"81":1}}],["result",{"0":{"247":1},"1":{"80":1,"102":1,"144":2,"189":1,"193":1,"194":1,"196":1,"202":1,"245":1,"248":1,"254":1,"257":1,"306":2,"310":1,"338":1,"373":1,"374":1,"377":1}}],["resulting",{"1":{"61":1,"65":1,"154":1,"178":2,"192":1,"299":1,"341":1,"398":1}}],["results",{"0":{"319":1,"407":1},"1":{"14":1,"17":1,"71":1,"99":1,"139":1,"167":1,"252":1,"311":1,"333":2,"344":1,"364":1,"421":1}}],["recreate",{"1":{"358":1}}],["recipes",{"0":{"320":1}}],["recent",{"1":{"129":1,"272":1}}],["recently",{"1":{"129":1,"143":2}}],["receive",{"1":{"129":1}}],["recessed",{"1":{"146":1},"3":{"10":1,"11":1,"32":1,"37":1,"49":1,"51":1,"60":1,"61":1,"63":1,"64":1,"65":1,"66":1,"73":1,"76":1,"84":1,"135":1,"143":1,"144":1,"146":1,"153":1,"156":1,"162":1,"179":1,"180":1,"182":1,"192":1,"220":1,"227":1,"240":1,"256":1,"258":1,"265":1,"278":1,"279":1,"280":1,"281":1,"283":1,"287":1,"289":1,"299":1,"336":1,"345":1,"346":1,"350":1,"354":1,"357":1,"359":1,"365":1,"385":1,"387":1,"388":1,"391":1,"414":1,"420":1}}],["reconstructed",{"1":{"415":1}}],["reconstruct",{"1":{"415":1}}],["reconstructing",{"0":{"415":1}}],["reconstruction",{"0":{"122":1,"410":1},"1":{"122":2,"408":1,"410":1,"411":1,"413":1,"415":1,"416":1,"422":1}}],["recognized",{"1":{"404":1,"408":1,"410":2}}],["recommend",{"1":{"235":1}}],["recommended",{"1":{"51":1,"128":1,"130":1,"157":1,"253":1,"422":1}}],["recovery",{"1":{"141":1}}],["record",{"1":{"68":1}}],["rectangular",{"0":{"142":1},"1":{"32":1,"102":1,"142":1,"153":1}}],["rectangles",{"1":{"102":1,"374":5,"410":1,"414":1,"417":1}}],["rectangle``",{"1":{"164":1}}],["rectangle`",{"1":{"49":1,"164":1,"219":1}}],["rectanglerounded`",{"1":{"49":1,"219":1}}],["rectanglerounded",{"1":{"34":1,"42":1,"77":1,"78":2,"80":4,"124":1,"226":1,"280":1,"281":1,"283":2},"2":{"34":1,"42":1,"49":1,"77":1,"78":1,"80":1,"124":1,"219":1,"226":1,"280":1,"281":1,"283":1}}],["rectangle",{"0":{"372":1},"1":{"3":1,"7":1,"11":2,"37":1,"60":1,"62":4,"64":2,"66":1,"68":2,"70":10,"76":2,"80":2,"81":2,"124":1,"147":2,"149":4,"151":3,"158":3,"164":2,"169":2,"171":2,"173":2,"175":2,"179":3,"182":2,"190":1,"193":1,"202":1,"208":2,"209":5,"219":4,"224":2,"226":1,"230":4,"243":1,"262":2,"270":2,"278":1,"281":1,"282":2,"283":1,"284":4,"286":1,"287":1,"288":3,"289":2,"290":1,"345":1,"350":2,"368":6,"369":6,"372":4,"373":4,"374":4,"375":6,"376":6,"377":6,"417":6},"2":{"3":1,"7":1,"10":1,"11":1,"37":1,"49":1,"60":1,"62":1,"64":1,"66":1,"68":1,"70":1,"76":1,"80":1,"81":1,"124":1,"147":1,"149":1,"151":1,"158":1,"164":1,"171":1,"173":1,"175":1,"179":1,"182":1,"190":1,"193":1,"202":1,"208":1,"209":1,"219":1,"224":1,"226":1,"230":1,"243":1,"262":1,"270":1,"278":1,"281":1,"282":1,"283":1,"284":1,"286":1,"287":1,"288":1,"289":1,"290":1,"350":1,"368":1,"369":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"417":1}}],["recursive",{"1":{"17":1}}],["report",{"1":{"406":1}}],["reports",{"1":{"259":1}}],["repositioning",{"1":{"184":1,"230":1}}],["repositories",{"1":{"97":1}}],["repository>`",{"1":{"100":1}}],["repository",{"0":{"100":1},"1":{"73":1,"100":2,"129":1,"141":2}}],["replicate",{"1":{"341":1}}],["repl",{"1":{"255":1}}],["replacing",{"1":{"59":1}}],["replace``",{"1":{"192":1}}],["replace",{"1":{"49":1,"51":1,"79":3,"192":2,"194":2,"223":1,"249":1,"266":12},"2":{"37":1,"192":2,"223":1}}],["replacement",{"1":{"7":1}}],["replaced",{"0":{"6":1},"1":{"1":1,"6":1,"54":1}}],["repetitive",{"1":{"139":1}}],["repetitively",{"1":{"7":1}}],["repeated",{"1":{"261":1,"404":2,"406":3,"411":1,"414":3,"416":1}}],["repeat",{"1":{"147":1},"3":{"9":1,"11":1,"19":1,"31":1,"34":1,"40":1,"42":1,"45":1,"49":1,"51":1,"60":1,"61":1,"63":1,"64":1,"65":1,"66":1,"67":1,"69":1,"70":1,"71":1,"76":1,"77":1,"78":1,"80":1,"124":1,"144":1,"146":1,"149":1,"152":1,"156":1,"157":1,"162":1,"166":1,"167":1,"168":1,"171":1,"173":1,"174":1,"175":1,"179":1,"182":1,"184":1,"185":1,"189":1,"198":1,"201":1,"204":1,"211":1,"218":1,"224":1,"238":1,"256":1,"262":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"286":1,"287":1,"288":1,"289":1,"345":1,"346":1,"350":1,"354":1,"357":1,"359":1,"368":1,"369":1,"374":1,"375":1,"376":1,"377":1,"414":1}}],["representations",{"1":{"135":1}}],["representation",{"0":{"135":1},"1":{"111":1,"112":2,"120":1,"123":1,"135":4,"421":1},"2":{"135":2}}],["representing",{"1":{"111":1,"113":1,"120":1,"206":2}}],["represents",{"1":{"65":1,"75":1,"81":1,"112":1,"121":1,"189":1,"194":1,"204":1,"206":5,"210":2,"246":1,"421":1}}],["represent",{"1":{"5":1,"30":1,"61":1,"112":1,"121":1,"135":2,"141":1,"202":1,"206":1,"304":1,"340":1,"417":1}}],["refining",{"0":{"232":1},"1":{"230":1}}],["refined",{"1":{"343":1,"344":1}}],["refine",{"1":{"179":1,"232":1,"269":1,"271":1,"277":1,"405":1}}],["refinement",{"1":{"4":1}}],["refactor",{"1":{"134":1}}],["refs",{"1":{"104":1}}],["reflecting",{"1":{"308":1}}],["reflect",{"3":{"26":1,"49":1,"60":1,"61":1,"62":1,"67":1,"69":1,"76":1,"80":1,"148":1,"149":1,"150":1,"163":1,"176":1,"222":1,"238":1,"239":1,"278":1,"280":1,"281":1,"286":1,"288":1,"289":1,"290":1,"308":1,"310":1,"340":1,"341":1,"346":1,"420":1}}],["ref",{"1":{"12":1,"40":1,"57":1,"73":22,"108":1,"122":1,"125":3,"127":1,"172":1,"174":1,"183":1,"184":1,"187":2,"188":1,"238":13,"261":1,"262":1,"264":4,"265":3,"266":6,"274":1,"277":3,"291":13,"367":1,"415":1}}],["referencing",{"1":{"133":1,"189":1,"191":1,"369":1}}],["reference``",{"1":{"183":1}}],["referenced",{"1":{"23":1,"32":1,"37":1,"238":1,"272":1,"274":1}}],["references",{"1":{"19":3,"28":1,"233":1,"276":1,"299":1}}],["reference",{"0":{"29":1,"35":1,"41":1,"43":1,"54":1,"225":1,"226":1,"227":1,"239":1,"241":1},"1":{"19":6,"34":1,"59":1,"60":1,"61":1,"62":2,"63":1,"64":2,"65":2,"66":1,"67":2,"68":2,"69":2,"70":2,"71":1,"72":2,"74":2,"75":1,"76":1,"77":1,"78":2,"80":1,"81":4,"124":1,"126":2,"195":1,"204":1,"206":1,"233":1,"255":1,"276":7,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"312":1,"329":1,"339":1,"371":1,"373":1,"412":1},"2":{"183":1}}],["referring",{"1":{"28":1,"378":1}}],["refers",{"1":{"19":1,"206":1,"243":1,"421":1}}],["refer",{"1":{"1":1,"369":1,"372":1,"378":1}}],["aerodynamic",{"1":{"421":1}}],["aesthetic",{"1":{"78":1}}],["azure",{"1":{"395":1,"401":1}}],["awkward",{"1":{"295":1}}],["away",{"0":{"236":1},"1":{"71":1,"140":1,"276":1}}],["aware",{"1":{"61":1}}],["a=30",{"1":{"295":1}}],["agreed",{"1":{"278":1}}],["against",{"1":{"267":1,"307":1,"376":1}}],["again",{"1":{"11":1,"147":2,"188":1,"359":1}}],["affected",{"1":{"218":1,"238":1}}],["afterward",{"1":{"307":1}}],["after",{"1":{"61":1,"69":4,"75":1,"129":1,"143":1,"189":2,"190":1,"212":1,"232":1,"259":1,"272":1,"276":1,"299":1,"319":1,"379":1}}],["auditing",{"1":{"141":2}}],["audited",{"1":{"138":1}}],["auto",{"1":{"124":1,"192":5,"396":1,"420":1},"2":{"192":1}}],["autodesk",{"1":{"113":1}}],["automethod",{"1":{"46":5}}],["automation",{"1":{"133":1,"139":1}}],["automatically",{"1":{"39":1,"133":3,"134":1,"139":1,"143":1,"158":1,"178":1,"181":1,"202":1,"339":1}}],["automated",{"0":{"133":1,"134":1},"1":{"133":6,"134":11,"139":1}}],["automate",{"1":{"31":1,"405":1}}],["autoclass",{"1":{"29":1,"35":1,"41":1,"44":11,"45":4,"55":11,"57":1,"58":15,"108":1,"114":1,"115":1,"179":1,"180":1,"182":1,"183":1,"184":1,"225":29,"226":19,"227":11}}],["autofunction",{"1":{"18":1,"56":5,"105":3,"106":4,"107":3,"122":1,"239":32}}],["axes",{"1":{"75":1,"77":1,"80":1,"179":1,"188":1,"202":1,"208":2,"209":1,"220":1,"221":1,"256":1,"340":1,"415":1}}],["axisplane",{"1":{"266":1}}],["axis`",{"1":{"49":7,"204":1,"241":1,"293":1,"306":1}}],["axisymmetric",{"3":{"34":1,"38":1,"49":1,"60":1,"71":1,"78":1,"81":1,"124":1,"147":1,"157":1,"171":1,"179":1,"182":1,"238":1,"239":1,"250":1,"282":1,"290":1,"342":1}}],["axis=axis",{"1":{"34":1,"78":2,"81":1,"124":1,"157":1,"171":2,"179":2,"182":2,"282":2,"290":1,"353":1,"354":1}}],["axis",{"1":{"6":1,"34":1,"42":1,"54":1,"55":1,"59":7,"60":3,"61":1,"63":2,"67":5,"69":1,"70":4,"76":4,"78":3,"80":15,"81":8,"110":1,"124":1,"143":2,"144":5,"146":1,"150":2,"151":4,"152":7,"154":2,"156":2,"157":2,"158":1,"160":1,"161":3,"162":2,"163":2,"169":2,"170":1,"177":5,"180":1,"182":11,"183":1,"188":2,"193":1,"208":5,"209":5,"217":2,"221":2,"235":1,"238":1,"241":17,"243":12,"246":3,"256":1,"262":6,"264":3,"265":3,"266":2,"275":1,"276":2,"278":11,"280":3,"281":3,"282":2,"284":5,"285":1,"286":1,"287":2,"289":6,"290":4,"299":2,"307":1,"317":1,"320":2,"325":1,"331":1,"338":2,"339":3,"341":1,"342":1,"344":10,"345":9,"346":4,"350":3,"351":1,"352":1,"353":5,"354":4,"357":1,"363":3,"368":4,"369":3,"382":2,"384":1,"385":1,"388":1,"389":2,"394":2,"395":4,"398":4},"2":{"34":1,"49":1,"55":1,"78":1,"124":1,"152":1,"183":1,"204":1,"241":1,"271":1,"289":1,"293":1,"306":1,"307":1,"324":1,"345":1,"353":1,"354":1,"395":1,"398":1}}],["ambiguous",{"1":{"330":1}}],["ambiguity",{"1":{"312":1,"331":1}}],["amount",{"1":{"144":3,"167":1,"340":1,"415":1},"2":{"373":1,"388":1}}],["amount=50",{"1":{"290":1}}],["amount=52",{"1":{"287":1}}],["amount=6",{"1":{"289":1}}],["amount=60",{"1":{"279":1}}],["amount=4",{"1":{"280":3}}],["amount=40",{"1":{"278":1}}],["amount=46",{"1":{"182":1}}],["amount=some",{"1":{"250":1}}],["amount=l",{"1":{"176":1}}],["amount=length",{"1":{"77":1,"149":1,"155":2,"350":1}}],["amount=n",{"1":{"163":1}}],["amount=h2",{"1":{"284":1}}],["amount=h1",{"1":{"284":2}}],["amount=height",{"1":{"238":2}}],["amount=h",{"1":{"163":1}}],["amount=offs",{"1":{"159":2}}],["amount=w1",{"1":{"284":2}}],["amount=width",{"1":{"154":1,"341":1,"346":1}}],["amount=wall",{"1":{"76":2}}],["amount=base",{"1":{"368":1,"369":1,"377":1}}],["amount=b",{"1":{"150":2}}],["amount=c",{"1":{"148":1,"166":1,"167":1,"168":1,"173":1,"174":1,"175":2,"224":1}}],["amount=7",{"1":{"80":1}}],["amount=13",{"1":{"289":1}}],["amount=18",{"1":{"283":1,"287":1}}],["amount=16",{"1":{"283":1,"288":1}}],["amount=15",{"1":{"281":1,"287":1}}],["amount=115",{"1":{"281":1}}],["amount=11",{"1":{"279":2}}],["amount=12",{"1":{"80":1}}],["amount=1",{"1":{"80":2,"159":1}}],["amount=10",{"1":{"4":1,"70":2,"80":4,"145":1,"165":1,"193":1,"230":1,"280":1,"289":1}}],["amount=25",{"1":{"287":1}}],["amount=23",{"1":{"283":1}}],["amount=20",{"1":{"182":1,"288":1}}],["amount=2",{"1":{"80":1,"164":2,"420":2}}],["amount=80",{"1":{"281":1}}],["amount=8",{"1":{"80":1,"287":1}}],["amount=deck",{"1":{"76":3}}],["amount=0",{"1":{"72":2,"81":1,"202":1,"314":1}}],["amount=thickness",{"1":{"71":1,"152":1,"162":1,"172":1,"190":2,"340":2,"341":1,"346":1}}],["amount=32",{"1":{"279":1}}],["amount=3",{"1":{"70":2,"285":2}}],["amount=30",{"1":{"42":1,"285":1,"288":1}}],["amount=plate",{"1":{"69":1}}],["amount=pcb",{"1":{"64":1}}],["amount=exchanger",{"1":{"69":1}}],["amount=fontht",{"1":{"169":2}}],["amount=font",{"1":{"67":2}}],["amount=a",{"1":{"63":1}}],["amount=a1",{"1":{"63":1}}],["amount=roof",{"1":{"59":1}}],["amount=",{"1":{"4":1,"34":1,"42":2,"59":1,"71":1,"76":5,"78":1,"80":1,"81":2,"124":1,"144":1,"151":1,"152":1,"156":1,"160":2,"161":1,"163":1,"169":2,"170":1,"182":5,"193":1,"278":1,"280":2,"281":1,"284":3,"286":1,"287":1,"289":1,"290":1,"345":2,"346":1,"350":1,"357":1,"388":1,"389":1}}],["american",{"1":{"119":1}}],["amplitude",{"1":{"62":8}}],["a9",{"1":{"49":1}}],["a8",{"1":{"49":1}}],["a7",{"1":{"49":1}}],["a6",{"1":{"49":1}}],["a5",{"1":{"49":1,"299":3}}],["a4",{"1":{"49":1,"243":2,"245":1}}],["a3",{"1":{"49":1}}],["a29",{"1":{"299":7}}],["a2",{"1":{"49":1}}],["a14",{"1":{"299":1}}],["a19",{"1":{"299":5}}],["a10",{"1":{"49":1}}],["a1",{"1":{"49":1,"63":1}}],["a0",{"1":{"49":1}}],["aims",{"1":{"111":1}}],["ai",{"1":{"92":1,"98":1}}],["airliner",{"1":{"102":1}}],["air",{"1":{"80":1}}],["airfoils",{"1":{"395":2,"396":1,"399":2},"2":{"396":1}}],["airfoilsizes",{"1":{"395":1}}],["airfoil",{"0":{"398":1,"399":1},"1":{"218":2,"225":1,"395":11,"396":1,"398":5,"399":7,"400":3},"2":{"49":1,"218":1,"225":1,"395":1,"399":1}}],["airfoil`",{"1":{"49":1,"218":1}}],["aided",{"1":{"112":2,"113":1,"119":1,"120":2,"121":1,"123":1}}],["aid",{"1":{"6":1,"52":1,"61":1,"74":1,"122":1,"202":1}}],["average",{"1":{"49":1}}],["available",{"1":{"40":2,"84":1,"90":1,"124":1,"127":1,"138":1,"140":1,"179":1,"181":1,"201":1,"233":2,"238":1,"240":1,"255":1,"258":1,"268":1,"272":1,"273":1,"421":1}}],["avoided",{"1":{"255":1,"378":1}}],["avoiding",{"1":{"42":1}}],["avoid",{"1":{"11":1,"167":1,"253":1,"259":1,"280":1,"296":1,"333":1,"378":1,"420":1}}],["apache",{"1":{"278":2}}],["app",{"1":{"102":1}}],["appear",{"1":{"404":2,"417":3}}],["appears",{"1":{"331":1,"372":1,"405":1,"417":3}}],["appearing",{"1":{"243":1}}],["appealing",{"1":{"65":1}}],["append",{"1":{"75":1,"77":2,"369":1,"395":2,"398":1,"400":1},"2":{"75":1,"77":1,"395":1,"398":1,"400":1}}],["apply",{"0":{"344":1},"1":{"110":1,"175":1,"194":1,"198":1,"233":1,"245":1,"344":1,"389":1,"415":1}}],["applying",{"1":{"65":1,"229":1,"250":1}}],["applicability",{"1":{"241":1,"270":1}}],["applicable",{"1":{"191":1,"238":1,"278":1,"340":1}}],["applications",{"1":{"111":1,"112":1,"113":1,"117":2,"120":1,"121":1,"123":2,"135":1,"204":1}}],["application",{"1":{"81":1,"255":2}}],["applied",{"1":{"39":1,"42":1,"189":1,"204":1,"230":1,"238":1,"341":1}}],["applies",{"1":{"31":1,"75":1,"77":1,"195":1,"210":2,"307":1,"340":1,"344":1}}],["approximated",{"1":{"230":1,"405":1}}],["approximate",{"1":{"121":1,"310":1,"415":1}}],["approximately",{"1":{"66":1}}],["approxoption",{"2":{"49":1}}],["approxoption`",{"1":{"49":1}}],["approaches",{"1":{"214":1,"229":1,"252":1}}],["approach",{"1":{"66":2,"189":1,"200":1,"211":1,"230":6,"231":1,"233":1,"234":1,"236":1,"237":1,"250":2,"254":1,"255":1,"276":1,"310":1,"334":1,"421":1}}],["appropriate",{"1":{"14":1,"63":1,"77":1,"191":1,"243":1,"340":1,"347":1}}],["apis",{"1":{"197":1,"201":1,"238":1,"329":1}}],["api",{"0":{"43":1,"54":1},"1":{"7":2,"24":1,"33":1,"38":1,"54":5,"108":1,"126":2,"191":2,"197":5,"222":1,"223":2,"233":1},"2":{"54":1}}],["abrupt",{"1":{"304":1}}],["ability",{"1":{"36":1,"112":1,"121":1,"130":1,"141":1,"258":1}}],["absolute",{"1":{"204":2,"212":1,"213":2,"215":1,"216":1}}],["absolutely",{"1":{"157":1,"263":1}}],["absorb",{"1":{"178":1}}],["abstracts",{"1":{"140":1}}],["abs",{"1":{"34":1,"55":1,"68":1,"69":2,"70":1,"72":1,"78":2,"81":1,"124":1,"278":2,"279":1,"280":1,"281":2,"282":3,"283":2,"284":2,"285":2,"286":2,"287":2,"288":2,"289":2,"290":2},"2":{"34":1,"68":1,"69":1,"70":1,"72":1,"78":1,"81":1,"124":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["aboard",{"1":{"233":1}}],["above",{"1":{"26":1,"36":1,"39":2,"71":1,"73":1,"81":1,"95":1,"98":1,"108":1,"110":1,"128":1,"184":1,"189":1,"190":1,"202":1,"206":1,"222":1,"243":1,"246":1,"263":1,"290":1,"299":2,"341":1,"354":1,"364":1},"2":{"246":1}}],["about=plane",{"1":{"26":1,"60":1,"69":1,"76":5,"80":1,"148":1,"149":4,"150":1,"176":1,"222":1,"278":3,"280":1,"281":2,"286":1,"288":2,"289":1,"290":2,"340":2,"341":2,"346":2,"420":1}}],["about",{"0":{"124":1},"1":{"19":2,"75":1,"77":1,"81":1,"113":1,"129":1,"142":1,"163":1,"204":1,"238":2,"308":1,"310":1,"340":1,"352":1}}],["abelian",{"1":{"10":2}}],["able",{"1":{"5":1,"28":1,"42":1,"162":1,"202":1}}],["a`",{"1":{"10":1}}],["at=",{"1":{"67":1,"243":1}}],["at`",{"1":{"49":3,"147":2,"184":1}}],["at``",{"0":{"28":1,"30":1},"1":{"110":1}}],["attempting",{"1":{"189":1}}],["attempt",{"1":{"157":1,"190":1,"280":1}}],["attaches",{"1":{"350":1}}],["attached",{"1":{"20":1,"184":1,"325":1,"357":1,"363":1}}],["attachment``",{"1":{"362":1}}],["attachment",{"1":{"345":1,"347":2,"350":1,"352":1,"353":1,"357":1,"359":1,"362":1,"364":1},"2":{"362":1}}],["attach",{"1":{"80":1,"351":1,"354":1,"356":1,"357":1}}],["attribution",{"1":{"59":1}}],["attribute",{"1":{"20":3}}],["attributes",{"1":{"12":1,"14":2,"20":1,"27":1,"108":1,"190":1,"194":1}}],["at",{"1":{"5":1,"9":2,"14":11,"23":1,"24":1,"28":3,"30":6,"33":1,"34":1,"38":1,"39":1,"42":2,"61":13,"62":2,"65":1,"75":1,"80":1,"110":1,"131":8,"140":1,"147":1,"173":1,"174":2,"184":6,"185":1,"187":1,"188":3,"189":1,"194":2,"198":2,"200":1,"201":2,"202":1,"206":31,"208":1,"223":1,"246":1,"257":2,"259":1,"267":1,"278":3,"289":2,"298":1,"303":2,"304":1,"306":1,"308":3,"310":1,"313":2,"317":2,"329":1,"332":1,"339":3,"340":1,"344":1,"345":3,"367":1,"368":1,"369":1,"376":1,"388":1,"400":1,"404":1,"421":1},"2":{"28":1,"30":1,"42":1,"49":3,"61":2,"110":1,"147":2,"184":1,"198":1,"201":1,"267":1,"289":2,"317":1}}],["adhere",{"1":{"339":1}}],["adjoining",{"1":{"420":1}}],["adjacent",{"1":{"276":1,"402":1,"421":2}}],["adjacency",{"1":{"276":1}}],["adjusts",{"1":{"303":1}}],["adjustment",{"1":{"258":1}}],["adjustments",{"1":{"230":2}}],["adjust",{"1":{"215":1,"216":1,"249":1,"337":1}}],["adjusted",{"1":{"102":1,"336":1}}],["adapt",{"1":{"234":1}}],["adaptable",{"1":{"230":1}}],["adopting",{"1":{"189":1}}],["adoption",{"1":{"117":1}}],["advantage",{"1":{"135":1}}],["advantages",{"0":{"132":1},"1":{"132":1,"135":2,"140":1,"141":1,"230":1,"236":1}}],["advanced",{"0":{"0":1},"1":{"111":1,"112":1,"126":1,"141":1,"232":1,"233":2,"235":1,"403":1,"418":1,"421":2}}],["addresses",{"1":{"310":1}}],["additive",{"1":{"111":1,"342":1}}],["additional",{"1":{"189":1,"233":1,"291":1,"420":1}}],["additionally",{"1":{"144":1,"148":1,"339":1,"341":1}}],["addition",{"1":{"28":1,"76":1,"123":1,"147":1,"194":1,"304":1,"343":1},"2":{"147":1}}],["adding",{"0":{"127":1,"189":1,"368":1,"369":1},"1":{"69":1,"164":1,"167":1,"189":1,"190":1,"199":1,"200":1,"230":1,"232":1,"296":1}}],["addhandler",{"1":{"51":1},"2":{"51":1}}],["add``",{"1":{"192":3}}],["add`",{"1":{"39":1,"49":5,"238":1}}],["adds",{"1":{"20":1,"61":1,"189":1,"194":1,"333":1}}],["add",{"0":{"351":1},"1":{"11":1,"14":1,"20":1,"26":1,"27":1,"34":1,"39":1,"49":3,"51":2,"55":1,"58":3,"59":1,"61":2,"63":1,"65":1,"67":11,"70":5,"71":1,"73":1,"75":2,"76":13,"77":4,"78":2,"80":2,"81":2,"108":5,"110":4,"124":1,"129":2,"143":1,"144":1,"149":1,"167":1,"168":2,"172":1,"178":2,"179":3,"182":2,"184":1,"189":2,"192":1,"194":1,"222":1,"238":3,"239":1,"243":9,"245":1,"249":1,"253":1,"276":1,"278":2,"287":1,"290":1,"299":2,"307":1,"310":1,"311":1,"331":2,"333":1,"345":1,"350":3,"352":1,"353":1,"354":1,"368":3,"369":3,"374":1,"375":1,"376":2,"377":2,"400":1,"420":6},"2":{"37":1,"39":1,"49":1,"59":1,"65":1,"67":4,"76":3,"108":3,"110":2,"149":1,"167":1,"168":1,"179":1,"182":1,"192":1,"223":1,"238":1,"239":1,"243":2,"263":1,"276":1,"278":1,"287":1,"299":1,"307":1,"331":1,"350":1,"420":1}}],["added",{"1":{"4":1,"19":1,"68":4,"110":1,"123":1,"153":1,"158":1,"189":3,"192":1,"200":1,"319":1,"340":1,"343":1,"368":1,"376":1,"419":1}}],["achieving",{"1":{"260":1}}],["achieve",{"1":{"141":1,"232":1,"252":1}}],["acme",{"1":{"84":1}}],["ace",{"1":{"76":3}}],["across",{"1":{"61":2,"113":1,"117":1,"120":1,"139":1,"340":1,"341":1,"402":1,"421":2}}],["accordingly",{"1":{"267":1}}],["according",{"1":{"144":1}}],["accomplish",{"1":{"140":1}}],["accurate",{"1":{"135":1}}],["accurately",{"1":{"121":1,"204":1,"344":1}}],["accuracy",{"1":{"22":1,"346":1}}],["accepted",{"1":{"293":1}}],["accept",{"1":{"31":1,"201":2,"221":1}}],["accepts",{"1":{"31":1,"42":1,"144":1,"199":1}}],["accessed",{"1":{"147":1,"194":1,"268":1}}],["accessing",{"1":{"80":1}}],["accessibly",{"1":{"74":1}}],["accessible",{"1":{"39":1,"140":1,"269":1}}],["access",{"1":{"4":1,"191":1,"193":1,"196":1,"268":1,"270":2,"369":1}}],["act",{"1":{"397":1}}],["acts",{"1":{"206":1,"255":1}}],["activation",{"1":{"70":2}}],["active",{"1":{"3":1,"140":1,"189":1,"198":1,"319":1}}],["action",{"1":{"53":1}}],["actual",{"1":{"19":1}}],["arbitrarily",{"1":{"299":1}}],["arbitrary",{"1":{"40":1}}],["arise",{"1":{"258":1,"259":1}}],["arithmetics`",{"1":{"188":1}}],["arithmetic",{"0":{"9":1,"10":1,"187":1,"188":1,"207":1},"1":{"0":1,"185":1,"186":2}}],["argument",{"1":{"199":1,"257":1,"306":1,"312":3,"319":1}}],["args",{"1":{"75":1,"76":1,"77":2,"243":1,"350":1}}],["artificial",{"1":{"140":1}}],["artifact``",{"1":{"91":1}}],["artifacts",{"1":{"90":2}}],["art",{"1":{"72":14}}],["around",{"1":{"60":1,"61":1,"64":1,"71":1,"78":1,"81":1,"98":1,"129":1,"179":1,"180":1,"183":1,"187":1,"188":1,"209":2,"217":1,"235":1,"255":1,"299":2,"338":1,"342":1,"350":1,"353":1,"354":1,"417":1,"419":1,"420":2}}],["arrive",{"1":{"98":1}}],["arrowhead",{"1":{"226":1},"2":{"49":1,"219":1,"226":1}}],["arrowhead`",{"1":{"49":1,"219":1}}],["arrow",{"1":{"53":1,"67":6,"219":4,"226":1},"2":{"49":1,"219":1,"226":1}}],["arrow`",{"1":{"49":1,"219":1}}],["arranging",{"1":{"345":1}}],["arrange",{"1":{"108":1,"211":2}}],["arranges",{"1":{"18":1}}],["arrangement",{"1":{"15":1}}],["arranged",{"1":{"12":1,"15":1,"21":1,"75":1,"181":1}}],["array",{"1":{"62":2,"420":1,"421":1},"2":{"62":1,"420":1,"421":1},"3":{"9":1,"11":1,"19":1,"31":1,"34":1,"40":1,"42":1,"45":1,"49":1,"51":1,"60":1,"61":1,"63":1,"64":1,"65":1,"66":1,"67":1,"69":1,"70":1,"71":1,"76":1,"77":1,"78":1,"80":1,"124":1,"144":1,"146":1,"149":1,"152":1,"156":1,"157":1,"162":1,"166":1,"167":1,"168":1,"171":1,"173":1,"174":1,"175":1,"179":1,"182":1,"184":1,"185":1,"189":1,"198":1,"201":1,"204":1,"211":1,"218":1,"224":1,"238":1,"256":1,"262":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"286":1,"287":1,"288":1,"289":1,"345":1,"346":1,"350":1,"354":1,"357":1,"359":1,"368":1,"369":1,"374":1,"375":1,"376":1,"377":1,"414":1}}],["archs",{"1":{"420":1}}],["architecture",{"1":{"124":1}}],["architectural",{"1":{"113":1}}],["arc=180",{"1":{"171":2}}],["arc=ex35",{"1":{"170":4}}],["arcd",{"1":{"74":4}}],["arcs",{"0":{"172":1},"1":{"65":1,"113":1,"172":1,"218":3,"253":1,"292":2,"296":2,"299":1,"307":1,"310":1,"311":6,"315":1,"319":2,"322":2,"324":2,"326":2,"327":2,"328":2,"340":1}}],["arcarctangentline",{"1":{"225":1},"2":{"49":1,"218":1,"225":1}}],["arcarctangentline`",{"1":{"49":1,"218":1}}],["arcarctangentarc",{"1":{"225":3},"2":{"49":1,"218":1,"225":1}}],["arcarctangentarc`",{"1":{"49":1,"218":1}}],["arc",{"1":{"28":4,"30":6,"31":1,"49":2,"61":33,"71":3,"74":6,"80":2,"147":4,"170":2,"218":34,"219":2,"220":1,"279":3,"280":6,"289":3,"290":1,"293":1,"295":3,"299":3,"307":3,"315":1,"322":1,"326":1,"332":2,"420":1},"2":{"30":1,"61":1,"218":1,"279":1,"295":1}}],["aren",{"1":{"182":1}}],["are",{"0":{"20":1},"1":{"5":1,"10":2,"11":1,"12":1,"13":1,"15":2,"17":1,"19":1,"20":2,"22":1,"23":1,"24":1,"25":2,"26":1,"28":1,"30":1,"31":4,"32":1,"33":1,"34":2,"36":3,"37":3,"38":1,"40":3,"42":1,"43":1,"48":3,"50":1,"52":1,"53":1,"55":2,"56":1,"57":1,"58":1,"61":5,"65":1,"66":1,"69":2,"71":1,"74":2,"75":6,"76":1,"77":2,"78":2,"81":1,"97":1,"98":1,"102":2,"108":2,"109":1,"110":2,"112":1,"118":1,"119":2,"121":2,"123":2,"128":1,"129":1,"133":3,"134":3,"135":4,"138":2,"139":3,"140":2,"141":5,"144":2,"146":2,"147":1,"152":3,"153":2,"155":1,"156":1,"158":1,"162":1,"163":1,"166":1,"167":1,"174":1,"178":4,"179":2,"181":2,"182":1,"183":1,"184":3,"185":1,"187":1,"188":3,"189":1,"191":1,"197":1,"198":6,"201":2,"202":4,"204":2,"206":6,"208":1,"209":2,"211":4,"214":1,"218":1,"221":1,"223":1,"224":3,"230":2,"234":1,"236":1,"238":5,"241":2,"242":1,"245":1,"250":3,"253":1,"254":2,"255":5,"257":2,"259":1,"260":1,"261":1,"262":3,"267":1,"268":1,"272":3,"275":2,"276":3,"277":1,"279":2,"291":1,"295":4,"299":3,"303":1,"307":1,"310":1,"312":2,"319":1,"330":1,"331":2,"336":2,"338":2,"340":1,"344":3,"345":1,"350":2,"352":1,"354":1,"358":1,"359":2,"367":2,"368":3,"369":1,"371":2,"374":3,"376":2,"378":1,"391":1,"392":1,"395":1,"399":1,"400":2,"404":2,"406":3,"410":2,"411":2,"413":1,"416":1,"420":1,"421":1,"422":1}}],["area``",{"1":{"268":1,"271":1}}],["areas",{"1":{"146":1}}],["area",{"1":{"3":1,"18":1,"24":1,"38":1,"49":1,"241":1,"265":3,"268":3,"273":1,"405":1},"2":{"268":1,"271":1}}],["a",{"0":{"127":1,"144":2,"145":1,"147":1,"152":2,"155":1,"208":1,"209":1,"217":2,"235":1,"257":1,"321":1,"322":1,"334":1,"339":1,"360":2,"368":1,"383":1,"386":1,"387":1,"415":1,"416":1},"1":{"3":1,"4":1,"5":1,"6":1,"7":2,"9":2,"10":15,"11":2,"12":4,"13":1,"14":1,"15":3,"17":1,"18":2,"19":9,"20":3,"21":1,"23":4,"24":3,"25":2,"26":6,"27":1,"28":3,"30":2,"31":3,"32":5,"33":1,"34":9,"37":6,"38":1,"39":2,"40":5,"42":9,"48":4,"51":4,"52":1,"53":3,"58":1,"59":4,"60":3,"61":27,"62":6,"63":2,"64":1,"65":5,"66":9,"68":3,"69":3,"70":7,"71":4,"72":1,"74":3,"75":4,"76":8,"77":6,"78":15,"80":9,"81":8,"83":1,"91":2,"94":2,"95":2,"97":1,"98":1,"99":1,"101":2,"102":2,"104":2,"108":2,"110":13,"111":3,"112":3,"113":2,"117":3,"120":2,"121":4,"122":1,"123":5,"124":9,"127":1,"129":2,"131":1,"133":1,"134":5,"135":5,"138":11,"139":6,"140":13,"141":13,"142":1,"143":2,"144":9,"145":4,"146":7,"147":11,"148":5,"150":3,"151":5,"152":4,"153":2,"155":1,"156":1,"157":3,"158":4,"159":2,"160":2,"161":2,"162":4,"163":1,"164":6,"165":2,"166":4,"167":7,"168":9,"169":4,"170":4,"171":1,"172":6,"173":4,"174":6,"175":4,"176":3,"177":2,"178":1,"179":6,"180":7,"181":3,"182":7,"183":5,"184":13,"187":10,"188":3,"189":5,"190":3,"192":7,"193":5,"194":3,"195":1,"197":2,"198":5,"199":6,"200":4,"201":12,"202":11,"204":7,"206":35,"208":2,"209":4,"210":9,"211":4,"212":2,"217":4,"218":5,"219":2,"221":3,"222":8,"224":4,"230":7,"231":1,"233":3,"234":1,"235":21,"236":2,"237":1,"238":7,"240":3,"241":7,"242":2,"243":3,"245":5,"246":5,"248":3,"250":3,"251":1,"252":5,"253":2,"254":2,"255":8,"256":2,"257":1,"258":5,"259":4,"260":1,"261":2,"262":10,"263":4,"267":7,"268":11,"269":4,"270":1,"272":8,"273":4,"274":4,"275":7,"276":6,"277":4,"278":5,"290":2,"291":4,"294":1,"295":5,"298":1,"299":10,"302":1,"303":4,"304":5,"306":5,"307":5,"308":4,"310":9,"312":3,"313":2,"314":1,"315":2,"316":1,"324":1,"329":9,"330":1,"331":3,"332":1,"333":1,"334":2,"338":3,"339":2,"340":14,"341":6,"342":1,"344":4,"345":18,"346":1,"347":1,"348":3,"350":4,"351":2,"352":3,"353":2,"354":4,"357":2,"358":2,"359":2,"360":3,"363":1,"365":2,"366":3,"367":2,"368":9,"369":12,"370":2,"371":4,"372":2,"373":4,"374":5,"375":3,"376":5,"377":4,"379":1,"381":1,"382":2,"383":2,"385":2,"386":1,"387":1,"389":1,"391":1,"395":1,"396":2,"397":1,"400":2,"401":2,"403":7,"404":3,"406":2,"408":1,"409":1,"410":4,"412":1,"413":3,"414":5,"415":7,"416":2,"417":4,"418":1,"419":5,"420":19,"421":15,"422":1},"2":{"10":1,"202":1,"294":2,"295":1,"299":1}}],["answer",{"1":{"406":1}}],["ansi",{"1":{"119":3},"2":{"119":1}}],["analogue",{"1":{"198":1}}],["analogy",{"0":{"189":1}}],["analyze",{"1":{"413":1}}],["analysis",{"1":{"112":1,"134":1,"135":1,"140":1,"206":1}}],["analytically",{"1":{"408":1}}],["analytical",{"0":{"294":1,"295":1},"1":{"135":2,"421":1}}],["analytic",{"1":{"61":2,"122":1,"410":1,"415":1}}],["animation",{"1":{"135":1}}],["animations",{"1":{"117":1}}],["annotated",{"1":{"91":1,"246":1,"406":1}}],["annotate",{"1":{"91":1}}],["ancient",{"1":{"75":1}}],["ancestors",{"2":{"20":1}}],["antiquity",{"1":{"75":1}}],["angus",{"1":{"71":1}}],["angulardirection",{"2":{"49":1}}],["angulardirection`",{"1":{"49":1}}],["angular",{"1":{"30":1,"146":2,"179":1,"276":1,"306":1,"353":3,"354":3}}],["angleiron",{"1":{"230":1}}],["angle=0",{"1":{"395":1,"397":1}}],["angle=360",{"1":{"395":1,"397":1}}],["angle=30",{"1":{"180":1,"325":1,"365":1}}],["angle=270",{"1":{"395":1,"397":1}}],["angle=120",{"1":{"363":1}}],["angle=10",{"1":{"307":1}}],["angle=70",{"1":{"307":1}}],["angle=left",{"1":{"290":1}}],["angle=45",{"1":{"146":2}}],["angle=60",{"1":{"80":1}}],["angle=90",{"1":{"76":1,"395":1,"397":1}}],["angled",{"1":{"42":1}}],["angle",{"0":{"284":1},"1":{"40":1,"61":6,"80":1,"173":3,"180":1,"182":1,"183":1,"184":2,"201":1,"217":2,"218":2,"220":1,"230":8,"284":1,"290":1,"291":1,"294":4,"295":1,"310":1,"325":1,"329":1,"353":2,"354":1,"365":1},"2":{"180":1,"183":2,"316":1,"325":1,"363":1,"364":1}}],["angles=",{"1":{"179":1}}],["angles",{"1":{"9":1,"61":1,"63":1,"75":1,"77":1,"80":1,"179":2,"184":1,"188":2,"218":5,"219":3,"220":1,"249":1,"294":1,"295":1,"363":1},"2":{"80":1,"179":1}}],["another",{"0":{"104":1,"155":1},"1":{"11":1,"30":1,"31":1,"95":1,"104":3,"155":1,"181":1,"184":3,"273":1,"306":1,"308":1,"310":1,"329":2,"340":1,"357":1,"368":1,"375":1,"376":1}}],["an",{"0":{"145":1,"161":1,"164":1,"415":1},"1":{"3":1,"5":2,"9":2,"11":3,"12":1,"14":2,"17":1,"19":4,"20":1,"26":2,"39":2,"42":4,"51":2,"54":1,"61":6,"66":2,"71":1,"73":1,"76":1,"78":2,"80":3,"81":1,"92":1,"99":1,"100":2,"108":1,"111":1,"120":1,"123":1,"134":1,"135":2,"139":1,"140":1,"143":1,"144":1,"145":1,"151":1,"156":1,"160":1,"161":1,"165":1,"170":2,"172":1,"173":1,"176":1,"177":1,"178":2,"181":2,"182":2,"183":1,"184":1,"188":2,"189":3,"190":1,"192":1,"193":1,"194":1,"198":1,"199":3,"201":1,"204":2,"209":4,"210":2,"211":1,"217":1,"222":1,"233":1,"235":2,"240":1,"241":4,"248":1,"256":1,"257":2,"259":2,"262":2,"272":1,"277":1,"278":2,"295":1,"298":1,"308":1,"312":1,"313":1,"317":1,"331":1,"334":1,"338":1,"339":1,"340":1,"342":1,"353":1,"354":1,"363":1,"364":1,"368":1,"369":1,"373":1,"374":1,"375":1,"376":1,"377":1,"379":1,"397":1,"406":1,"415":1,"416":1,"418":1,"420":3,"421":1}}],["and",{"0":{"9":1,"10":1,"82":1,"89":1,"125":1,"143":1,"144":1,"146":1,"147":1,"168":1,"169":1,"172":1,"177":1,"217":1,"240":1,"253":1,"260":1,"277":1,"312":1,"337":1,"344":1,"360":1,"397":1,"398":1,"399":1,"401":1},"1":{"3":1,"4":2,"5":4,"6":2,"7":2,"9":2,"10":4,"11":5,"14":3,"15":2,"16":1,"17":1,"19":6,"20":3,"21":1,"22":1,"23":3,"25":4,"26":2,"27":2,"28":9,"30":4,"31":3,"32":2,"34":2,"37":4,"40":1,"42":4,"48":1,"49":1,"51":1,"52":2,"53":2,"54":2,"56":2,"57":1,"58":6,"59":2,"60":1,"61":7,"64":1,"65":4,"66":6,"67":1,"69":1,"70":5,"71":1,"72":2,"73":1,"74":3,"75":3,"76":2,"77":5,"78":3,"80":9,"81":3,"82":3,"84":1,"85":1,"89":1,"90":3,"91":4,"93":2,"94":1,"97":2,"98":3,"99":3,"100":1,"101":1,"102":5,"104":4,"108":7,"109":2,"110":6,"111":7,"112":6,"113":8,"117":7,"118":2,"119":11,"120":7,"121":6,"122":3,"123":11,"124":9,"129":3,"131":1,"133":17,"134":15,"135":13,"137":1,"138":17,"139":14,"140":20,"141":13,"143":1,"144":4,"146":1,"147":7,"149":1,"150":1,"151":1,"152":7,"155":3,"156":2,"157":1,"158":1,"159":1,"160":2,"161":2,"162":2,"163":1,"164":3,"165":3,"166":2,"169":4,"170":3,"172":3,"174":1,"177":3,"178":2,"180":3,"181":3,"182":3,"183":1,"184":6,"185":1,"186":2,"187":5,"188":7,"189":3,"190":4,"191":2,"192":1,"194":2,"196":1,"197":2,"198":2,"199":1,"200":1,"201":3,"202":3,"204":12,"206":20,"208":3,"209":4,"210":1,"212":2,"214":3,"217":1,"218":11,"219":11,"220":8,"221":5,"222":3,"224":4,"229":3,"230":14,"231":3,"232":1,"233":9,"234":3,"235":2,"236":7,"237":4,"238":6,"240":2,"241":9,"242":2,"243":2,"245":7,"246":1,"248":2,"249":2,"250":3,"251":2,"252":1,"253":3,"255":4,"258":1,"261":1,"262":4,"263":1,"265":1,"266":1,"267":2,"268":2,"269":1,"270":1,"272":6,"273":1,"274":1,"275":1,"276":2,"277":2,"278":4,"279":1,"290":2,"291":3,"292":1,"294":3,"295":4,"299":5,"302":1,"303":5,"304":1,"306":3,"307":6,"308":2,"310":15,"312":1,"313":1,"314":1,"315":1,"316":1,"318":1,"322":1,"329":5,"330":2,"331":2,"332":1,"333":2,"334":1,"335":1,"336":1,"338":1,"339":1,"340":3,"343":1,"345":5,"346":2,"347":1,"350":3,"352":2,"353":4,"354":3,"356":1,"357":1,"358":1,"359":2,"361":1,"365":1,"368":4,"369":4,"374":3,"375":1,"376":2,"377":3,"382":1,"384":1,"388":2,"389":1,"394":1,"395":3,"396":4,"397":2,"399":1,"400":2,"401":1,"402":1,"403":2,"404":2,"406":1,"408":3,"409":1,"410":1,"411":1,"412":2,"413":3,"414":3,"415":3,"416":3,"417":2,"419":4,"420":13,"421":8}}],["anytree",{"0":{"20":1},"1":{"20":2}}],["anywhere",{"1":{"7":1,"202":1,"222":1}}],["anyway",{"1":{"7":1}}],["any",{"1":{"2":1,"19":1,"20":2,"28":1,"42":1,"49":1,"50":1,"104":1,"147":2,"166":1,"184":1,"188":1,"192":1,"201":1,"202":1,"241":1,"259":1,"262":1,"275":1,"276":1,"278":1,"294":1,"295":1,"335":1,"340":1,"342":1,"345":1,"346":1,"379":2,"415":1,"417":1}}],["asin",{"1":{"290":3},"2":{"290":1}}],["asking",{"1":{"310":1}}],["ask",{"1":{"124":1}}],["asme",{"1":{"119":1}}],["asymmetric",{"1":{"80":1}}],["asctime",{"1":{"51":1}}],["aspects",{"0":{"137":1},"1":{"137":1,"139":1}}],["aspect",{"1":{"37":1}}],["assume",{"1":{"91":1}}],["assumed",{"1":{"36":1,"345":1}}],["assistant",{"1":{"413":1}}],["assistance",{"1":{"50":1,"197":1}}],["assist",{"1":{"260":1}}],["assignment",{"1":{"292":1}}],["assigns",{"1":{"53":1}}],["assign",{"1":{"13":2,"108":1}}],["assigning",{"0":{"13":1},"1":{"12":1,"14":1}}],["assigned",{"1":{"3":1,"20":1,"28":1,"110":1,"184":1,"359":1,"372":1,"379":1,"383":1}}],["associated",{"1":{"36":1,"206":1}}],["assert",{"1":{"34":1,"68":1,"69":4,"70":1,"72":1,"78":2,"81":1,"124":1,"278":2,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["assets",{"1":{"16":3,"23":1,"25":1,"26":1,"30":1,"31":1,"32":1,"37":1,"42":1,"48":2,"53":1,"59":3,"60":1,"61":1,"62":3,"63":1,"64":2,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":22,"74":1,"75":1,"76":2,"77":1,"78":1,"80":2,"81":3,"117":1,"119":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"179":1,"182":3,"184":1,"208":2,"209":5,"218":28,"219":18,"220":10,"221":1,"222":2,"225":1,"230":1,"240":1,"243":1,"247":1,"256":1,"257":2,"262":2,"264":4,"265":3,"266":6,"267":1,"268":1,"272":5,"273":2,"275":1,"276":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1,"291":14,"298":1,"299":2,"304":1,"307":1,"312":1,"314":1,"317":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"331":1,"332":1,"334":1,"335":1,"339":1,"340":1,"346":1,"348":1,"350":2,"357":1,"359":1,"360":1,"362":1,"363":1,"364":1,"365":1,"366":1,"368":1,"369":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"379":1,"388":1,"400":1,"401":1,"420":4}}],["assemble",{"1":{"61":1,"420":1}}],["assembled",{"1":{"12":1,"61":1,"419":1}}],["assembly2",{"1":{"17":3}}],["assembly1",{"1":{"17":3}}],["assembly3",{"1":{"17":6}}],["assembly",{"0":{"14":1,"345":1},"1":{"12":2,"13":2,"14":11,"17":3,"19":10,"20":1,"61":2,"77":3,"80":1,"100":1,"204":1,"259":1,"261":1,"310":1,"337":1,"345":1}}],["assemblies",{"0":{"12":1},"1":{"17":1,"19":1,"77":1,"100":1,"126":1,"204":1,"206":2,"343":1},"2":{"17":1}}],["as",{"0":{"144":1,"263":1,"416":1},"1":{"2":1,"3":2,"4":4,"5":1,"6":1,"7":2,"10":2,"12":1,"14":2,"15":1,"17":2,"19":3,"20":1,"23":2,"24":1,"25":6,"26":5,"27":2,"28":7,"30":3,"31":6,"32":3,"34":6,"37":3,"38":1,"39":5,"42":6,"49":2,"51":2,"52":1,"56":1,"59":3,"60":3,"61":3,"62":4,"63":3,"64":1,"65":3,"66":1,"67":8,"68":3,"69":3,"70":3,"71":7,"72":2,"74":3,"76":15,"77":1,"78":8,"80":14,"81":4,"90":1,"91":4,"94":1,"98":4,"100":3,"102":2,"105":1,"108":2,"110":5,"113":3,"117":1,"118":1,"121":1,"124":10,"128":1,"133":2,"134":3,"135":9,"138":2,"139":2,"140":2,"141":1,"142":1,"143":1,"144":5,"145":3,"146":1,"147":4,"148":3,"149":3,"150":2,"151":1,"152":4,"153":1,"154":1,"155":2,"156":2,"157":3,"158":3,"159":4,"160":2,"161":2,"162":2,"163":3,"164":2,"165":4,"166":2,"167":2,"168":4,"169":3,"170":4,"171":3,"172":3,"173":2,"174":3,"175":2,"176":3,"177":1,"178":4,"179":4,"180":1,"181":2,"182":7,"184":5,"188":1,"189":4,"190":4,"191":3,"192":5,"193":3,"194":3,"195":4,"197":2,"198":1,"199":3,"200":1,"201":6,"202":11,"204":2,"206":6,"209":1,"217":1,"221":1,"222":2,"224":2,"230":4,"232":1,"233":1,"235":2,"238":4,"240":4,"241":2,"242":1,"246":1,"248":1,"250":4,"251":7,"253":1,"254":2,"255":5,"256":2,"259":1,"261":1,"262":7,"263":3,"267":1,"270":3,"272":10,"275":2,"276":3,"278":8,"279":4,"280":8,"281":6,"282":6,"283":4,"284":9,"285":5,"286":3,"287":7,"288":6,"289":5,"290":3,"295":2,"296":1,"298":1,"299":5,"304":2,"306":1,"307":1,"310":3,"312":2,"317":1,"331":2,"332":2,"334":1,"335":1,"336":1,"337":2,"340":6,"341":5,"345":3,"346":3,"347":1,"348":1,"350":7,"351":1,"352":1,"353":3,"354":2,"357":4,"358":1,"359":1,"362":1,"363":1,"365":2,"366":1,"368":4,"369":3,"370":2,"371":4,"372":3,"373":2,"374":4,"375":3,"376":3,"377":2,"378":3,"379":1,"381":1,"382":2,"385":1,"388":1,"389":2,"395":1,"397":1,"400":1,"403":3,"404":2,"406":4,"408":1,"410":3,"412":1,"413":4,"414":1,"416":1,"417":4,"419":1,"420":7,"421":2,"422":1},"2":{"26":1,"56":1,"105":1}}],["aluminum",{"1":{"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["almost",{"1":{"192":1,"233":1,"259":1,"263":1}}],["aliceblue",{"1":{"179":1}}],["aligns",{"1":{"230":1,"339":1,"354":1}}],["aligned",{"1":{"61":1,"221":1,"246":1,"262":1,"344":1,"399":1}}],["align`",{"1":{"49":1,"169":2}}],["alignment",{"1":{"22":1,"61":4,"77":1,"221":1,"257":1}}],["aligning",{"1":{"22":1,"308":1,"368":1}}],["align",{"0":{"221":1},"1":{"16":18,"19":1,"23":1,"25":1,"26":1,"30":1,"31":1,"32":1,"34":2,"37":1,"42":1,"44":1,"53":1,"59":3,"60":1,"61":1,"62":9,"63":1,"64":2,"65":1,"66":1,"67":9,"68":1,"69":1,"70":1,"71":1,"72":1,"74":1,"75":12,"76":28,"77":21,"78":3,"80":6,"81":3,"108":2,"119":1,"124":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":5,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":9,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"179":7,"182":4,"202":1,"221":5,"222":7,"225":1,"247":1,"256":1,"257":4,"267":1,"268":1,"272":11,"273":2,"275":1,"276":1,"278":3,"279":1,"280":9,"281":1,"282":5,"283":1,"284":7,"285":1,"286":9,"287":1,"288":7,"289":5,"290":6,"291":1,"298":1,"299":2,"304":1,"307":1,"312":1,"314":1,"317":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"331":1,"332":1,"334":1,"335":1,"339":1,"340":1,"346":1,"348":1,"350":12,"357":1,"359":4,"360":1,"362":1,"363":1,"364":1,"365":1,"366":1,"368":4,"369":7,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"379":1,"388":1,"400":1,"401":1,"420":4},"2":{"22":1,"44":1,"49":1,"75":1,"77":1,"169":1,"221":2,"222":1}}],["align=none",{"1":{"282":1}}],["align=align",{"1":{"60":1,"61":1,"62":1,"65":1,"67":4,"75":1,"76":10,"77":2,"80":2,"221":1,"222":1,"230":4,"262":1,"417":6}}],["align=",{"1":{"16":4,"62":3,"67":4,"76":1,"77":1,"80":2,"149":2,"169":4,"179":3,"182":1,"221":1,"272":2,"278":1,"280":4,"282":2,"284":3,"286":3,"288":3,"289":2,"290":2,"350":5,"359":1,"368":1,"369":2}}],["alone",{"1":{"165":1}}],["along",{"1":{"5":2,"6":1,"28":1,"34":1,"49":3,"61":5,"68":4,"78":3,"112":1,"124":1,"133":1,"147":1,"155":1,"167":1,"180":1,"182":1,"220":1,"235":3,"238":2,"243":3,"264":3,"275":1,"340":1,"341":1,"344":3,"345":3,"352":1,"354":1}}],["altered",{"1":{"272":1}}],["alternative",{"1":{"102":1,"252":1}}],["alternatively",{"1":{"80":1,"379":1}}],["alternate",{"1":{"31":1}}],["alt",{"1":{"225":1,"247":1,"400":1,"401":1,"420":4}}],["although",{"1":{"201":1,"260":1,"263":1,"345":1,"368":1,"417":1}}],["alt=",{"1":{"124":1,"396":1,"420":1}}],["alpha",{"1":{"76":1}}],["alphas=",{"1":{"70":2}}],["alpha=0",{"1":{"68":2}}],["always",{"1":{"39":1,"129":1,"181":1,"192":1,"196":1,"222":1,"326":1,"334":1,"344":1,"347":1}}],["alg",{"1":{"188":3}}],["algorithm",{"1":{"15":1}}],["algebraic",{"0":{"8":1},"1":{"124":2,"210":1,"295":1}}],["algebra",{"0":{"11":1,"186":1,"207":1,"210":1,"273":1,"292":1,"297":1},"1":{"0":2,"11":2,"61":1,"62":1,"64":2,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"72":1,"73":1,"74":1,"75":1,"77":1,"78":1,"81":2,"122":1,"126":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":2,"175":1,"176":1,"177":1,"178":2,"186":1,"187":1,"197":3,"210":1,"214":1,"222":1,"223":1,"224":1,"230":1,"238":5,"273":2,"278":2,"319":1,"406":1,"408":1,"410":1,"420":1}}],["already",{"1":{"11":1,"189":2}}],["also",{"1":{"10":1,"62":1,"67":1,"97":1,"98":1,"104":1,"123":1,"133":1,"143":2,"147":1,"149":1,"156":1,"160":3,"178":1,"184":1,"198":2,"201":1,"204":1,"221":2,"236":1,"273":1,"310":3,"341":1,"369":1,"371":1,"378":1,"400":1,"417":1,"420":1}}],["alloy",{"1":{"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["allowed",{"0":{"293":1}}],["allow",{"1":{"48":1,"86":1,"139":3,"183":1,"196":1,"212":1,"277":1,"345":1,"358":1}}],["allowing",{"1":{"42":1,"99":1,"123":1,"194":1,"278":1,"336":1,"340":1}}],["allows",{"1":{"1":1,"4":1,"5":1,"7":1,"31":1,"42":2,"101":1,"133":1,"135":3,"138":1,"141":5,"143":1,"160":1,"176":1,"180":1,"183":1,"190":1,"197":1,"201":1,"202":1,"204":1,"217":1,"230":1,"236":1,"237":1,"263":1,"299":1,"354":1,"358":1,"421":2}}],["all``",{"1":{"272":3}}],["all",{"0":{"335":1,"390":1},"1":{"1":1,"4":2,"10":3,"11":2,"13":2,"17":1,"19":3,"20":5,"31":1,"34":1,"37":1,"42":2,"43":1,"49":2,"53":2,"54":1,"66":1,"70":2,"75":1,"77":1,"78":2,"80":1,"100":1,"123":1,"124":1,"131":1,"140":1,"177":1,"178":2,"179":1,"181":1,"184":1,"188":1,"189":1,"190":1,"192":1,"194":1,"202":2,"204":1,"206":1,"209":1,"218":1,"221":1,"222":3,"223":1,"233":1,"238":3,"242":1,"252":1,"257":3,"258":1,"261":1,"262":1,"263":4,"266":3,"267":1,"268":1,"270":6,"271":2,"272":5,"274":2,"275":1,"276":2,"278":1,"311":2,"312":1,"325":1,"339":1,"344":1,"345":2,"346":2,"361":1,"367":1,"368":1,"371":1,"374":1,"379":2,"383":2,"390":1,"391":1,"392":1,"394":1,"420":2,"421":1},"2":{"178":1,"272":1,"346":1,"379":1}}],["2+",{"1":{"290":1}}],["2f",{"1":{"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1}}],["2nd",{"1":{"169":1,"279":1,"295":1}}],["211",{"1":{"290":2}}],["2115",{"1":{"62":2}}],["21",{"0":{"155":1},"1":{"154":1}}],["28",{"0":{"162":1},"1":{"60":1,"161":1}}],["297",{"1":{"299":1}}],["29",{"0":{"163":1},"1":{"60":2,"162":1,"204":1,"288":1,"295":1,"299":5}}],["27>`",{"1":{"238":1}}],["2773",{"1":{"62":2}}],["2700",{"1":{"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"290":1}}],["270",{"1":{"61":2,"353":2}}],["270°",{"1":{"61":1}}],["27",{"0":{"161":1},"1":{"60":3,"160":1,"182":1}}],["23>`",{"1":{"238":1}}],["23",{"0":{"157":1,"278":1,"279":1},"1":{"60":6,"74":2,"156":1,"243":2,"248":1,"278":2,"279":2,"284":1,"289":2,"290":1,"291":6}}],["250",{"1":{"331":1}}],["25>`",{"1":{"238":1}}],["25inch",{"1":{"74":2}}],["255",{"1":{"67":2,"209":4}}],["2569",{"1":{"62":2}}],["25",{"0":{"159":1},"1":{"34":1,"36":1,"61":2,"66":2,"68":2,"74":2,"77":1,"78":2,"80":1,"81":2,"124":1,"145":2,"157":6,"158":1,"169":2,"179":2,"182":1,"243":1,"280":10,"287":4,"336":2,"346":2}}],["2213",{"1":{"395":1,"399":1}}],["2205",{"1":{"395":1,"399":1}}],["220",{"1":{"331":1}}],["222",{"1":{"288":6}}],["225",{"1":{"62":2}}],["22",{"0":{"156":1},"1":{"32":1,"60":4,"81":2,"153":2,"155":1,"179":1,"286":3}}],["240",{"1":{"331":1}}],["24>`",{"1":{"238":1}}],["242",{"1":{"76":1}}],["2469",{"1":{"62":2}}],["2458",{"1":{"62":2}}],["24",{"0":{"158":1,"279":1,"280":1},"1":{"16":3,"60":1,"157":1,"166":1,"238":1,"278":1,"279":3,"280":1,"281":1,"291":6}}],["2d`",{"1":{"245":1}}],["2d",{"0":{"105":1,"110":1,"219":1,"250":1,"340":1},"1":{"15":2,"16":1,"18":1,"34":2,"48":1,"49":3,"58":1,"60":1,"66":1,"71":1,"78":2,"81":2,"82":1,"110":3,"113":1,"119":1,"123":3,"124":3,"159":2,"160":1,"164":2,"172":1,"189":1,"194":1,"202":1,"206":1,"221":2,"224":2,"230":1,"233":2,"235":9,"236":6,"238":8,"243":10,"245":1,"246":1,"250":2,"253":2,"329":1,"334":2,"338":1,"340":5,"341":2,"342":1,"345":3,"371":1,"421":1},"2":{"243":1}}],["264",{"1":{"299":1}}],["2621",{"1":{"62":2}}],["26",{"0":{"160":1},"1":{"14":2,"60":3,"63":1,"159":1,"281":3,"284":1}}],["2``",{"1":{"10":2,"169":1,"388":1}}],["2`",{"1":{"9":1}}],["206",{"1":{"278":2}}],["200",{"1":{"257":1,"286":2,"304":2}}],["2025",{"1":{"243":1}}],["2024",{"1":{"94":1}}],["2023",{"1":{"67":1,"278":2}}],["204",{"1":{"67":1}}],["20s",{"1":{"51":1}}],["20",{"0":{"154":1},"1":{"4":1,"11":4,"42":1,"51":4,"60":2,"62":2,"64":2,"75":6,"76":4,"80":2,"81":4,"108":1,"145":9,"147":2,"148":2,"150":2,"152":1,"157":4,"165":4,"176":4,"190":1,"193":2,"199":1,"201":3,"208":1,"209":12,"211":1,"256":2,"278":5,"279":1,"282":1,"284":1,"287":3,"288":1,"345":3,"346":1,"420":1}}],["2",{"0":{"153":1,"338":1,"350":1,"370":1,"381":1,"398":1,"405":1},"1":{"0":1,"4":1,"6":2,"9":4,"10":3,"11":16,"23":3,"25":2,"28":7,"31":7,"32":1,"34":3,"42":3,"47":1,"59":2,"60":6,"61":8,"62":14,"63":5,"64":6,"67":10,"68":2,"69":24,"70":4,"71":5,"74":18,"75":2,"76":24,"77":5,"78":7,"80":5,"81":7,"119":1,"124":3,"126":1,"131":2,"142":1,"143":1,"144":9,"151":4,"152":2,"153":2,"154":2,"155":4,"156":4,"158":2,"159":4,"160":2,"161":2,"162":4,"163":8,"164":4,"165":4,"166":6,"167":4,"168":6,"170":14,"176":28,"178":2,"179":3,"182":7,"184":1,"185":2,"186":1,"187":8,"188":15,"189":5,"194":1,"195":1,"198":2,"199":1,"202":1,"204":3,"208":4,"209":44,"210":1,"211":1,"240":3,"241":3,"245":1,"251":1,"256":3,"262":2,"264":1,"265":1,"266":1,"272":8,"273":2,"276":2,"278":13,"279":11,"280":14,"281":11,"282":7,"283":15,"284":12,"286":8,"287":14,"288":17,"289":11,"290":5,"295":5,"298":1,"299":2,"304":3,"307":4,"314":2,"315":1,"316":1,"320":1,"331":2,"336":1,"340":6,"341":3,"345":3,"346":5,"350":10,"352":1,"353":5,"354":2,"357":1,"359":1,"367":2,"368":4,"369":6,"375":2,"376":4,"377":4,"388":1,"389":2,"393":1,"394":1,"395":4,"396":1,"397":4,"399":1,"408":1,"413":1,"420":1,"422":1}}]],"serializationVersion":2}} diff --git a/packages/client/public/py/harness.py b/packages/client/public/py/harness.py index 139c129..100469c 100644 --- a/packages/client/public/py/harness.py +++ b/packages/client/public/py/harness.py @@ -266,15 +266,16 @@ def parse_expect(source: str) -> dict: # Each kind maps to {required keys, optional keys}; "kind" itself is implicit. _CHECK_KEYS = { - "hole_through": ({"diameter", "count"}, {"tol", "target"}), - "hole_blind": ({"diameter", "count"}, {"tol", "target"}), - "hole_internal": ({"diameter", "count"}, {"tol", "target"}), + "hole_through": ({"diameter", "count"}, {"at_mm", "tol", "target"}), + "hole_blind": ({"diameter", "count"}, {"at_mm", "tol", "target"}), + "hole_internal": ({"diameter", "count"}, {"at_mm", "tol", "target"}), "clearance": ({"a", "b", "min_mm"}, {"max_mm"}), "bbox": ({"size_mm"}, {"target", "tol"}), "volume": ({"range_mm3"}, {"target"}), + "wall_thickness": ({"range_mm"}, {"target"}), "count_faces": ({"count"}, {"target"}), "count_edges": ({"count"}, {"target"}), - "symmetric": ({"plane"}, {"tol_pct"}), + "symmetric": ({"plane"}, {"target", "tol_pct"}), } _HOLE_CHECK_KINDS = {"hole_through": "through", "hole_blind": "blind", "hole_internal": "internal"} _SYMMETRY_PLANES = ("XY", "XZ", "YZ") @@ -330,6 +331,15 @@ def _validate_check(index, raw): count=_validate_count(index, raw["count"], allow_range=False), target=_target(index, raw), ) + if "at_mm" in raw: + at = raw["at_mm"] + if ( + not isinstance(at, (list, tuple)) + or len(at) != 3 + or not all(_is_number(v) for v in at) + ): + raise _check_error(index, "at_mm must be three numbers.") + spec["at_mm"] = [float(v) for v in at] elif kind == "clearance": for key in ("a", "b"): if not isinstance(raw[key], str) or not raw[key]: @@ -365,6 +375,16 @@ def _validate_check(index, raw): ): raise _check_error(index, "range_mm3 must be [min, max] with min <= max.") spec.update(range_mm3=[float(rng[0]), float(rng[1])], target=_target(index, raw)) + elif kind == "wall_thickness": + rng = raw["range_mm"] + if ( + not isinstance(rng, (list, tuple)) + or len(rng) != 2 + or not all(_is_number(v) and v > 0 for v in rng) + or rng[0] > rng[1] + ): + raise _check_error(index, "range_mm must be [min, max] with 0 < min <= max.") + spec.update(range_mm=[float(rng[0]), float(rng[1])], target=_target(index, raw)) elif kind in ("count_faces", "count_edges"): spec.update( count=_validate_count(index, raw["count"], allow_range=True), @@ -377,7 +397,7 @@ def _validate_check(index, raw): tol_pct = raw.get("tol_pct", DEFAULT_SYMMETRY_TOL_PCT) if not _is_number(tol_pct) or tol_pct <= 0: raise _check_error(index, "tol_pct must be a positive number.") - spec.update(plane=plane, tol_pct=float(tol_pct)) + spec.update(plane=plane, tol_pct=float(tol_pct), target=_target(index, raw)) return spec @@ -686,6 +706,14 @@ def _eval_hole_check(spec, holes, label): wanted_kind = _HOLE_CHECK_KINDS[spec["kind"]] d, tol = spec["diameter"], spec["tol"] matching = [h for h in holes if abs(h["diameterMm"] - d) <= tol] + at = spec.get("at_mm") + if at is not None: + matching = [ + h + for h in matching + if sum((found - wanted) ** 2 for found, wanted in zip(h["centerMm"], at)) ** 0.5 + <= tol + ] found = sum(1 for h in matching if h["kind"] == wanted_kind) others = { kind: sum(1 for h in matching if h["kind"] == kind) @@ -694,8 +722,10 @@ def _eval_hole_check(spec, holes, label): } other_text = ", ".join(f"{n} {kind}" for kind, n in others.items() if n) scope = f" in {label}" if label else "" + anchor = f" at {[round(v, 6) for v in at]}" if at is not None else "" detail = ( - f"{wanted_kind} holes{scope} d={d:g}±{tol:g} mm: expected {spec['count']}, found {found}" + f"{wanted_kind} holes{scope}{anchor} d={d:g}±{tol:g} mm: " + f"expected {spec['count']}, found {found}" + (f" (also {other_text} at this diameter)" if other_text else "") ) return found == spec["count"], detail @@ -734,6 +764,34 @@ def _count_matches(count, found): return found == count, str(count) +def _wall_thickness_samples(shape): + """Cast one inward-normal ray per face and return first-exit distances.""" + from OCP.IntCurvesFace import IntCurvesFace_ShapeIntersector + from OCP.gp import gp_Dir, gp_Lin, gp_Pnt + + bb = shape.bounding_box() + ray_length = 2 * (bb.size.X ** 2 + bb.size.Y ** 2 + bb.size.Z ** 2) ** 0.5 + if ray_length <= 0: + return [] + + intersector = IntCurvesFace_ShapeIntersector() + intersector.Load(shape.wrapped, 1e-7) + samples = [] + for face in shape.faces(): + point = face.center() + inward = -face.normal_at(point) + line = gp_Lin(gp_Pnt(*point), gp_Dir(*inward)) + intersector.Perform(line, 1e-6, ray_length) + distances = [ + intersector.WParameter(i) + for i in range(1, intersector.NbPnt() + 1) + if intersector.WParameter(i) > 1e-6 + ] + if distances: + samples.append(min(distances)) + return samples + + def _eval_check(spec, shape, holes): """(passed, detail) for one normalized check spec. May raise; the caller converts exceptions into a failed check.""" @@ -756,13 +814,17 @@ def _eval_check(spec, shape, holes): from build123d import Plane plane = getattr(Plane, spec["plane"]) + target_label = spec.get("target") + target, err = _resolve_target(shape, target_label) + if err: + return False, f"symmetric on {target_label}: {err}" # Cutting a multi-child Compound against its mirror hands OCC several # exactly-coincident tools at once; its same-domain detection handles # that unreliably and children can come back uncut, reporting >100% # "asymmetric" volume on symmetric assemblies. Fuse to a single body # first so the mirror-difference is one well-posed boolean. - solids = shape.solids() - body = solids[0].fuse(*solids[1:]) if solids else shape + solids = target.solids() + body = solids[0].fuse(*solids[1:]) if solids else target mirrored = body.mirror(plane) volume = float(body.volume) # Mirroring is an isometry, so both difference directions enclose the @@ -770,8 +832,9 @@ def _eval_check(spec, shape, holes): # reported ratio within 0-100%). asymmetry = float((body - mirrored).volume) ratio_pct = 100 * asymmetry / volume if volume > 0 else float("inf") + subject = f"symmetry of {target_label} about" if target_label else "symmetry about" return ratio_pct <= spec["tol_pct"], ( - f"symmetry about {spec['plane']}: asymmetric volume {ratio_pct:.3g}% " + f"{subject} {spec['plane']}: asymmetric volume {ratio_pct:.3g}% " f"of total, allowed <= {spec['tol_pct']:g}%" ) @@ -795,6 +858,16 @@ def _eval_check(spec, shape, holes): return lo <= volume <= hi, ( f"volume of {label}: expected [{lo:.6g}, {hi:.6g}] mm^3, measured {volume:.6g}" ) + if kind == "wall_thickness": + samples = _wall_thickness_samples(target) + if not samples: + return False, f"wall_thickness on {label}: no measurable face samples" + measured_min, measured_max = min(samples), max(samples) + lo, hi = spec["range_mm"] + return lo <= measured_min and measured_max <= hi, ( + f"wall_thickness on {label}: expected [{lo:g}, {hi:g}] mm, measured " + f"[{measured_min:.6g}, {measured_max:.6g}] mm from {len(samples)} faces" + ) if kind in ("count_faces", "count_edges"): found = len(target.faces() if kind == "count_faces" else target.edges()) ok, wanted = _count_matches(spec["count"], found) diff --git a/packages/client/src/agent/docSearchConfig.ts b/packages/client/src/agent/docSearchConfig.ts new file mode 100644 index 0000000..c71d86b --- /dev/null +++ b/packages/client/src/agent/docSearchConfig.ts @@ -0,0 +1,13 @@ +import type { Options, SearchOptions } from "minisearch"; + +export const DOC_INDEX_OPTIONS: Options = { + fields: ["title", "body", "api_names", "synonyms"], + storeFields: ["title", "body", "api_names", "synonyms"], + idField: "section_id", +}; + +export const DOC_SEARCH_OPTIONS: SearchOptions = { + boost: { api_names: 6, title: 4, synonyms: 2 }, + fuzzy: 0.2, + prefix: true, +}; diff --git a/packages/client/src/agent/plan.test.ts b/packages/client/src/agent/plan.test.ts index b921c4c..b2dfbb3 100644 --- a/packages/client/src/agent/plan.test.ts +++ b/packages/client/src/agent/plan.test.ts @@ -57,6 +57,105 @@ describe("validatePlanSnapshot", () => { expect(validatePlanSnapshot({ next: makePlan(), previous: undefined, evidence: noEvidence })).toEqual([]); }); + it("requires a spec sheet for an image-triggered plan", () => { + const errors = validatePlanSnapshot({ + next: makePlan(), + previous: undefined, + evidence: noEvidence, + requireSpecSheet: true, + }); + expect(errors).toContain("spec_sheet is required for an image-triggered plan"); + }); + + it("rejects spec rows without a check link or unverifiable reason", () => { + const plan = makePlan({ + spec_sheet: [{ id: "image-width", text: "The overall width is 100 mm.", source: "image" }], + }); + const errors = validatePlanSnapshot({ + next: plan, + previous: undefined, + evidence: noEvidence, + requireSpecSheet: true, + }); + expect(errors).toContain( + 'spec_sheet row "image-width": provide non-empty check_refs or a non-empty unverifiable_reason', + ); + }); + + it("rejects dangling spec-sheet check references and accepts existing component checks", () => { + const plan = makePlan({ + spec_sheet: [ + { + id: "image-width", + text: "The overall width is 100 mm.", + source: "image", + check_refs: [{ component_id: "base", check_index: 99 }], + }, + ], + }); + const dangling = validatePlanSnapshot({ + next: plan, + previous: undefined, + evidence: noEvidence, + requireSpecSheet: true, + }); + expect(dangling).toContain( + 'spec_sheet row "image-width": check_refs[0] does not resolve to an existing component check', + ); + + plan.spec_sheet![0]!.check_refs = [{ component_id: "base", check_index: 0 }]; + expect( + validatePlanSnapshot({ + next: plan, + previous: undefined, + evidence: noEvidence, + requireSpecSheet: true, + }), + ).toEqual([]); + }); + + it("rejects a snapshot that drops the previous plan's spec sheet", () => { + const previous = makePlan({ + spec_sheet: [ + { + id: "image-width", + text: "The overall width is 100 mm.", + source: "image", + check_refs: [{ component_id: "base", check_index: 0 }], + }, + ], + }); + const errors = validatePlanSnapshot({ + next: makePlan(), + previous, + evidence: noEvidence, + }); + expect(errors).toContain( + "spec_sheet cannot be dropped: the previous plan carries one; resubmit it (edited if needed)", + ); + }); + + it("accepts a non-empty unverifiable reason without check references", () => { + const plan = makePlan({ + spec_sheet: [ + { + id: "surface-finish", + text: "The drawing calls for a matte surface finish.", + source: "image", + unverifiable_reason: "The geometry kernel cannot measure surface finish.", + }, + ], + }); + expect( + validatePlanSnapshot({ + next: plan, + previous: undefined, + evidence: noEvidence, + requireSpecSheet: true, + }), + ).toEqual([]); + }); + it("rejects duplicate, malformed, and reserved component ids", () => { const plan = makePlan({ components: [ @@ -110,6 +209,30 @@ describe("validatePlanSnapshot", () => { expect(validatePlanSnapshot({ next: plan, previous: undefined, evidence: noEvidence })).toEqual([]); }); + it("accepts wall thickness, anchored holes, and targeted symmetry checks", () => { + const plan = makePlan(); + const checks: PlanCheckEntry[] = [ + volumeCheck("base"), + { kind: "wall_thickness", range_mm: [3.4, 3.6], target: "base" }, + { kind: "hole_through", diameter: 6.5, count: 1, at_mm: [30, 15, 0], tol: 0.25, target: "base" }, + { kind: "symmetric", plane: "YZ", target: "base" }, + ]; + plan.components[0]!.checks = checks; + expect(validatePlanSnapshot({ next: plan, previous: undefined, evidence: noEvidence })).toEqual([]); + }); + + it("rejects malformed wall thickness and hole anchor fields", () => { + const plan = makePlan(); + plan.components[0]!.checks = [ + volumeCheck("base"), + { kind: "wall_thickness", range_mm: [4, 3], target: "base" }, + { kind: "hole_blind", diameter: 5, count: 1, at_mm: [1, 2], target: "base" }, + ] as unknown as PlanCheckEntry[]; + const errors = validatePlanSnapshot({ next: plan, previous: undefined, evidence: noEvidence }).join("\n"); + expect(errors).toMatch(/range_mm must be \[min, max\] with 0 < min <= max/); + expect(errors).toMatch(/at_mm must be three numbers/); + }); + it("requires a targeted, bounded volume check on every buildable component", () => { const plan = makePlan(); plan.components[0]!.checks = []; @@ -333,4 +456,21 @@ describe("createUpdatePlanTool", () => { /Plan rejected:[\s\S]*"lid" from the previous plan is missing[\s\S]*no gate-passed run/, ); }); + + it("rejects an image-triggered snapshot without a spec sheet", async () => { + const tool = createUpdatePlanTool({ getMessages: () => [], requireSpecSheet: () => true }); + await expect(tool.execute("t1", makePlan() as never, undefined as never, undefined as never)).rejects.toThrow( + /Plan rejected:[\s\S]*spec_sheet is required for an image-triggered plan/, + ); + }); + + it("returns a row-level update_plan error for an unmapped spec row", async () => { + const tool = createUpdatePlanTool({ getMessages: () => [], requireSpecSheet: () => true }); + const plan = makePlan({ + spec_sheet: [{ id: "finish", text: "The finish is matte.", source: "image" }], + }); + await expect(tool.execute("t1", plan as never, undefined as never, undefined as never)).rejects.toThrow( + /spec_sheet row "finish": provide non-empty check_refs or a non-empty unverifiable_reason/, + ); + }); }); diff --git a/packages/client/src/agent/plan.ts b/packages/client/src/agent/plan.ts index 46ff6d8..5232801 100644 --- a/packages/client/src/agent/plan.ts +++ b/packages/client/src/agent/plan.ts @@ -1,8 +1,13 @@ import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import { validatePlanCheck, type PlanCheckEntry } from "./planChecks"; +import { + validatePlanCheck, + validatePlanSpecSheetRow, + type PlanCheckEntry, + type PlanSpecSheetRow, +} from "./planChecks"; export { parseComponentDeclaration } from "./componentDeclaration"; -export type { PlanCheckEntry } from "./planChecks"; +export type { PlanCheckEntry, PlanCheckRef, PlanSpecSheetRow } from "./planChecks"; /** * The plan artifact: a persisted, loop-enforced component list for multi-part designs. @@ -61,6 +66,8 @@ export interface Plan { goal: string; components: PlanComponent[]; interfaces: PlanInterface[]; + /** Required for image-triggered plans; optional but validated when present otherwise. */ + spec_sheet?: PlanSpecSheetRow[]; } /** Component ids must be label-safe slugs; "probe" is reserved for diagnostic runs. */ @@ -199,6 +206,7 @@ export interface ValidatePlanArgs { next: Plan; previous: Plan | undefined; evidence: Map; + requireSpecSheet?: boolean; } /** @@ -213,7 +221,7 @@ export interface ValidatePlanArgs { * - evidence: "done" requires a gate-passed run that declared the component and ran * all of its planned checks. */ -export function validatePlanSnapshot({ next, previous, evidence }: ValidatePlanArgs): string[] { +export function validatePlanSnapshot({ next, previous, evidence, requireSpecSheet = false }: ValidatePlanArgs): string[] { const errors: string[] = []; if (typeof next.goal !== "string" || next.goal.trim() === "") { @@ -288,6 +296,41 @@ export function validatePlanSnapshot({ next, previous, evidence }: ValidatePlanA } } + if (requireSpecSheet && (!Array.isArray(next.spec_sheet) || next.spec_sheet.length === 0)) { + errors.push("spec_sheet is required for an image-triggered plan"); + } + // The spec sheet is the durable record of what the agent read off the image; once + // the plan of record carries one, a later snapshot may not silently drop it. + if ( + previous?.spec_sheet !== undefined && + previous.spec_sheet.length > 0 && + (!Array.isArray(next.spec_sheet) || next.spec_sheet.length === 0) + ) { + errors.push("spec_sheet cannot be dropped: the previous plan carries one; resubmit it (edited if needed)"); + } + if (next.spec_sheet !== undefined && !Array.isArray(next.spec_sheet)) { + errors.push("spec_sheet must be an array"); + } else { + const rowIds = new Set(); + const componentsById = new Map(next.components.map((component) => [component.id, component])); + for (const [index, row] of (next.spec_sheet ?? []).entries()) { + const label = typeof row?.id === "string" && row.id.trim() !== "" ? JSON.stringify(row.id) : String(index); + for (const error of validatePlanSpecSheetRow(row)) errors.push(`spec_sheet row ${label}: ${error}`); + if (typeof row?.id === "string" && row.id.trim() !== "") { + if (rowIds.has(row.id)) errors.push(`spec_sheet row ${label}: duplicate id`); + rowIds.add(row.id); + } + for (const [refIndex, ref] of (Array.isArray(row?.check_refs) ? row.check_refs : []).entries()) { + const component = componentsById.get(ref.component_id); + if (!component || !Number.isInteger(ref.check_index) || ref.check_index < 0 || !component.checks?.[ref.check_index]) { + errors.push( + `spec_sheet row ${label}: check_refs[${refIndex}] does not resolve to an existing component check`, + ); + } + } + } + } + for (const iface of interfaces) { const label = `interface ${JSON.stringify(iface?.a)}/${JSON.stringify(iface?.b)}`; if (!ids.has(iface?.a as string) || !ids.has(iface?.b as string)) { diff --git a/packages/client/src/agent/planChecks.ts b/packages/client/src/agent/planChecks.ts index e339211..dd6f76c 100644 --- a/packages/client/src/agent/planChecks.ts +++ b/packages/client/src/agent/planChecks.ts @@ -14,6 +14,7 @@ export const PLAN_CHECK_ENTRY_SCHEMA = Type.Union([ kind: Type.Union([Type.Literal("hole_through"), Type.Literal("hole_blind"), Type.Literal("hole_internal")]), diameter: positive, count: Type.Integer({ minimum: 0 }), + at_mm: Type.Optional(Type.Tuple([Type.Number(), Type.Number(), Type.Number()])), tol: Type.Optional(positive), target, }, @@ -46,6 +47,14 @@ export const PLAN_CHECK_ENTRY_SCHEMA = Type.Union([ }, { additionalProperties: false }, ), + Type.Object( + { + kind: Type.Literal("wall_thickness"), + range_mm: Type.Tuple([positive, positive]), + target, + }, + { additionalProperties: false }, + ), Type.Object( { kind: Type.Union([Type.Literal("count_faces"), Type.Literal("count_edges")]), count, target }, { additionalProperties: false }, @@ -55,6 +64,7 @@ export const PLAN_CHECK_ENTRY_SCHEMA = Type.Union([ kind: Type.Literal("symmetric"), plane: Type.Union([Type.Literal("XY"), Type.Literal("XZ"), Type.Literal("YZ")]), tol_pct: Type.Optional(positive), + target, }, { additionalProperties: false }, ), @@ -62,16 +72,49 @@ export const PLAN_CHECK_ENTRY_SCHEMA = Type.Union([ export type PlanCheckEntry = Static; +export const PLAN_CHECK_REF_SCHEMA = Type.Object( + { + component_id: Type.String({ minLength: 1 }), + check_index: Type.Integer({ minimum: 0 }), + }, + { additionalProperties: false }, +); + +export interface PlanCheckRef { + component_id: string; + check_index: number; +} + +export const PLAN_SPEC_SHEET_ROW_SCHEMA = Type.Object( + { + id: Type.String({ minLength: 1 }), + text: Type.String({ minLength: 1 }), + source: Type.Union([Type.Literal("image"), Type.Literal("text")]), + check_refs: Type.Optional(Type.Array(PLAN_CHECK_REF_SCHEMA)), + unverifiable_reason: Type.Optional(Type.String()), + }, + { additionalProperties: false }, +); + +export interface PlanSpecSheetRow { + id: string; + text: string; + source: "image" | "text"; + check_refs?: PlanCheckRef[]; + unverifiable_reason?: string; +} + const CHECK_KEYS: Record = { - hole_through: { required: ["diameter", "count"], optional: ["tol", "target"] }, - hole_blind: { required: ["diameter", "count"], optional: ["tol", "target"] }, - hole_internal: { required: ["diameter", "count"], optional: ["tol", "target"] }, + hole_through: { required: ["diameter", "count"], optional: ["at_mm", "tol", "target"] }, + hole_blind: { required: ["diameter", "count"], optional: ["at_mm", "tol", "target"] }, + hole_internal: { required: ["diameter", "count"], optional: ["at_mm", "tol", "target"] }, clearance: { required: ["a", "b", "min_mm"], optional: ["max_mm"] }, bbox: { required: ["size_mm"], optional: ["target", "tol"] }, volume: { required: ["range_mm3"], optional: ["target"] }, + wall_thickness: { required: ["range_mm"], optional: ["target"] }, count_faces: { required: ["count"], optional: ["target"] }, count_edges: { required: ["count"], optional: ["target"] }, - symmetric: { required: ["plane"], optional: ["tol_pct"] }, + symmetric: { required: ["plane"], optional: ["target", "tol_pct"] }, }; function isNumber(value: unknown): value is number { @@ -107,6 +150,7 @@ export function validatePlanCheck(value: unknown): string[] { if (kind.startsWith("hole_")) { if (!isNumber(check.diameter) || check.diameter <= 0) errors.push("diameter must be a positive number"); if (!validCount(check.count, false)) errors.push("count must be an integer >= 0"); + if (check.at_mm !== undefined && (!Array.isArray(check.at_mm) || check.at_mm.length !== 3 || check.at_mm.some((v) => !isNumber(v)))) errors.push("at_mm must be three numbers"); if (check.tol !== undefined && (!isNumber(check.tol) || check.tol <= 0)) errors.push("tol must be positive"); } else if (kind === "clearance") { if (typeof check.a !== "string" || !check.a || typeof check.b !== "string" || !check.b) errors.push("a and b must be non-empty strings"); @@ -117,6 +161,8 @@ export function validatePlanCheck(value: unknown): string[] { if (check.tol !== undefined && (!isNumber(check.tol) || check.tol <= 0)) errors.push("tol must be positive"); } else if (kind === "volume") { if (!Array.isArray(check.range_mm3) || check.range_mm3.length !== 2 || check.range_mm3.some((v) => !isNumber(v)) || (isNumber(check.range_mm3?.[0]) && isNumber(check.range_mm3?.[1]) && check.range_mm3[0] > check.range_mm3[1])) errors.push("range_mm3 must be [min, max] with min <= max"); + } else if (kind === "wall_thickness") { + if (!Array.isArray(check.range_mm) || check.range_mm.length !== 2 || check.range_mm.some((v) => !isNumber(v) || v <= 0) || (isNumber(check.range_mm?.[0]) && isNumber(check.range_mm?.[1]) && check.range_mm[0] > check.range_mm[1])) errors.push("range_mm must be [min, max] with 0 < min <= max"); } else if (kind === "count_faces" || kind === "count_edges") { if (!validCount(check.count, true)) errors.push("count must be an integer >= 0 or [min, max]"); } else if (kind === "symmetric") { @@ -126,3 +172,39 @@ export function validatePlanCheck(value: unknown): string[] { if (check.target !== undefined && (typeof check.target !== "string" || !check.target)) errors.push("target must be a non-empty string"); return errors; } + +/** Runtime mirror for spec-sheet rows so update_plan can return row-level errors. */ +export function validatePlanSpecSheetRow(value: unknown): string[] { + if (!value || typeof value !== "object" || Array.isArray(value)) return ["must be an object"]; + const row = value as Record; + const errors: string[] = []; + if (typeof row.id !== "string" || row.id.trim() === "") errors.push("id must be a non-empty string"); + if (typeof row.text !== "string" || row.text.trim() === "") errors.push("text must be a non-empty string"); + if (row.source !== "image" && row.source !== "text") errors.push('source must be "image" or "text"'); + if (row.check_refs !== undefined && !Array.isArray(row.check_refs)) { + errors.push("check_refs must be an array"); + } else { + for (const [index, valueRef] of ((row.check_refs as unknown[] | undefined) ?? []).entries()) { + if (!valueRef || typeof valueRef !== "object" || Array.isArray(valueRef)) { + errors.push(`check_refs[${index}] must be an object`); + continue; + } + const ref = valueRef as Record; + if (typeof ref.component_id !== "string" || ref.component_id.trim() === "") { + errors.push(`check_refs[${index}].component_id must be a non-empty string`); + } + if (!Number.isInteger(ref.check_index) || (ref.check_index as number) < 0) { + errors.push(`check_refs[${index}].check_index must be an integer >= 0`); + } + } + } + if (row.unverifiable_reason !== undefined && typeof row.unverifiable_reason !== "string") { + errors.push("unverifiable_reason must be a string"); + } + const hasChecks = Array.isArray(row.check_refs) && row.check_refs.length > 0; + const hasReason = typeof row.unverifiable_reason === "string" && row.unverifiable_reason.trim() !== ""; + if (!hasChecks && !hasReason) { + errors.push("provide non-empty check_refs or a non-empty unverifiable_reason"); + } + return errors; +} diff --git a/packages/client/src/agent/prompt.test.ts b/packages/client/src/agent/prompt.test.ts index f78ef0c..b3c8647 100644 --- a/packages/client/src/agent/prompt.test.ts +++ b/packages/client/src/agent/prompt.test.ts @@ -2,6 +2,13 @@ import { describe, expect, it } from "vitest"; import { systemPrompt } from "./prompt"; describe("systemPrompt", () => { + it("defines Chamfer as a multimodal CAD designer with outcome-first success criteria", () => { + expect(systemPrompt).toContain("creates precise, manufacturable models from text, images, or both"); + expect(systemPrompt).toContain("## Goal and Success Criteria"); + expect(systemPrompt).toContain("image-based requests account for all readable visual evidence"); + expect(systemPrompt).toContain("Choose the fewest useful tool loops"); + }); + it("documents the allowed build123d API surface", () => { expect(systemPrompt).toContain("## Allowed API Surface"); expect(systemPrompt).toContain("Builders: BuildPart, BuildSketch, BuildLine"); @@ -10,7 +17,7 @@ describe("systemPrompt", () => { }); it("contains a concrete DO NOT list for runtime-unsafe behavior", () => { - expect(systemPrompt).toContain("## DO NOT"); + expect(systemPrompt).toContain("## Runtime Boundaries"); expect(systemPrompt).toContain("Do not use file I/O, network I/O, subprocesses"); expect(systemPrompt).toContain("Do not call show, show_object"); expect(systemPrompt).toContain("Do not rely on state, variables, files, or geometry from a previous run_build123d call"); @@ -30,9 +37,12 @@ describe("systemPrompt", () => { it("specifies the agent-authored checks block and its full vocabulary", () => { expect(systemPrompt).toContain("# --- checks ---"); expect(systemPrompt).toContain("CHECKS = ["); - for (const kind of ["hole_through", "hole_blind", "clearance", "bbox", "volume", "count_faces", "count_edges", "symmetric"]) { + for (const kind of ["hole_through", "hole_blind", "hole_internal", "clearance", "bbox", "volume", "wall_thickness", "count_faces", "count_edges", "symmetric"]) { expect(systemPrompt).toContain(kind); } + expect(systemPrompt).toContain("at_mm [x, y, z]"); + expect(systemPrompt).toContain("symmetric"); + expect(systemPrompt).toContain("optional target (child label)"); expect(systemPrompt).toContain("never weaken or delete a check to make the gate pass"); }); @@ -48,6 +58,12 @@ describe("systemPrompt", () => { expect(systemPrompt).toContain("never stop after the first successful intermediate result"); }); + it("defines how image evidence and text are reconciled", () => { + expect(systemPrompt).toContain("treat the image as design evidence, not decoration"); + expect(systemPrompt).toContain("explicit text overrides an ambiguous visual inference"); + expect(systemPrompt).toContain("Do not invent hidden geometry"); + }); + it("points verification at the new diagnostics", () => { expect(systemPrompt).toContain("holes (every detected bore"); expect(systemPrompt).toContain("clearances (pairwise child states)"); diff --git a/packages/client/src/agent/prompt.ts b/packages/client/src/agent/prompt.ts index f020d87..23db84e 100644 --- a/packages/client/src/agent/prompt.ts +++ b/packages/client/src/agent/prompt.ts @@ -1,8 +1,21 @@ import { DOC_TOPICS } from "./tools/lookupDocs"; -export const systemPrompt = `You are Chamfer, a text-to-CAD agent that creates precise, manufacturable models with build123d. +export const systemPrompt = `You are Chamfer, an AI CAD designer that creates precise, manufacturable models from text, images, or both using build123d. + +## Goal and Success Criteria + +Resolve the user's CAD request end to end by building and verifying real geometry, not merely describing code. +Success means: +- the final geometry represents every requested part, feature, dimension, relationship, and manufacturing constraint; +- user-supplied values are preserved, while genuinely unspecified values use explicit, reasonable assumptions; +- image-based requests account for all readable visual evidence, including dimensions, tolerances, notes, tables, repeated features, and spatial relationships; +- the verify gate passes and the measurements and inspection views support completion; and +- the final response concisely reports the result, measured overall dimensions, and important assumptions. + +Choose the fewest useful tool loops, but never let loop minimization outrank geometry correctness or required evidence. +Ask a question only when a missing or conflicting requirement materially changes the design and cannot be resolved from the request. +Otherwise make an explicit engineering assumption and continue. -Use the available CAD tools to build and verify real geometry instead of merely describing code. Your runtime is Pyodide with build123d and OCP.wasm. Each run_build123d call executes one fresh Python script in a fresh namespace. There is no persistent REPL state between calls. @@ -43,7 +56,6 @@ EXPECT must be one literal dict with exactly these keys (bodies and bbox_mm are Derive the values from the user's request before writing any geometry; if the user gave no dimensions, choose reasonable ones and declare them. Chamfer verifies the produced geometry against EXPECT after every run (the verify gate) and additionally checks that the result is a valid, non-degenerate B-rep. The bounding box is compared with sorted dimensions, so axis orientation never causes a false failure. -A missing or malformed expect block is itself a gate failure. After the expect block, encode the user's acceptance criteria in a checks block (test-driven CAD): @@ -55,27 +67,33 @@ CHECKS = [ # --- end checks --- CHECKS must be one literal list of dicts. Available kinds: -- hole_through / hole_blind / hole_internal: diameter, count, optional tol (default 0.5), optional target (child label) — counts detected cylindrical bores at that diameter. With target the census runs on that child alone, so a bore occupied or capped by a neighbouring part still classifies by the component's own geometry; hole_internal counts bores buried inside material at both ends. -- clearance: a, b (child labels), min_mm, optional max_mm — gap between two children; interpenetration always fails; max_mm 0 asserts touching, [min_mm, max_mm] asserts a controlled fit. +- hole_through / hole_blind / hole_internal: diameter, count, optional at_mm [x, y, z], optional tol (default 0.5), optional target (child label) - counts detected cylindrical bores at that diameter. With at_mm, only bores whose axis center is within tol of that anchor match. With target the census runs on that child alone, so a bore occupied or capped by a neighbouring part still classifies by the component's own geometry; hole_internal counts bores buried inside material at both ends. +- clearance: a, b (child labels), min_mm, optional max_mm - gap between two children; interpenetration always fails; max_mm 0 asserts touching, [min_mm, max_mm] asserts a controlled fit. - bbox: size_mm [x, y, z], optional target (child label), optional tol — sorted comparison like EXPECT. - volume: range_mm3 [min, max], optional target. +- wall_thickness: range_mm [min, max], optional target (child label) - casts inward from sampled faces; every measured thickness must be in range. - count_faces / count_edges: count (exact int or [min, max]), optional target. -- symmetric: plane "XY", "XZ", or "YZ", optional tol_pct (default 1.0). +- symmetric: plane "XY", "XZ", or "YZ", optional tol_pct (default 1.0), optional target (child label). -Before writing any geometry, enumerate every feature the user asked for (each hole pattern, pocket, boss, slot, fit, symmetry) and encode each as a CHECKS entry; the gate evaluates them all on every run. +Encode every requested feature (hole pattern, pocket, boss, slot, fit, symmetry) as a CHECKS entry before building. Give Compound children stable labels (part.label = "lid") so clearance, bbox, and volume checks can reference them. -A malformed checks block is a gate failure; omitting the block entirely is allowed only for trivially simple single-feature parts. Checks exist to catch your own mistakes: never weaken or delete a check to make the gate pass; change one only when it genuinely misread the request, and say so. -## Planning (multi-component designs) +## Planning -If the request contains two or more distinct components, or you expect more than one script to complete it, call update_plan BEFORE writing any geometry: restate the goal, list every component with its target bbox and CHECKS, and declare the interfaces that hold the assembly together. -Every component's checks MUST include a volume check targeting it ({"kind": "volume", "range_mm3": [lo, hi], "target": ""}) with a range about ±10% around the volume you derive from its intended dimensions (walls, floors, flanges, minus cavities and holes). -Volume is the cheapest topology detector: a cavity accidentally sealed shut, a missing pocket, or an over-deep cut shifts the measured volume immediately, while feature counts and bounding boxes stay silent. Do the arithmetic honestly - a range wide enough to cover both the right and the wrong topology is rejected. +For an image-based request, treat the image as design evidence, not decoration. +Infer the intended 3D form from all supplied views and reconcile image evidence with the user's text; explicit text overrides an ambiguous visual inference, but never silently overrides a clear conflict. +Publish a valid update_plan before run_build123d, even for one component; the loop rejects earlier runs. +Its spec_sheet must restate, in your own words, every readable dimension, tolerance, feature, note, and table row - omit nothing - as {id, text, source: "image"|"text"} rows, each carrying non-empty check_refs ({"component_id", "check_index"} resolving to an existing check) or an unverifiable_reason the user will see. +Do not invent hidden geometry that the supplied views cannot establish. +When hidden geometry is required to make a manufacturable model, use the smallest explicit assumption consistent with the visible evidence. + +If the request contains two or more distinct components, or you expect more than one script to complete it, call update_plan before writing geometry: restate the goal, list every component with its target bbox and CHECKS, and declare the interfaces that hold the assembly together. +Every component's checks must include a volume check targeting it ({"kind": "volume", "range_mm3": [lo, hi], "target": ""}) with a range about ±10% around the volume you derive from its intended dimensions (walls, floors, flanges, minus cavities and holes). +Use a discriminating range; cavities, pockets, and cuts must measurably affect it. Decompose along the interfaces: decide the mating dimensions, shared datums, and clearances first, define them once as named parameters, and derive every component from them. Every component must be located and retained by something - contact, fastener, or captivity; if the user's request leaves a part unsupported, say so and ask instead of building it floating. -Build one component at a time: declare the component in the script (see COMPONENT below), pass its planned checks through the gate, then record the progress by calling update_plan with that component marked done. -Marking done is evidence-checked - it is accepted only after a gate-passed run declared the component and ran its planned checks - so build the evidence first; never try to talk a component into being finished. +Build one component at a time, pass its planned checks, then mark it done with update_plan. Revise the plan when the decomposition genuinely changes, but never delete or shrink an unfinished component to escape a failing build: abandoning one requires an explicit reason the user will see. Finish with an assembly script that declares all components, labels the Compound children, and whose CHECKS contain each plan interface's clearance entry verbatim ({"kind": "clearance", "a": ..., "b": ..., "min_mm": ..., "max_mm": ...} exactly as planned): the plan only counts as finished once one gate-passed run declared all components AND ran every interface check. @@ -85,8 +103,7 @@ Declare which plan component a script builds with a component block after the ch COMPONENT = "lid" # --- end component --- -Use the component id from the plan; an assembly script lists all of them (COMPONENT = ["base", "lid"]). -Label the geometry with the same id (result.label = "base" on a single-component run, part.label on Compound children) so the component's targeted checks resolve identically in both contexts. +Use plan component ids; an assembly lists all of them (COMPONENT = ["base", "lid"]). Label geometry with the same ids. For a diagnostic run that only probes behavior and is not a deliverable, declare COMPONENT = "probe": probe runs never advance the plan, never replace the current model shown to the user, and do not count against a component's run budget. Simple single-part requests need no plan and no component block; everything behaves as before. @@ -104,11 +121,11 @@ Prefer this stable build123d surface: - Enums and selectors: Mode, Align, Keep, Select, edges(), faces(), solids(), filter_by(...), sort_by(...), group_by(...). - Shape composition: Part algebra with +, -, and &, translate(...), rotate(...), Compound(children=[...]). -Use lookup_docs for details instead of guessing at uncommon build123d APIs. -Available documentation topics: ${DOC_TOPICS.join(", ")}. -Look up docs before using an unfamiliar operation, after any API-related traceback, or when selecting edges/faces for fillets, chamfers, holes, or splits. +Use search_docs for build123d API usage and errors instead of guessing: query with short API names, operation verbs, or raw traceback text, and reformulate if the titled results miss. +lookup_docs serves Chamfer's curated technique cards on runtime-specific practices; read one when selecting edges/faces for fillets, chamfers, holes, or splits. +Available topics: ${DOC_TOPICS.join(", ")}. -## DO NOT +## Runtime Boundaries - Do not use file I/O, network I/O, subprocesses, package installation, or environment access. - Do not call show, show_object, ocp_vscode, Jupyter, matplotlib, display, viewer, render, export_step, export_stl, export_svg, import_step, import_stl, or import_svg. @@ -123,17 +140,13 @@ Look up docs before using an unfamiliar operation, after any API-related traceba ## Modeling Discipline -Work the way experienced build123d engineers do: - Resolve geometry in two dimensions before three. Build profiles with BuildLine and BuildSketch, resolve overlaps and interior cutouts at the sketch level, then extrude, revolve, loft, or sweep once. -Fixing a 2D mistake with 3D booleans is the most failure-prone way to model. Apply fillets and chamfers last, after every structural boolean is stable: early edge blending converts simple faces to splines, slows every later boolean, and breaks selectors. Select topology with geometric queries, never raw indices: filter_by, sort_by, group_by, and Select.LAST/Select.NEW (e.g. faces().sort_by(Axis.Z)[-1] for the top face); a bare edges()[3] silently picks a different edge whenever the model changes. Exploit symmetry: model the smallest unique sector and complete it with mirror, PolarLocations, or GridLocations instead of repeating features by hand. Derive every dimension in the geometry from the named parameters or arithmetic on them; magic numbers in the body are a defect. -Build bottom-up from named dimensions and named components. Use millimetres unless the user explicitly requests another unit. Preserve the user's requested coordinate system and orientation. Prefer robust, explicit build123d operations over visually guessed meshes. @@ -141,34 +154,28 @@ Extend subtractive tools slightly through the target to avoid coincident faces. Keep subtractive tools scoped to the feature they cut: a bore that only needs to pass through two walls must not also gouge flanges, seals, or unrelated faces on its way through. Use Compound only when the requested object contains distinct non-fused components. Otherwise return a single fused Part or Shape. -In an assembly, every component must be physically held: resting contact, fasteners through aligned holes, or captive placement. A part floating in space with no interface to its neighbors is a defect even when its own dimensions are perfect. ## Verification Discipline After every run_build123d result, inspect stdout, measurements, and the attached multi-view sheet before deciding what to do next. -If execution fails, read the full traceback and fix the first real cause. -If an API name, selector, or operation is uncertain, call lookup_docs before rewriting. +If execution fails, read the full traceback and fix the first real cause; call search_docs when the API is the uncertainty. For every successful run: - Inspect every view one at a time: isometric, front, back, left, right, top, and bottom. - Compare bboxMm, volumeMm3, areaMm2, and child measurements against the requested dimensions and component count. - Read the diagnostics in measurements: topology (face/edge/vertex/shell counts), holes (every detected bore with diameter, depth, and through/blind/internal classification), and clearances (pairwise child states). A hole the user wants to go through must report kind "through"; interpenetrating children are a defect unless the user asked for fused geometry. -- If measurements list a "floating" entry, those children touch nothing: an unsupported part is a defect unless the user explicitly wants it detached — fix the geometry or ask, never ignore it. +- If measurements list a "floating" entry, those children touch nothing: an unsupported part is a defect unless the user explicitly wants it detached; fix the geometry or ask, never ignore it. - Numerically check each requested width, height, depth, diameter, radius, wall thickness, offset, spacing, count, and angle that can be inferred from the returned measurements. - Check visible topology: holes are open, counterbores are on the correct face, fillets and chamfers affect the intended edges, booleans did not leave extra blocks, and mirrored or repeated features are symmetric. -- Before rewriting, briefly state concrete discrepancies such as missing features, wrong orientation, incorrect proportions, interference, asymmetric placement, or numeric mismatch. - Only claim what the cited evidence can actually show: a view cannot confirm a feature another part occludes (a lid hides the cavity under it), and a loose volume range cannot confirm topology. When a requested feature is hidden in the assembly, verify it with a per-component run (COMPONENT-declared) where it is visible and measurable. -- Then submit a complete corrected script, not a patch or fragment. Every run_build123d result includes a verify-gate verdict covering EXPECT, B-rep validity, and your CHECKS. -While the gate reports FAILED you must not declare success or present the model as finished: fix the geometry (or correct a genuinely wrong expectation, stating why) and run again. +While the gate reports FAILED, fix the geometry or a genuinely wrong expectation and run again; do not declare success. If the gate reports unavailable, fall back to the inspection sheet and measurements alone. A passing gate on a partial model is not completion: the gate only confirms the current script matches its own EXPECT and CHECKS blocks, and completion means the CHECKS list that encodes the FULL request passes. -When the request has several parts, features, or steps, keep iterating after each intermediate gate pass until every one is built and verified; never stop after the first successful intermediate result. -Before stopping, enumerate every part, feature, and step of the user's request and confirm each one is present in the measured geometry, the diagnostics, and the views. +For multi-part or multi-feature requests, never stop after the first successful intermediate result. Stop only when the verify gate passes, every view and the measured dimensions match the request, and that checklist has no missing items. Use no more than 10 run_build123d calls in one user turn. If the model cannot be completed within that limit, explain the remaining discrepancy honestly instead of claiming success. -When the model is complete, respond with a concise summary of the final geometry, its measured overall dimensions, and any important assumptions. Do not expose private chain-of-thought.`; diff --git a/packages/client/src/agent/session.test.ts b/packages/client/src/agent/session.test.ts index 6b63756..0386682 100644 --- a/packages/client/src/agent/session.test.ts +++ b/packages/client/src/agent/session.test.ts @@ -724,6 +724,85 @@ describe("createSession agent-loop policies", () => { }; } + it("blocks run_build123d for an image turn until update_plan accepts a spec-sheet plan", async () => { + const { tool, execute } = gateTool("failed"); + const plan = { + goal: "single image-derived spacer", + components: [ + { + id: "spacer", + description: "10 mm cube spacer shown in the image", + bbox_mm: [10, 10, 10], + status: "todo", + free_floating_reason: "single component", + checks: [{ kind: "volume", range_mm3: [900, 1100], target: "spacer" }], + }, + ], + interfaces: [], + spec_sheet: [ + { + id: "cube-size", + text: "The image shows a 10 mm cube.", + source: "image", + check_refs: [{ component_id: "spacer", check_index: 0 }], + }, + ], + }; + const updatePlanCall: AssistantMessage = { + ...textMessage("", "toolUse"), + content: [{ type: "toolCall", id: "plan-1", name: "update_plan", arguments: plan }], + }; + const { streamFn } = makeScriptedStreamFn([ + toolCallMessage("run-before-plan"), + updatePlanCall, + toolCallMessage("run-after-plan"), + textMessage("The planned CAD run completed."), + textMessage("No more work this turn."), + ]); + const session = createSession({ + conversationId: "conv-1", + modelJson: JSON.stringify(FAKE_MODEL), + systemPrompt, + tools: [tool], + priorMessages: [], + __streamFn: streamFn as never, + } as unknown as Parameters[0]); + + let latest: SessionState | undefined; + session.subscribe((state) => (latest = state)); + await session.send("Build the dimensioned part in this image", [new File(["image"], "drawing.png", { type: "image/png" })]); + + expect(execute).toHaveBeenCalledTimes(1); + const rejectedRun = (latest?.messages ?? []).find((message) => { + const result = message as { role?: string; toolCallId?: string }; + return result.role === "toolResult" && result.toolCallId === "run-before-plan"; + }) as { isError?: boolean; content?: Array<{ text?: string }> } | undefined; + expect(rejectedRun?.isError).toBe(true); + expect(rejectedRun?.content?.[0]?.text).toContain("update_plan"); + expect(rejectedRun?.content?.[0]?.text).toContain("spec sheet"); + expect(rejectedRun?.content?.[0]?.text).toContain("every readable dimension, feature, and spec-table row"); + }); + + it("does not apply the plan gate to a text-only turn", async () => { + const { tool, execute } = gateTool("failed"); + const { streamFn } = makeScriptedStreamFn([ + toolCallMessage("text-run"), + textMessage("The CAD run completed."), + ]); + const session = createSession({ + conversationId: "conv-1", + modelJson: JSON.stringify(FAKE_MODEL), + systemPrompt, + tools: [tool], + priorMessages: [], + __streamFn: streamFn as never, + } as unknown as Parameters[0]); + + await session.send("Build a text-only box"); + + expect(execute).toHaveBeenCalledTimes(1); + }); + it("injects the self-check once after a gate pass and lets the agent continue", async () => { const { tool } = gateTool("passed"); const { streamFn, turnContexts } = makeScriptedStreamFn([ diff --git a/packages/client/src/agent/session.ts b/packages/client/src/agent/session.ts index 0bb6afa..58e77cf 100644 --- a/packages/client/src/agent/session.ts +++ b/packages/client/src/agent/session.ts @@ -113,6 +113,9 @@ export const PLAN_NUDGE_MARKER = "[Chamfer plan check]"; * component bucket individually stays within maxCadRuns. */ export const PLAN_BUDGET_CEILING_FACTOR = 3; +export const IMAGE_PLAN_GATE_ERROR = + "run_build123d is blocked for this image-triggered design request. Call update_plan first with a valid plan. The plan must include the goal, components with acceptance checks, interfaces, and a spec sheet in your own words that enumerates every readable dimension, feature, and spec-table row from the image. Each spec-sheet row must use non-empty check_refs that resolve to component checks, or a non-empty unverifiable_reason."; + export function buildPlanNudgePrompt(incomplete: readonly { id: string; status: string }[]): string { const list = incomplete.map((c) => `"${c.id}" (${c.status})`).join(", "); return `${PLAN_NUDGE_MARKER} The plan still has unfinished components: ${list}. A component only counts as done after a gate-passed run declares it via COMPONENT and passes its planned checks, and update_plan records it. Continue with the next unfinished component now, or - only if the request genuinely changed - revise the plan with update_plan and state why. Do not stop while the plan has unfinished components and budget remains.`; @@ -188,11 +191,18 @@ export function createSession(opts: CreateSessionOptions): ChatSession { }, }); + let imagePlanRequiredThisTurn = false; + let imagePlanAcceptedThisTurn = false; + // update_plan validates against the live transcript (latest plan + gate evidence), // so it is session-owned: the closure resolves to the agent created just below. let agentForPlanTool: Agent | undefined; const planTool = createUpdatePlanTool({ getMessages: () => agentForPlanTool?.state.messages ?? [], + requireSpecSheet: () => imagePlanRequiredThisTurn, + onAccepted: () => { + imagePlanAcceptedThisTurn = true; + }, }) as unknown as AgentTool; const agent = new Agent({ @@ -202,6 +212,12 @@ export function createSession(opts: CreateSessionOptions): ChatSession { tools: [...((opts.tools ?? []) as AgentTool[]), planTool], }, streamFn, + beforeToolCall: async ({ toolCall }) => { + if (toolCall.name === "run_build123d" && imagePlanRequiredThisTurn && !imagePlanAcceptedThisTurn) { + return { block: true, reason: IMAGE_PLAN_GATE_ERROR }; + } + return undefined; + }, // The persisted transcript is the source of truth; what the model sees is the // policy-transformed view (stale view sheets stubbed, compacted history windowed). transformContext: async (messages) => transformLlmContext(messages), @@ -427,6 +443,8 @@ export function createSession(opts: CreateSessionOptions): ChatSession { selfCheckArmed = true; cadRunsByBucket.clear(); planNudgedWithoutRun = false; + imagePlanRequiredThisTurn = Boolean(images?.length); + imagePlanAcceptedThisTurn = false; // Compaction runs between turns, before the prompt: when the LLM-visible context // is near the window, older history is summarized into a persisted compaction // row. Failures are non-fatal - the turn proceeds on the uncompacted context. diff --git a/packages/client/src/agent/tools/searchDocs.test.ts b/packages/client/src/agent/tools/searchDocs.test.ts new file mode 100644 index 0000000..0070f42 --- /dev/null +++ b/packages/client/src/agent/tools/searchDocs.test.ts @@ -0,0 +1,111 @@ +import { readFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import MiniSearch from "minisearch"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { DOC_INDEX_OPTIONS } from "../docSearchConfig"; +import { createSearchDocsTool } from "./searchDocs"; + +function indexResponse() { + const index = new MiniSearch(DOC_INDEX_OPTIONS); + index.addAll([ + { + section_id: "introductory-examples#24-loft", + title: "24. Loft", + body: "Loft joins dissimilar cross sections on parallel workplanes.", + api_names: "loft BuildSketch Plane", + synonyms: "blend transition", + }, + { + section_id: "introductory-examples#23-revolve", + title: "23. Revolve", + body: "Revolve a connected sketch around an axis.", + api_names: "revolve Axis", + synonyms: "turn lathe", + }, + ]); + return new Response( + JSON.stringify({ + format_version: 1, + attribution: { + project: "build123d", + version: "0.11.1", + source: "https://github.com/gumyr/build123d/tree/v0.11.1/docs", + license: "Apache-2.0", + }, + index: index.toJSON(), + }), + { status: 200 }, + ); +} + +describe("search_docs tool", () => { + afterEach(() => vi.unstubAllGlobals()); + + it("returns ranked titled sections and structured retrieval details", async () => { + const fetchMock = vi.fn().mockResolvedValue(indexResponse()); + vi.stubGlobal("fetch", fetchMock); + const tool = createSearchDocsTool(); + + const result = await tool.execute("search-1", { query: "loft between cross sections" }); + + expect(fetchMock).toHaveBeenCalledWith("/docs/build123d-index.json"); + expect(result.content[0]).toEqual({ + type: "text", + text: expect.stringMatching(/# build123d documentation search.*## 24\. Loft.*cross sections/s), + }); + expect(result.details).toEqual({ + query: "loft between cross sections", + results: [ + { + section_id: "introductory-examples#24-loft", + score: expect.any(Number), + }, + ], + }); + expect(tool.description).toMatch(/API names.*operation verbs.*traceback/i); + }); + + it("returns an empty titled result that invites reformulation", async () => { + vi.stubGlobal("fetch", vi.fn().mockResolvedValue(indexResponse())); + const tool = createSearchDocsTool(); + + const result = await tool.execute("search-2", { query: "zzzzquuxnotacapterm" }); + + expect(result.content[0]).toEqual({ + type: "text", + text: expect.stringMatching(/^# build123d documentation search.*No matching sections.*Reformulate/is), + }); + expect(result.details).toEqual({ query: "zzzzquuxnotacapterm", results: [] }); + }); + + it("retries the index load after a failed fetch instead of caching the rejection", async () => { + const fetchMock = vi + .fn() + .mockRejectedValueOnce(new Error("network down")) + .mockResolvedValue(indexResponse()); + vi.stubGlobal("fetch", fetchMock); + const tool = createSearchDocsTool(); + + await expect(tool.execute("search-fail", { query: "loft" })).rejects.toThrow("network down"); + + const result = await tool.execute("search-retry", { query: "loft between cross sections" }); + expect(result.details.results.length).toBeGreaterThan(0); + expect(fetchMock).toHaveBeenCalledTimes(2); + }); + + it("returns the loft teaching section in the top 3 from the committed index", async () => { + const asset = readFileSync( + join(dirname(fileURLToPath(import.meta.url)), "../../../public/docs/build123d-index.json"), + "utf8", + ); + vi.stubGlobal("fetch", vi.fn().mockResolvedValue(new Response(asset, { status: 200 }))); + const tool = createSearchDocsTool(); + + const result = await tool.execute("search-3", { query: "loft between cross sections" }); + + expect(result.details.results.slice(0, 3).map(({ section_id }) => section_id)).toContain( + "introductory-examples#24-loft", + ); + }); +}); diff --git a/packages/client/src/agent/tools/searchDocs.ts b/packages/client/src/agent/tools/searchDocs.ts new file mode 100644 index 0000000..2ee13be --- /dev/null +++ b/packages/client/src/agent/tools/searchDocs.ts @@ -0,0 +1,73 @@ +import type { AgentTool } from "@earendil-works/pi-agent-core"; +import { Type } from "@earendil-works/pi-ai"; +import MiniSearch, { type SearchResult } from "minisearch"; +import { DOC_INDEX_OPTIONS, DOC_SEARCH_OPTIONS } from "../docSearchConfig"; + +const INDEX_URL = "/docs/build123d-index.json"; +const TOP_K = 5; +const MAX_SECTION_CHARS = 6_000; +const parameters = Type.Object({ + query: Type.String({ + description: "Short keyword query using API names, operation verbs, or raw traceback text.", + }), +}); + +interface SearchDetails { + query: string; + results: Array<{ section_id: string; score: number }>; +} + +function resultText(query: string, results: SearchResult[]): string { + const heading = `# build123d documentation search: "${query}"`; + if (results.length === 0) { + return `${heading}\n\nNo matching sections. Reformulate with an API name, operation verb, or raw traceback text.`; + } + const sections = results.map((result) => { + const body = String(result.body ?? ""); + const displayed = body.length > MAX_SECTION_CHARS ? `${body.slice(0, MAX_SECTION_CHARS)}\n\n[Section truncated]` : body; + return `## ${String(result.title)}\nSection ID: ${String(result.id)}\n\n${displayed}`; + }); + return `${heading}\n\n${sections.join("\n\n")}`; +} + +export function createSearchDocsTool(): AgentTool { + let indexPromise: Promise | undefined; + const loadIndex = () => { + // A rejected load must not stick: drop the cached promise so the next call + // retries instead of failing every future search on one transient fetch error. + indexPromise ??= fetch(INDEX_URL) + .then(async (response) => { + if (!response.ok) throw new Error(`Failed to load build123d documentation index: ${response.status}`); + const asset = await response.json() as { index?: unknown }; + if (!asset.index) throw new Error("Build123d documentation index is malformed"); + return MiniSearch.loadJS(asset.index as Parameters[0], DOC_INDEX_OPTIONS); + }) + .catch((error: unknown) => { + indexPromise = undefined; + throw error; + }); + return indexPromise; + }; + + return { + name: "search_docs", + label: "Search build123d docs", + description: + "Search the full bundled build123d documentation. Use a short keyword query made of API names, operation verbs, or raw traceback text. Read the titled results, and reformulate when none match.", + parameters, + execute: async (_toolCallId, { query }) => { + const normalizedQuery = query.trim(); + const index = await loadIndex(); + const results = normalizedQuery + ? index.search(normalizedQuery, DOC_SEARCH_OPTIONS).slice(0, TOP_K) + : []; + return { + content: [{ type: "text", text: resultText(normalizedQuery, results) }], + details: { + query: normalizedQuery, + results: results.map((result) => ({ section_id: String(result.id), score: result.score })), + }, + }; + }, + }; +} diff --git a/packages/client/src/agent/tools/updatePlan.ts b/packages/client/src/agent/tools/updatePlan.ts index 2331fe7..c232d72 100644 --- a/packages/client/src/agent/tools/updatePlan.ts +++ b/packages/client/src/agent/tools/updatePlan.ts @@ -11,6 +11,7 @@ import { type Plan, } from "../plan"; import { PLAN_CHECK_ENTRY_SCHEMA } from "../planChecks"; +import { PLAN_SPEC_SHEET_ROW_SCHEMA } from "../planChecks"; const component = Type.Object({ id: Type.String({ @@ -60,6 +61,12 @@ const parameters = Type.Object({ description: "Physical relations that hold the assembly together. Every non-free-floating component must appear in at least one, and the graph must be connected.", }), + spec_sheet: Type.Optional( + Type.Array(PLAN_SPEC_SHEET_ROW_SCHEMA, { + description: + "The agent's own reading of every dimension, feature, and spec-table row visible in the request image. Each row links to component checks by component_id and zero-based check_index, or states why it is unverifiable.", + }), + ), }); /** @@ -71,12 +78,16 @@ const parameters = Type.Object({ export function createUpdatePlanTool(deps: { /** Live view of the session transcript (agent.state.messages). */ getMessages: () => readonly unknown[]; + /** Whether the pending user turn contains an image and therefore requires a spec sheet. */ + requireSpecSheet?: () => boolean; + /** Notifies the session only after a snapshot has passed validation. */ + onAccepted?: (plan: Plan) => void; }): AgentTool { return { name: UPDATE_PLAN_TOOL_NAME, label: "Update plan", description: - "Create or revise the design plan for a multi-component request: the component list, per-component checks, and the interfaces that hold the assembly together. Submit the complete plan every time (never a delta). Call it before writing any geometry when the request has two or more distinct components or needs more than one script, and again whenever the decomposition changes or a component is finished.", + "Create or revise the complete design plan: goal, components, per-component checks, interfaces, and the image spec sheet when required. For an image request, call this before run_build123d and enumerate every readable dimension, feature, note, and spec-table row in spec_sheet. Each spec row must link to an existing component check with {component_id, check_index}, or state a non-empty unverifiable_reason. Submit the complete plan every time, never a delta.", parameters, execute: async (_toolCallId, args) => { const messages = deps.getMessages(); @@ -85,10 +96,12 @@ export function createUpdatePlanTool(deps: { next, previous: latestPlan(messages), evidence: collectComponentEvidence(messages), + requireSpecSheet: deps.requireSpecSheet?.() ?? false, }); if (errors.length > 0) { throw new Error(`Plan rejected:\n${errors.map((e) => `- ${e}`).join("\n")}`); } + deps.onAccepted?.(next); return { content: [ { diff --git a/packages/client/src/cad/cad.worker.ts b/packages/client/src/cad/cad.worker.ts index 4693552..5ea5537 100644 --- a/packages/client/src/cad/cad.worker.ts +++ b/packages/client/src/cad/cad.worker.ts @@ -1,4 +1,5 @@ import type { CadBootStatus, CadRequest, CadResponse } from "@chamfer/shared"; +import { BUILD123D_VERSION } from "./versions"; // Pyodide runtime version. Must match a Python ABI that OCP.wasm publishes // wheels for (see packages/client/public/py/bootstrap.py header for the @@ -14,7 +15,6 @@ import type { CadBootStatus, CadRequest, CadResponse } from "@chamfer/shared"; // worker and matches OCP.wasm's cp313 emscripten wheels. const PYODIDE_VERSION = "0.29.4"; const PYODIDE_URL = `https://cdn.jsdelivr.net/pyodide/v${PYODIDE_VERSION}/full/`; -const BUILD123D_VERSION = "0.11.1"; const PACKAGE_CACHE_DIR = "/chamfer-cache"; const PACKAGE_CACHE_FILE = `${PACKAGE_CACHE_DIR}/cad-packages-${PYODIDE_VERSION}-${BUILD123D_VERSION}.zip`; diff --git a/packages/client/src/cad/versions.ts b/packages/client/src/cad/versions.ts new file mode 100644 index 0000000..2ae2024 --- /dev/null +++ b/packages/client/src/cad/versions.ts @@ -0,0 +1 @@ +export const BUILD123D_VERSION = "0.11.1"; diff --git a/packages/client/src/components/PlanCard.test.tsx b/packages/client/src/components/PlanCard.test.tsx index 54dee27..71e95f8 100644 --- a/packages/client/src/components/PlanCard.test.tsx +++ b/packages/client/src/components/PlanCard.test.tsx @@ -11,6 +11,20 @@ const plan: Plan = { { id: "rib", description: "stiffening rib", status: "abandoned", abandon_reason: "user removed it" }, ], interfaces: [{ a: "base", b: "lid", kind: "clearance", min_mm: 0, max_mm: 0 }], + spec_sheet: [ + { + id: "housing-volume", + text: "The housing base has a bounded material volume.", + source: "image", + check_refs: [{ component_id: "base", check_index: 0 }], + }, + { + id: "surface-finish", + text: "The drawing specifies a matte surface finish.", + source: "image", + unverifiable_reason: "The geometry kernel cannot measure surface finish.", + }, + ], }; describe("PlanCard", () => { @@ -33,4 +47,30 @@ describe("PlanCard", () => { expect(iface.textContent).toContain("base·lid"); expect(iface.textContent).toContain("≤0mm"); }); + + it("expanded: links spec rows to component checks and distinguishes unverifiable rows", () => { + const planWithChecks: Plan = { + ...plan, + components: plan.components.map((component) => + component.id === "base" + ? { + ...component, + checks: [{ kind: "volume", range_mm3: [5000, 6000], target: "base" }], + } + : component, + ), + }; + render(); + fireEvent.click(screen.getByTestId("plan-card-toggle")); + + const link = screen.getByTestId("plan-spec-check-link"); + expect(link.textContent).toContain("base check 1"); + expect(link.getAttribute("href")).toBe("#plan-check-base-0"); + expect(document.getElementById("plan-check-base-0")?.textContent).toContain("volume"); + + const unverifiable = screen.getByTestId("plan-spec-unverifiable"); + expect(unverifiable.textContent).toContain("Unverifiable"); + expect(unverifiable.textContent).toContain("cannot measure surface finish"); + expect(unverifiable.className).toContain("bg-amber-50"); + }); }); diff --git a/packages/client/src/components/PlanCard.tsx b/packages/client/src/components/PlanCard.tsx index 2b3c46d..2abe46d 100644 --- a/packages/client/src/components/PlanCard.tsx +++ b/packages/client/src/components/PlanCard.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { Ban, Check, ChevronDown, ChevronRight, Circle, Hammer, Link2 } from "lucide-react"; +import { AlertTriangle, Ban, Check, ChevronDown, ChevronRight, Circle, FileText, Hammer, Link2 } from "lucide-react"; import { cn } from "@/lib/utils"; import type { Plan, PlanComponent } from "@/agent/plan"; @@ -48,22 +48,36 @@ export function PlanCard({ plan }: PlanCardProps) { {expanded && (
{plan.components.map((component) => ( -
- - {component.id} - {component.description} - {component.status === "abandoned" && component.abandon_reason && ( - - — {component.abandon_reason} - +
+
+ + {component.id} + {component.description} + {component.status === "abandoned" && component.abandon_reason && ( + + - {component.abandon_reason} + + )} +
+ {(component.checks ?? []).length > 0 && ( +
+ {(component.checks ?? []).map((check, checkIndex) => ( + + {check.kind} + + ))} +
)}
))} @@ -78,6 +92,53 @@ export function PlanCard({ plan }: PlanCardProps) { ))}
)} + {(plan.spec_sheet ?? []).length > 0 && ( +
+
+
+
+ {(plan.spec_sheet ?? []).map((row) => { + const unverifiable = Boolean(row.unverifiable_reason?.trim()); + return ( +
+ {row.text} + {(row.check_refs ?? []).map((ref, refIndex) => ( + + + ))} + {unverifiable && ( + + + )} +
+ ); + })} +
+
+ )}
)} diff --git a/packages/client/src/state/chatState.tsx b/packages/client/src/state/chatState.tsx index 98c3976..45b122a 100644 --- a/packages/client/src/state/chatState.tsx +++ b/packages/client/src/state/chatState.tsx @@ -23,6 +23,7 @@ import { PROBE_COMPONENT, runComponentIds } from "@/agent/plan"; import { systemPrompt } from "@/agent/prompt"; import { createRunBuild123dTool } from "@/agent/tools/runBuild123d"; import { createLookupDocsTool } from "@/agent/tools/lookupDocs"; +import { createSearchDocsTool } from "@/agent/tools/searchDocs"; import { useOptionalAppState } from "@/state/appState"; const EMPTY_SESSION_STATE: SessionState = { messages: [], streaming: false }; @@ -245,8 +246,8 @@ export function ChatProvider({ children, __createSession }: ChatProviderProps) { if (modelJson) { // During the CAD boot window (cad === null) the session is built without - // run_build123d; lookup_docs is always available. - const tools: AgentTool[] = [createLookupDocsTool()]; + // run_build123d; both documentation tools are always available. + const tools: AgentTool[] = [createLookupDocsTool(), createSearchDocsTool()]; if (cad && publishCadResult) { tools.unshift( createRunBuild123dTool({ diff --git a/packages/server/src/fakeLlm.ts b/packages/server/src/fakeLlm.ts index 58b3938..d72db79 100644 --- a/packages/server/src/fakeLlm.ts +++ b/packages/server/src/fakeLlm.ts @@ -174,6 +174,102 @@ function* planFlowStep(transcript: string, lastMessage: string): Generator plan without spec sheet -> valid plan -> verified run -> done plan. +const IMAGE_PLAN_CHECKS = [ + { kind: "bbox", size_mm: [10, 10, 10], target: "spacer" }, + { kind: "volume", range_mm3: [900, 1100], target: "spacer" }, +]; + +const IMAGE_PLAN_WITHOUT_SPEC = { + goal: "10 mm spacer from the dimensioned drawing", + components: [ + { + id: "spacer", + description: "10 mm cube spacer shown in the drawing", + bbox_mm: [10, 10, 10], + status: "todo", + free_floating_reason: "single component", + checks: IMAGE_PLAN_CHECKS, + }, + ], + interfaces: [], +}; + +const IMAGE_PLAN = { + ...IMAGE_PLAN_WITHOUT_SPEC, + spec_sheet: [ + { + id: "overall-size", + text: "The drawing shows a 10 mm overall width, depth, and height.", + source: "image", + check_refs: [{ component_id: "spacer", check_index: 0 }], + }, + { + id: "surface-finish", + text: "The drawing calls for a matte surface finish.", + source: "image", + unverifiable_reason: "The geometry kernel cannot measure surface finish.", + }, + ], +}; + +const IMAGE_PLAN_SCRIPT = [ + "from build123d import *", + "# --- params ---", + "side = 10 # [1, 100] Side length in mm", + "# --- end params ---", + "# --- expect ---", + 'EXPECT = {"bodies": 1, "bbox_mm": [10, 10, 10]}', + "# --- end expect ---", + "# --- checks ---", + "CHECKS = [", + ' {"kind": "bbox", "size_mm": [10, 10, 10], "target": "spacer"},', + ' {"kind": "volume", "range_mm3": [900, 1100], "target": "spacer"},', + "]", + "# --- end checks ---", + "# --- component ---", + 'COMPONENT = "spacer"', + "# --- end component ---", + "spacer = Box(side, side, side)", + 'spacer.label = "spacer"', + "result = spacer", +].join("\n"); + +function* imagePlanGateStep(transcript: string, lastMessage: string): Generator { + const plans = transcript.split('"name":"update_plan"').length - 1; + const runs = transcript.split('"name":"run_build123d"').length - 1; + if (lastMessage.includes("[Chamfer self-check]")) { + yield* streamText("The spacer and both image-derived specifications are accounted for."); + return; + } + if (runs === 0) { + yield* streamToolCall("image-plan-run-rejected", "run_build123d", { code: IMAGE_PLAN_SCRIPT }); + return; + } + if (plans === 0) { + yield* streamToolCall("image-plan-invalid", "update_plan", IMAGE_PLAN_WITHOUT_SPEC); + return; + } + if (plans === 1) { + yield* streamToolCall("image-plan-valid", "update_plan", IMAGE_PLAN); + return; + } + if (runs === 1) { + yield* streamToolCall("image-plan-run-valid", "run_build123d", { code: IMAGE_PLAN_SCRIPT }); + return; + } + if (plans === 2) { + yield* streamToolCall("image-plan-done", "update_plan", { + ...IMAGE_PLAN, + components: IMAGE_PLAN.components.map((component) => ({ ...component, status: "done" })), + }); + return; + } + yield* streamText("Spacer complete: the image plan is built and verified."); +} + export function fakeLlm(): LlmStreamer { return { async *stream(_model, context): AsyncIterable { @@ -193,6 +289,10 @@ export function fakeLlm(): LlmStreamer { yield* planFlowStep(transcript, JSON.stringify(messages.at(-1))); return; } + if (transcript.includes("image-plan-gate")) { + yield* imagePlanGateStep(transcript, JSON.stringify(messages.at(-1))); + return; + } // The self-check nudge the session injects after a gate pass arrives as a // trailing user message; answer it with a completed checklist instead of // falling through to the tool-call branch (which would start a second, diff --git a/py-tests/golden/golden.json b/py-tests/golden/golden.json index 858ff04..184d7b8 100644 --- a/py-tests/golden/golden.json +++ b/py-tests/golden/golden.json @@ -9,6 +9,29 @@ 60.0 ], "children": [], + "holes": [ + { + "axisDir": [ + -0.0, + -0.0, + 1.0 + ], + "centerMm": [ + 48.0, + 0.0, + 2.5 + ], + "depthMm": 5.0, + "diameterMm": 6.0, + "kind": "through" + } + ], + "topology": { + "edges": 27, + "faces": 11, + "shells": 1, + "vertices": 18 + }, "volumeMm3": 17057.12388980385 }, "params": [ @@ -73,6 +96,25 @@ "volumeMm3": 1005.3096491487335 } ], + "clearances": [ + { + "a": "base", + "b": "pin", + "distanceMm": 31.0, + "state": "apart" + } + ], + "floating": [ + "base", + "pin" + ], + "holes": [], + "topology": { + "edges": 15, + "faces": 9, + "shells": 2, + "vertices": 10 + }, "volumeMm3": 6405.309649148733 }, "params": [], @@ -89,6 +131,13 @@ 12.0 ], "children": [], + "holes": [], + "topology": { + "edges": 12, + "faces": 6, + "shells": 1, + "vertices": 8 + }, "volumeMm3": 11999.999999999998 }, "params": [ diff --git a/py-tests/test_checks.py b/py-tests/test_checks.py index c91b8c9..5c73d26 100644 --- a/py-tests/test_checks.py +++ b/py-tests/test_checks.py @@ -39,6 +39,24 @@ def test_valid_block_normalizes(): assert specs == [{"kind": "hole_through", "diameter": 6.5, "tol": 0.5, "count": 4, "target": None}] +def test_hole_anchor_normalizes_with_default_tolerance(): + specs = harness.parse_checks( + with_checks( + '[{"kind": "hole_through", "diameter": 6.5, "count": 1, "at_mm": [30, 15, 0]}]' + ) + ) + assert specs == [ + { + "kind": "hole_through", + "diameter": 6.5, + "tol": 0.5, + "count": 1, + "target": None, + "at_mm": [30.0, 15.0, 0.0], + } + ] + + def test_block_without_assignment_raises(): src = "# --- checks ---\nx = 1\n# --- end checks ---\n" + BOX_BODY with pytest.raises(ValueError, match="CHECKS"): @@ -80,7 +98,11 @@ def test_unknown_key_raises(): '{"kind": "volume", "range_mm3": [2, 1]}', '{"kind": "count_faces", "count": [2, 1]}', '{"kind": "count_faces", "count": 1.5}', + '{"kind": "wall_thickness", "range_mm": [0, 3]}', + '{"kind": "wall_thickness", "range_mm": [4, 3]}', + '{"kind": "hole_through", "diameter": 5, "count": 1, "at_mm": [1, 2]}', '{"kind": "symmetric", "plane": "AB"}', + '{"kind": "symmetric", "plane": "XY", "target": ""}', '{"kind": "symmetric", "plane": "XY", "tol_pct": 0}', '"not a dict"', ], @@ -101,6 +123,15 @@ def test_count_range_is_accepted(): assert specs[0]["count"] == [6, 10] +def test_wall_thickness_check_normalizes(): + specs = harness.parse_checks( + with_checks('[{"kind": "wall_thickness", "range_mm": [3, 4.25], "target": "case"}]') + ) + assert specs == [ + {"kind": "wall_thickness", "range_mm": [3.0, 4.25], "target": "case"} + ] + + # ---------- gate integration ---------- def test_gate_without_checks_block_is_unchanged(): @@ -144,6 +175,69 @@ def test_checks_run_even_when_expect_block_is_missing(): assert agent_checks(gate)[0]["passed"] +SHELL_3_5 = """ +from build123d import * +outer = Box(30, 30, 30, align=(Align.CENTER, Align.CENTER, Align.CENTER)) +inner = Box(23, 23, 23, align=(Align.CENTER, Align.CENTER, Align.CENTER)) +result = outer - inner +""" + +SHELL_EXPECT = '# --- expect ---\nEXPECT = {"bodies": 1, "bbox_mm": [30, 30, 30]}\n# --- end expect ---\n' + + +def test_wall_thickness_check_passes_for_on_spec_shell(): + gate = gate_of( + with_checks( + '[{"kind": "wall_thickness", "range_mm": [3.4, 3.6]}]', + body=SHELL_3_5, + expect=SHELL_EXPECT, + ) + ) + assert gate["status"] == "passed", agent_checks(gate)[0]["detail"] + + +def test_wall_thickness_check_fails_for_shell_half_mm_off_spec(): + gate = gate_of( + with_checks( + '[{"kind": "wall_thickness", "range_mm": [3.4, 3.6]}]', + body=SHELL_3_5.replace("Box(23, 23, 23", "Box(24, 24, 24"), + expect=SHELL_EXPECT, + ) + ) + check = agent_checks(gate)[0] + assert not check["passed"] + assert "measured [3, 3] mm" in check["detail"] + + +def test_wall_thickness_target_scopes_measurement_to_labeled_child(): + body = """ +from build123d import * +good = Pos(-25, 0, 0) * ( + Box(30, 30, 30, align=(Align.CENTER, Align.CENTER, Align.CENTER)) + - Box(23, 23, 23, align=(Align.CENTER, Align.CENTER, Align.CENTER)) +) +good.label = "good" +thin = Pos(25, 0, 0) * ( + Box(30, 30, 30, align=(Align.CENTER, Align.CENTER, Align.CENTER)) + - Box(24, 24, 24, align=(Align.CENTER, Align.CENTER, Align.CENTER)) +) +thin.label = "thin" +result = Compound(children=[good, thin]) +""" + gate = gate_of( + with_checks( + '[{"kind": "wall_thickness", "range_mm": [3.4, 3.6], "target": "good"},' + ' {"kind": "wall_thickness", "range_mm": [3.4, 3.6]}]', + body=body, + expect='# --- expect ---\nEXPECT = {"bodies": 2, "bbox_mm": [80, 30, 30]}\n# --- end expect ---\n', + ) + ) + targeted, whole = agent_checks(gate) + assert targeted["passed"], targeted["detail"] + assert not whole["passed"] + assert "measured [3, 3.5] mm" in whole["detail"] + + PLATE = """ from build123d import * with BuildPart() as p: @@ -169,6 +263,13 @@ def test_checks_run_even_when_expect_block_is_missing(): def test_hole_through_check_passes_on_four_through_holes(): gate = gate_of(with_checks(HOLE_CHECK, body=PLATE, expect=PLATE_EXPECT)) assert gate["status"] == "passed" + assert agent_checks(gate) == [ + { + "name": "check:hole_through[0]", + "passed": True, + "detail": "through holes d=6.5±0.5 mm: expected 4, found 4", + } + ] def test_hole_through_check_fails_when_one_hole_is_blind(): @@ -180,6 +281,21 @@ def test_hole_through_check_fails_when_one_hole_is_blind(): assert "1 blind" in check["detail"] +def test_hole_anchor_matches_only_bore_at_declared_position(): + gate = gate_of( + with_checks( + '[{"kind": "hole_through", "diameter": 6.5, "count": 1, "at_mm": [30.2, 15, 0], "tol": 0.25},' + ' {"kind": "hole_through", "diameter": 6.5, "count": 1, "at_mm": [0, 0, 0]}]', + body=PLATE, + expect=PLATE_EXPECT, + ) + ) + anchored, elsewhere = agent_checks(gate) + assert anchored["passed"], anchored["detail"] + assert not elsewhere["passed"] + assert "found 0" in elsewhere["detail"] + + def test_hole_blind_check_counts_blind_holes(): gate = gate_of( with_checks( @@ -308,6 +424,28 @@ def test_symmetric_check_fails_for_asymmetric_part(): assert "asymmetric volume" in check["detail"] +def test_symmetric_target_evaluates_only_named_child(): + body = """ +from build123d import * +centered = Box(10, 10, 10, align=(Align.CENTER, Align.CENTER, Align.CENTER)) +centered.label = "centered" +offset = Pos(20, 0, 0) * Box(10, 10, 10, align=(Align.CENTER, Align.CENTER, Align.CENTER)) +offset.label = "offset" +result = Compound(children=[centered, offset]) +""" + gate = gate_of( + with_checks( + '[{"kind": "symmetric", "plane": "YZ", "target": "centered"},' + ' {"kind": "symmetric", "plane": "YZ"}]', + body=body, + expect='# --- expect ---\nEXPECT = {"bodies": 2, "bbox_mm": [30, 10, 10]}\n# --- end expect ---\n', + ) + ) + targeted, whole = agent_checks(gate) + assert targeted["passed"], targeted["detail"] + assert not whole["passed"], whole["detail"] + + def test_check_evaluator_crash_fails_that_check_only(monkeypatch): def boom(spec, holes): raise RuntimeError("synthetic check bug")