hlorus / CAD_Sketcher

Constraint-based geometry sketcher for blender
GNU General Public License v3.0
2.59k stars 122 forks source link

[BUG] CAD Sketcher shows horizontal and vertical constraints on slanting lines. #429

Closed raindropsfromsky closed 3 months ago

raindropsfromsky commented 7 months ago

Contact Details

raindrops.fromsky@gmail.com

Description

When we draw lines, CAD Sketcher starts showing constraint marker on them when they are "almost" horizontal/vertical.

I expected that the line will snap to perfect horizontal/vertical direction. But when I complete the line, the line stays slanting, with a small angle.

After completing the line segment, if I try to move any of the lines, all the slanting segments snap to their required directions (horizontal or vertical) simultaneously.

Constrained segments do not snap to their desired directions

Thus, this is not a serious problem, after all. But even this little quirk should be ironed out.

Addon Version

0.27.3

Blender Version

4.0 and 4.1

What platform are you running on?

Windows

TimStrauven commented 3 months ago

Hi, I checked this issue, and found the following:

The reason this is not updating can be found in the file "operators/add_line_2d.py" In the "fini" function the solve_system is called only in case a coincident constraint is added to the new line segment, and not when a horizonal/vertical constraint is added.

There are two possible solutions I found for this:

1 Always run the solver once the line segment is completed in the fini function by removing the check for coincident:

    def fini(self, context: Context, succeede: bool):
        if hasattr(self, "target"):
            logger.debug("Add: {}".format(self.target))

        if succeede:
            # if self.has_coincident():
             solve_system(context, sketch=self.sketch)

2 Add the solver to the parts where the "auto vertical/horizontal constraint" is added in the "main" function. This has the added benefit of updating the line itself to horizontal/vertical in real time while drawing. This is my preferred solution.

    def main(self, context: Context):
        wp = self.sketch.wp
        p1, p2 = self.get_point(context, 0), self.get_point(context, 1)

        self.target = context.scene.sketcher.entities.add_line_2d(p1, p2, self.sketch)
        if context.scene.sketcher.use_construction:
            self.target.construction = True

        # auto vertical/horizontal constraint
        constraints = context.scene.sketcher.constraints
        vec_dir = self.target.direction_vec()
        if vec_dir.length:
            angle = vec_dir.angle(Vector((1, 0)))

            threshold = 0.1
            if angle < threshold or angle > HALF_TURN - threshold:
                constraints.add_horizontal(self.target, sketch=self.sketch)
                solve_system(context, sketch=self.sketch) # added
            elif (QUARTER_TURN - threshold) < angle < (QUARTER_TURN + threshold):
                constraints.add_vertical(self.target, sketch=self.sketch)
                solve_system(context, sketch=self.sketch) # added

        ignore_hover(self.target)
        return True

I am not sure why the team opted not to use the solver more often, but I suspect it is for performance. However solving it with these two ways I did not see a big performance impact on my system. Lastly I took a look at getting the constraint info within the fini function, to add a check before running the solver, but could not find an elegant way to do this.

If this is in line with the expectations of the team, does this qualify for the bounty on the issue?

Regards, T

hlorus commented 3 months ago

Hey thanks for looking into this! The main method runs quite frequently so running the solver from there is likely not possible. The other solution should be alright, can you submit a PR? Once the PR is merged you can submit an invoice on open collective.

TimStrauven commented 3 months ago

Thanks for the fast feedback! PR has been created for solution 1 as you suggested!