Added the Triangle Sketch object

This commit is contained in:
gumyr 2023-12-08 16:06:45 -05:00
parent 0bdaabbb2f
commit 4f79ce745c
8 changed files with 140 additions and 2 deletions

View file

@ -0,0 +1,25 @@
<?xml version='1.0' encoding='utf-8'?>
<svg width="93.32161mm" height="100.089999mm" viewBox="-22.456606 -27.78867 44.913212 48.170658" version="1.1" xmlns="http://www.w3.org/2000/svg">
<g transform="scale(1,-1)" stroke-linecap="round">
<g fill="none" stroke="rgb(0,0,0)" stroke-width="0.043314609308420446">
<path d="M -15.0,-12.360331 L 15.0,-12.360331 L -0.0,24.720662 L -15.0,-12.360331" />
<path d="M -14.95,-18.351869 L -14.95,-14.360331 L -15.05,-14.360331 L -15.05,-20.360331 L -14.95,-20.360331 L -14.95,-18.368793 A 10.137937550497139,10.137937550497139 80.53767779197437 0,0 -12.0,-19.360331 L -12.35625,-18.410331 L -3.232503,-18.410331 L -3.232503,-18.310331 L -12.35625,-18.310331 L -12.0,-17.360331 A 10.137937550497139,10.137937550497139 -80.53767779197439 0,0 -14.95,-18.351869" />
<path d="M 15.05,-20.360331 L 15.05,-14.360331 L 14.95,-14.360331 L 14.95,-18.351869 A 10.137937550497139,10.137937550497139 -99.46232220802563 0,0 12.0,-17.360331 L 12.35625,-18.310331 L 3.232503,-18.310331 L 3.232503,-18.410331 L 12.35625,-18.410331 L 12.0,-19.360331 A 10.137937550497139,10.137937550497139 99.46232220802563 0,0 14.95,-18.368793 L 14.95,-20.360331 L 15.05,-20.360331" />
<path d="M -1.117497,-17.805326 L -0.69751,-17.805326 C -0.662613,-17.483777 -0.470742,-17.341897 -0.082503,-17.340336 C 0.288221,-17.339293 0.505095,-17.478048 0.50249,-17.730326 L 0.50249,-17.840336 Q 0.50249,-17.970332 0.407495,-18.035331 Q 0.3125,-18.100329 0.067497,-18.130326 C -0.052501,-18.146993 -0.135834,-18.15866 -0.182503,-18.165328 C -0.229172,-18.171995 -0.302507,-18.183663 -0.402507,-18.200329 C -0.502507,-18.216996 -0.572507,-18.231161 -0.612508,-18.242826 C -0.652509,-18.25449 -0.71001,-18.272823 -0.78501,-18.297823 C -0.86001,-18.322823 -0.913341,-18.348658 -0.945003,-18.375329 C -0.976666,-18.402 -1.015831,-18.436169 -1.0625,-18.477836 C -1.109169,-18.519502 -1.141669,-18.5645 -1.160002,-18.612829 C -1.194843,-18.709226 -1.234327,-18.837255 -1.232503,-18.990336 C -1.232503,-19.227 -1.155002,-19.415333 -1.0,-19.555334 C -0.844998,-19.695335 -0.635834,-19.765336 -0.37251,-19.765336 C -0.059174,-19.765336 0.237495,-19.636999 0.517497,-19.380326 Q 0.542497,-19.580326 0.644995,-19.672831 Q 0.747493,-19.765336 0.947493,-19.765336 Q 1.057503,-19.765336 1.232503,-19.720332 L 1.232503,-19.405326 Q 1.1875,-19.415336 1.142497,-19.415336 Q 0.917497,-19.415336 0.917497,-19.210323 L 0.917497,-17.670332 C 0.91906,-17.205229 0.577598,-16.953763 -0.067497,-16.955326 C -0.747499,-16.955326 -1.097499,-17.238659 -1.117497,-17.805326 M 0.50249,-18.825329 C 0.50249,-18.965325 0.429159,-19.096157 0.282495,-19.217826 C 0.135832,-19.339495 -0.052501,-19.400329 -0.282503,-19.400329 C -0.60657,-19.402413 -0.800114,-19.244909 -0.79751,-18.980326 C -0.79751,-18.846993 -0.74751,-18.742826 -0.64751,-18.667826 C -0.54751,-18.592826 -0.435843,-18.545327 -0.312508,-18.525329 C -0.189174,-18.505331 -0.04334,-18.482 0.124992,-18.455334 C 0.293324,-18.428668 0.419157,-18.395332 0.50249,-18.355326 L 0.50249,-18.825329" />
<path d="M 20.535554,-10.067153 L 16.8353,-11.56398 L 16.8728,-11.656682 L 22.434948,-9.406682 L 22.397448,-9.31398 L 20.551243,-10.060806 A 10.137937550497139,10.137937550497139 -167.43800937098342 0,0 20.364174,-6.954256 L 19.617094,-7.640759 L 14.298188,5.507928 L 14.205486,5.470428 L 19.524391,-7.678259 L 18.510124,-7.704256 A 10.137937550497139,10.137937550497139 31.486635045067814 0,0 20.535554,-10.067153" />
<path d="M 7.397448,27.767013 L 1.8353,25.517013 L 1.8728,25.42431 L 5.573054,26.921137 A 10.137937550497139,10.137937550497139 12.561990629016586 0,0 5.760124,23.814587 L 6.507204,24.50109 L 11.826109,11.352403 L 11.918812,11.389903 L 6.599906,24.53859 L 7.614174,24.564587 A 10.137937550497139,10.137937550497139 -148.51336495493217 0,0 5.588743,26.927484 L 7.434948,27.67431 L 7.397448,27.767013" />
<path d="M 11.759026,6.638225 L 15.138034,8.005102 L 14.997409,8.352736 L 14.686862,8.227113 Q 14.993397,8.669339 14.792774,9.165291 Q 14.597773,9.647347 14.117661,9.787537 Q 13.637548,9.927727 13.034982,9.683977 Q 12.446328,9.445854 12.215825,9.028995 Q 11.985323,8.612137 12.180324,8.130081 Q 12.377199,7.643393 12.88269,7.540446 L 11.603398,7.022947 L 11.759026,6.638225 M 12.571869,8.202174 Q 12.440619,8.526633 12.622372,8.823985 Q 12.804125,9.121337 13.23983,9.297588 Q 13.652359,9.464464 13.989295,9.371533 Q 14.32623,9.278603 14.453726,8.963423 Q 14.577475,8.657508 14.395227,8.368041 Q 14.212979,8.078574 13.786546,7.906074 Q 13.360113,7.733573 13.027866,7.814916 Q 12.695618,7.896259 12.571869,8.202174" />
<path d="M -5.573054,26.921137 L -1.8728,25.42431 L -1.8353,25.517013 L -7.397448,27.767013 L -7.434948,27.67431 L -5.588743,26.927484 A 10.137937550497139,10.137937550497139 -31.48663504506779 0,0 -7.614174,24.564587 L -6.599906,24.53859 L -11.940376,11.336596 L -11.847673,11.299096 L -6.507204,24.50109 L -5.760124,23.814587 A 10.137937550497139,10.137937550497139 167.43800937098345 0,0 -5.573054,26.921137" />
<path d="M -22.434948,-9.406682 L -16.8728,-11.656682 L -16.8353,-11.56398 L -20.535554,-10.067153 A 10.137937550497139,10.137937550497139 148.51336495493223 0,0 -18.510124,-7.704256 L -19.524391,-7.678259 L -14.183922,5.523735 L -14.276625,5.561235 L -19.617094,-7.640759 L -20.364174,-6.954256 A 10.137937550497139,10.137937550497139 -12.561990629016547 0,0 -20.551243,-10.060806 L -22.397448,-9.31398 L -22.434948,-9.406682" />
<path d="M -12.894355,7.644942 L -13.051856,7.255589 Q -12.607676,7.113657 -12.278364,7.274397 Q -11.949051,7.435137 -11.778428,7.85693 Q -11.579673,8.348265 -11.82215,8.788842 Q -12.064626,9.229419 -12.667193,9.473169 Q -13.255862,9.711297 -13.718368,9.56129 Q -14.180874,9.411283 -14.381496,8.915331 Q -14.557748,8.479626 -14.414766,8.11974 Q -14.271784,7.759854 -13.841811,7.542784 L -13.68431,7.932137 C -14.047409,8.154526 -14.162085,8.431038 -14.028336,8.761673 C -13.942086,8.97489 -13.792698,9.108632 -13.580174,9.162898 C -13.36765,9.217163 -13.117697,9.18617 -12.830315,9.069919 C -12.527493,8.947421 -12.314396,8.792 -12.191023,8.603654 C -12.067651,8.415308 -12.048464,8.216075 -12.133461,8.005956 C -12.260755,7.685726 -12.537162,7.555721 -12.894355,7.644942" />
<path d="M -7.301752,-9.425695 Q -7.006749,-9.140693 -7.006749,-8.67069 Q -7.006749,-8.340693 -7.164252,-8.130692 Q -7.321755,-7.92069 -7.671755,-7.785696 Q -7.166759,-7.550703 -7.166759,-6.990693 Q -7.166759,-6.835696 -7.216759,-6.688195 Q -7.266759,-6.540693 -7.379259,-6.393192 Q -7.491759,-6.24569 -7.716759,-6.155692 Q -7.941759,-6.065693 -8.246755,-6.065693 L -9.726752,-6.065693 L -9.726752,-9.710696 L -8.081749,-9.710696 Q -7.596755,-9.710696 -7.301752,-9.425695 M -7.631749,-7.0557 Q -7.631749,-7.635696 -8.361746,-7.635696 L -9.261746,-7.635696 L -9.261746,-6.475703 L -8.361746,-6.475703 Q -7.631749,-6.475703 -7.631749,-7.0557 M -8.126752,-9.300703 L -9.261746,-9.300703 L -9.261746,-8.04569 L -8.126752,-8.04569 Q -7.811746,-8.04569 -7.64175,-8.218192 Q -7.471755,-8.390693 -7.471755,-8.675703 Q -7.471755,-8.825703 -7.521755,-8.9557 Q -7.571755,-9.085696 -7.726752,-9.1932 Q -7.881749,-9.300703 -8.126752,-9.300703" />
<path d="M 6.836746,-7.40819 Q 6.794249,-7.653193 6.794249,-7.903193 Q 6.794249,-8.148196 6.836746,-8.388195 Q 6.879242,-8.628193 6.996747,-8.890693 Q 7.114252,-9.153193 7.29175,-9.348188 Q 7.469249,-9.543183 7.76675,-9.67069 Q 8.064252,-9.798196 8.439252,-9.798196 Q 9.774246,-9.798196 9.939252,-8.353193 L 9.459255,-8.353193 Q 9.374246,-8.88319 9.134247,-9.135688 Q 8.894249,-9.388187 8.444249,-9.388187 Q 7.899246,-9.388187 7.57925,-8.985688 Q 7.259255,-8.58319 7.259255,-7.898196 Q 7.259255,-7.198196 7.56675,-6.793192 Q 7.874246,-6.388187 8.404242,-6.388187 Q 8.839252,-6.388187 9.074254,-6.58319 Q 9.309255,-6.778193 9.389252,-7.168183 L 9.864252,-7.168183 Q 9.649246,-5.978193 8.459255,-5.978193 Q 8.079242,-5.978193 7.776744,-6.10819 Q 7.474246,-6.238187 7.296747,-6.435688 Q 7.119249,-6.63319 6.999246,-6.898188 Q 6.879242,-7.163187 6.836746,-7.40819" />
<path d="M 0.694995,15.993163 L 1.069995,14.89816 L 1.589998,14.89816 L 0.310002,18.543163 L -0.289998,18.543163 L -1.589998,14.89816 L -1.094995,14.89816 L -0.710002,15.993163 L 0.694995,15.993163 M 0.564998,16.383153 L -0.594995,16.383153 L 0.005005,18.043163 L 0.564998,16.383153" />
</g>
<g fill="none" stroke="rgb(0,0,0)" stroke-width="0.043314609308420446" id="dashed" stroke-dasharray="0.550096 0.275048">
<path d="M -10.0,-12.360331 A 5.0,5.0 0.0 0,1 -13.125,-7.725207" />
<path d="M 13.125,-7.725207 A 5.0,5.0 0.0 0,1 10.0,-12.360331" />
<path d="M -1.875,20.085538 A 5.0,5.0 0.0 0,1 1.875,20.085538" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

