Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checks for duplicate constraints. #461

Merged
merged 5 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
bl_info = {
"name": "CAD Sketcher",
"author": "hlorus",
"version": (0, 27, 3),
"version": (0, 27, 4),
"blender": (3, 3, 0),
"location": "View3D > Toolbar",
"description": "Parametric, constraint-based geometry sketcher",
Expand Down
2 changes: 1 addition & 1 deletion blender_manifest.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
schema_version = "1.0.0"

id = "CAD_Sketcher"
version = "0.27.3"
version = "0.27.4"
name = "CAD Sketcher"
tagline = "Parametric, constraint-based geometry sketcher"
maintainer = "hlorus <dave19924@gmail.com>"
Expand Down
17 changes: 10 additions & 7 deletions operators/add_angle.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from ..stateful_operator.utilities.register import register_stateops_factory
from .base_constraint import GenericConstraintOp

from ..model.angle import SlvsAngle

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -45,13 +47,14 @@ class VIEW3D_OT_slvs_add_angle(Operator, GenericConstraintOp):
property_keys = ("value", "setting")

def main(self, context):
self.target = context.scene.sketcher.constraints.add_angle(
self.entity1,
self.entity2,
sketch=self.sketch,
init=not self.initialized,
**self.get_settings()
)
if not self.exists(context, SlvsAngle):
self.target = context.scene.sketcher.constraints.add_angle(
self.entity1,
self.entity2,
sketch=self.sketch,
init=not self.initialized,
**self.get_settings()
)

return super().main(context)

Expand Down
15 changes: 9 additions & 6 deletions operators/add_diameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from ..stateful_operator.utilities.register import register_stateops_factory
from .base_constraint import GenericConstraintOp

from ..model.diameter import SlvsDiameter

logger = logging.getLogger(__name__)


Expand All @@ -30,12 +32,13 @@ class VIEW3D_OT_slvs_add_diameter(Operator, GenericConstraintOp):
property_keys = ("value", "setting")

def main(self, context):
self.target = context.scene.sketcher.constraints.add_diameter(
self.entity1,
sketch=self.sketch,
init=not self.initialized,
**self.get_settings(),
)
if not self.exists(context, SlvsDiameter):
self.target = context.scene.sketcher.constraints.add_diameter(
self.entity1,
sketch=self.sketch,
init=not self.initialized,
**self.get_settings(),
)

return super().main(context)

Expand Down
43 changes: 36 additions & 7 deletions operators/add_distance.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
from ..declarations import Operators
from ..stateful_operator.utilities.register import register_stateops_factory

from ..model.distance import SlvsDistance
from ..model.line_2d import SlvsLine2D
from ..model.point_2d import SlvsPoint2D
from ..model.types import SlvsPoint3D
from ..model.types import SlvsLine3D

logger = logging.getLogger(__name__)

Expand All @@ -33,13 +38,37 @@ class VIEW3D_OT_slvs_add_distance(Operator, GenericConstraintOp):
property_keys = ("value", "align", "flip")

def main(self, context):
self.target = context.scene.sketcher.constraints.add_distance(
self.entity1,
self.entity2,
sketch=self.sketch,
init=not self.initialized,
**self.get_settings(),
)
if isinstance(self.entity1, SlvsLine2D) and self.entity2 is None:
dependencies = self.entity1.dependencies()
if (isinstance(dependencies[0], SlvsPoint2D) and
isinstance(dependencies[1], SlvsPoint2D)):
# for loop changes the values of self.entity1 and self.entity2
# from a line entity to its endpoints
for i in range(0, 2):
state_data = self.get_state_data(i)
state_data["hovered"] = -1
state_data["type"] = type(dependencies[i])
state_data["is_existing_entity"] = True
state_data["entity_index"] = dependencies[i].slvs_index
self.next_state(context) # end user selection, no need for second entity

if (isinstance(self.entity1, (SlvsPoint3D, SlvsLine3D)) or
isinstance(self.entity2, (SlvsPoint3D, SlvsLine3D))):
max_constraints = 3
elif ((isinstance(self.entity1, SlvsLine2D) and self.entity2 is None) or
isinstance(self.entity1, SlvsPoint2D) and isinstance(self.entity2, SlvsPoint2D)):
max_constraints = 2
else:
max_constraints = 1

if not self.exists(context, SlvsDistance, max_constraints):
self.target = context.scene.sketcher.constraints.add_distance(
self.entity1,
self.entity2,
sketch=self.sketch,
init=not self.initialized,
**self.get_settings(),
)
return super().main(context)

def fini(self, context: Context, succeede: bool):
Expand Down
112 changes: 65 additions & 47 deletions operators/add_geometric_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@
from ..utilities.view import refresh
from ..solver import solve_system

from ..model.coincident import SlvsCoincident
from ..model.equal import SlvsEqual
from ..model.vertical import SlvsVertical
from ..model.horizontal import SlvsHorizontal
from ..model.parallel import SlvsParallel
from ..model.perpendicular import SlvsPerpendicular
from ..model.tangent import SlvsTangent
from ..model.midpoint import SlvsMidpoint
from ..model.ratio import SlvsRatio

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -52,11 +61,12 @@ def main(self, context: Context):
if self.handle_merge(context):
return True

self.target = context.scene.sketcher.constraints.add_coincident(
self.entity1,
self.entity2,
sketch=self.sketch,
)
if not self.exists(context, SlvsCoincident):
self.target = context.scene.sketcher.constraints.add_coincident(
self.entity1,
self.entity2,
sketch=self.sketch,
)
return super().main(context)


Expand All @@ -70,11 +80,12 @@ class VIEW3D_OT_slvs_add_equal(Operator, GenericConstraintOp):
type = "EQUAL"

def main(self, context):
self.target = context.scene.sketcher.constraints.add_equal(
self.entity1,
self.entity2,
sketch=self.sketch,
)
if not self.exists(context, SlvsEqual):
self.target = context.scene.sketcher.constraints.add_equal(
self.entity1,
self.entity2,
sketch=self.sketch,
)

return super().main(context)

Expand All @@ -89,11 +100,12 @@ class VIEW3D_OT_slvs_add_vertical(Operator, GenericConstraintOp):
type = "VERTICAL"

def main(self, context):
self.target = context.scene.sketcher.constraints.add_vertical(
self.entity1,
entity2=self.entity2,
sketch=self.sketch,
)
if not self.exists(context, SlvsVertical):
self.target = context.scene.sketcher.constraints.add_vertical(
self.entity1,
entity2=self.entity2,
sketch=self.sketch,
)

return super().main(context)

Expand All @@ -108,11 +120,12 @@ class VIEW3D_OT_slvs_add_horizontal(Operator, GenericConstraintOp):
type = "HORIZONTAL"

def main(self, context):
self.target = context.scene.sketcher.constraints.add_horizontal(
self.entity1,
entity2=self.entity2,
sketch=self.sketch,
)
if not self.exists(context, SlvsHorizontal):
self.target = context.scene.sketcher.constraints.add_horizontal(
self.entity1,
entity2=self.entity2,
sketch=self.sketch,
)

return super().main(context)

Expand All @@ -127,11 +140,12 @@ class VIEW3D_OT_slvs_add_parallel(Operator, GenericConstraintOp):
type = "PARALLEL"

def main(self, context):
self.target = context.scene.sketcher.constraints.add_parallel(
self.entity1,
self.entity2,
sketch=self.sketch,
)
if not self.exists(context, SlvsParallel):
self.target = context.scene.sketcher.constraints.add_parallel(
self.entity1,
self.entity2,
sketch=self.sketch,
)

return super().main(context)

Expand All @@ -146,11 +160,12 @@ class VIEW3D_OT_slvs_add_perpendicular(Operator, GenericConstraintOp):
type = "PERPENDICULAR"

def main(self, context):
self.target = context.scene.sketcher.constraints.add_perpendicular(
self.entity1,
self.entity2,
sketch=self.sketch,
)
if not self.exists(context, SlvsPerpendicular):
self.target = context.scene.sketcher.constraints.add_perpendicular(
self.entity1,
self.entity2,
sketch=self.sketch,
)

return super().main(context)

Expand All @@ -165,11 +180,12 @@ class VIEW3D_OT_slvs_add_tangent(Operator, GenericConstraintOp):
type = "TANGENT"

def main(self, context):
self.target = context.scene.sketcher.constraints.add_tangent(
self.entity1,
self.entity2,
sketch=self.sketch,
)
if not self.exists(context, SlvsTangent):
self.target = context.scene.sketcher.constraints.add_tangent(
self.entity1,
self.entity2,
sketch=self.sketch,
)

return super().main(context)

Expand All @@ -184,11 +200,12 @@ class VIEW3D_OT_slvs_add_midpoint(Operator, GenericConstraintOp):
type = "MIDPOINT"

def main(self, context):
self.target = context.scene.sketcher.constraints.add_midpoint(
self.entity1,
self.entity2,
sketch=self.sketch,
)
if not self.exists(context, SlvsMidpoint):
self.target = context.scene.sketcher.constraints.add_midpoint(
self.entity1,
self.entity2,
sketch=self.sketch,
)

return super().main(context)

Expand All @@ -211,13 +228,14 @@ class VIEW3D_OT_slvs_add_ratio(Operator, GenericConstraintOp):
property_keys = ("value",)

def main(self, context):
self.target = context.scene.sketcher.constraints.add_ratio(
self.entity1,
self.entity2,
sketch=self.sketch,
init=not self.initialized,
**self.get_settings(),
)
if not self.exists(context, SlvsRatio):
self.target = context.scene.sketcher.constraints.add_ratio(
self.entity1,
self.entity2,
sketch=self.sketch,
init=not self.initialized,
**self.get_settings(),
)

return super().main(context)

Expand Down
19 changes: 16 additions & 3 deletions operators/base_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@
from ..utilities.select import deselect_all
from ..utilities.view import refresh
from .base_2d import Operator2d
from ..utilities.select import deselect_all
from ..utilities.view import refresh
from ..solver import solve_system


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -124,3 +121,19 @@ def draw(self, context: Context):

for key in self.property_keys:
layout.prop(self, key)

def exists(self, context, constraint_type=None, max_constraints=1) -> bool:
if hasattr(self, "entity2"):
new_dependencies = [i for i in [self.entity1, self.entity2, self.sketch] if i is not None]
else:
new_dependencies = [i for i in [self.entity1, self.sketch] if i is not None]

constraint_counter = 0
for c in context.scene.sketcher.constraints.all:
if isinstance(c, constraint_type):
if set(c.dependencies()) == set(new_dependencies):
constraint_counter += 1
if constraint_counter >= max_constraints:
return True

return False
24 changes: 24 additions & 0 deletions versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,28 @@ def do_versioning(self):
)
c.is_reference = True

if version < (0, 27, 4):
TimStrauven marked this conversation as resolved.
Show resolved Hide resolved
# update distance constraints on only a line
# to distance constraints on the endpoints of that line.
from .model.line_2d import SlvsLine2D
from .model.distance import SlvsDistance
from .model.point_2d import SlvsPoint2D
from .model.sketch import SlvsSketch

for c in context.scene.sketcher.constraints.dimensional:
if len(c.dependencies()) != 2:
continue
if not (isinstance(c, SlvsDistance) and
isinstance(c.dependencies()[0], SlvsLine2D) and
isinstance(c.dependencies()[1], SlvsSketch)):
continue

line_dependencies = c.dependencies()[0].dependencies()
if len(line_dependencies) != 3:
continue
if (isinstance(line_dependencies[0], SlvsPoint2D) and
isinstance(line_dependencies[1], SlvsPoint2D)):
setattr(c, "entity1", line_dependencies[0])
setattr(c, "entity2", line_dependencies[1])

logger.debug(msg)