View file

@ -131,7 +131,7 @@ A procedure for avoiding this issue is to install in a conda environment, which
conda create -n <YOUR ENVIRONMENT NAME> python=3.10
conda activate <YOUR ENVIRONMENT NAME>
conda install -c cadquery -c conda-forge cadquery=master
pip install svgwrite svgpathtools anytree scipy ipython \
pip install svgwrite svgpathtools anytree scipy ipython trianglesolver \
ocp_tessellate webcolors==1.12 numpy numpy-quaternion cachetools==5.2.0 \
ocp_vscode requests orjson urllib3 certifi numpy-stl git+https://github.com/jdegenstein/py-lib3mf \
"svgpathtools>=1.5.1,<2" "svgelements>=1.9.1,<2"

View file

@ -329,6 +329,12 @@ Reference
+++
Trapezoid defined by width, height and interior angles
.. grid-item-card:: :class:`~objects_sketch.Triangle`
.. image:: assets/triangle_example.svg
+++
Triangle defined by one side & two other sides or interior angles
Reference
@ -353,6 +359,7 @@ Reference
.. autoclass:: drafting.TechnicalDrawing
.. autoclass:: Text
.. autoclass:: Trapezoid
.. autoclass:: Triangle
3D Objects
----------

View file

@ -193,6 +193,32 @@ exporter.add_shape(visible, layer="Visible")
exporter.add_shape(hidden, layer="Hidden")
exporter.write(f"assets/controller.svg")
d = Draft(line_width=0.1)
# [Ex. 15]
with BuildSketch() as isosceles_triangle:
t = Triangle(a=30, b=40, c=40)
# [Ex. 15]
ExtensionLine(t.edges().sort_by(Axis.Y)[0], 6, d, label="a")
ExtensionLine(t.edges().sort_by(Axis.X)[-1], 6, d, label="b")
ExtensionLine(t.edges().sort_by(SortBy.LENGTH)[-1], 6, d, label="c")
a1 = CenterArc(t.vertices().group_by(Axis.Y)[0].sort_by(Axis.X)[0], 5, 0, t.B)
a2 = CenterArc(t.vertices().group_by(Axis.Y)[0].sort_by(Axis.X)[-1], 5, 180 - t.C, t.C)
a3 = CenterArc(t.vertices().sort_by(Axis.Y)[-1], 5, 270 - t.A / 2, t.A)
p1 = CenterArc(t.vertices().group_by(Axis.Y)[0].sort_by(Axis.X)[0], 8, 0, t.B)
p2 = CenterArc(t.vertices().group_by(Axis.Y)[0].sort_by(Axis.X)[-1], 8, 180 - t.C, t.C)
p3 = CenterArc(t.vertices().sort_by(Axis.Y)[-1], 8, 270 - t.A / 2, t.A)
t1 = Text("B", font_size=d.font_size).moved(Pos(p1 @ 0.5))
t2 = Text("C", font_size=d.font_size).moved(Pos(p2 @ 0.5))
t3 = Text("A", font_size=d.font_size).moved(Pos(p3 @ 0.5))
s = 100 / max(*isosceles_triangle.sketch.bounding_box().size)
svg = ExportSVG(scale=s)
svg.add_layer("dashed", line_type=LineType.DASHED)
svg.add_shape([a1, a2, a3], "dashed")
svg.add_shape(isosceles_triangle.sketch)
svg.add_shape([t1, t2, t3])
svg.write("assets/triangle_example.svg")
# [Align]
with BuildSketch() as align:

View file

@ -45,6 +45,7 @@ dependencies = [
"ipython >= 8.0.0, <9",
"py-lib3mf",
"ocpsvg",
"trianglesolver"
]
[project.urls]

View file

@ -106,6 +106,7 @@ __all__ = [
"Text",
"TechnicalDrawing",
"Trapezoid",
"Triangle",
# 3D Part Objects
"BasePartObject",
"CounterBoreHole",

View file

@ -27,7 +27,9 @@ license:
"""
from __future__ import annotations
from math import cos, pi, radians, sin, tan
import trianglesolver
from math import cos, degrees, pi, radians, sin, tan
from typing import Iterable, Union
from build123d.build_common import LocationList, flatten_sequence, validate_inputs
@ -629,3 +631,68 @@ class Trapezoid(BaseSketchObject):
pts.append(pts[0])
face = Face.make_from_wires(Wire.make_polygon(pts))
super().__init__(face, rotation, self.align, mode)
class Triangle(BaseSketchObject):
"""Sketch Object: Triangle
Add any triangle to the sketch by specifying the length of any side and any
two other side lengths or interior angles. Note that the interior angles are
opposite the side with the same designation (i.e. side 'a' is opposite angle 'A').
Args:
a (float, optional): side 'a' length. Defaults to None.
b (float, optional): side 'b' length. Defaults to None.
c (float, optional): side 'c' length. Defaults to None.
A (float, optional): interior angle 'A' in degrees. Defaults to None.
B (float, optional): interior angle 'B' in degrees. Defaults to None.
C (float, optional): interior angle 'C' in degrees. Defaults to None.
rotation (float, optional): angles to rotate objects. Defaults to 0.
align (Union[Align, tuple[Align, Align]], optional): align min, center, or max of object.
Defaults to None.
mode (Mode, optional): combination mode. Defaults to Mode.ADD.
Raises:
ValueError: One length and two other values were not provided
"""
_applies_to = [BuildSketch._tag]
def __init__(
self,
*,
a: float = None,
b: float = None,
c: float = None,
A: float = None,
B: float = None,
C: float = None,
align: Union[None, Align, tuple[Align, Align]] = None,
rotation: float = 0,
mode: Mode = Mode.ADD,
):
context = BuildSketch._get_context(self)
validate_inputs(context, self)
if [v is None for v in [a, b, c]].count(True) == 3 or [
v is None for v in [a, b, c, A, B, C]
].count(True) != 3:
raise ValueError("One length and two other values must be provided")
A, B, C = (radians(angle) if angle is not None else None for angle in [A, B, C])
a, b, c, A, B, C = trianglesolver.solve(a, b, c, A, B, C)
self.a = a #: length of side 'a'
self.b = b #: length of side 'b'
self.c = c #: length of side 'c'
self.A = degrees(A) #: interior angle 'A' in degrees
self.B = degrees(B) #: interior angle 'B' in degrees
self.C = degrees(C) #: interior angle 'C' in degrees
triangle = Face.make_from_wires(
Wire.make_polygon(
[Vector(0, 0), Vector(a, 0), Vector(c, 0).rotate(Axis.Z, self.B)]
)
)
center_of_geometry = sum(Vector(v) for v in triangle.vertices()) / 3
triangle.move(Location(-center_of_geometry))
alignment = None if align is None else tuplify(align, 2)
super().__init__(obj=triangle, rotation=rotation, align=alignment, mode=mode)

View file

@ -382,6 +382,17 @@ class TestBuildSketchObjects(unittest.TestCase):
with BuildSketch() as test:
Trapezoid(6, 2, 30)
def test_triangle(self):
tri = Triangle(a=3, b=4, c=5)
self.assertAlmostEqual(tri.area, (3 * 4) / 2, 5)
tri = Triangle(c=5, C=90, a=3)
self.assertAlmostEqual(tri.area, (3 * 4) / 2, 5)
with self.assertRaises(ValueError):
Triangle(A=90, B=45, C=45)
with self.assertRaises(AssertionError):
Triangle(a=10, b=4, c=4)
def test_offset(self):
"""Test normal and error cases"""
with BuildSketch() as test: