gumyr/build123d

Pretty Printing of objects

Opened this issue · 4 comments

I have found it very useful to print out the result of a rough sort_by() or filter_by operation before narrowing in on a selection algorithm. To aid in that, I would like if printing shapes like Edges and Faces would offer some more useful insights then the standard:

<build123d.topology.Edge object at 0x000001CCE09F2810>

Something like:

Edge - CIRCLE of radius=12.5 at (5, 5, 22)
Edge - LINE of length=50 at (1, 5, 12)

A basic implementation can be achieved like this:

  def __str__(self):
    pos = self.center()
    type = self.geom_type()
    dim = ""
    if type == "CIRCLE":
       dim = f"radius={self.radius}"
     ....
     return f"Edge - {type} of {dim} at {pos}"

A more abstract solution might use a template to build the string

This would be a lot of work and is likely inferior to just using a viewer to show the selected object as follows:

b = Box(1, 1, 1)
top_points = b.vertices().group_by(Axis.Z)[-1]
show(b, top_points, alphas=(0.1, 1))

image
or

b = Box(1,1,1)
vertices = b.vertices().group_by(Axis.Z)[-1]
c = Pos(2,0,0) * Cylinder(0.5, 1)
edges = c.edges().group_by(Axis.Z)[0]

show(vertices, edges, show_parent=True)

image

I agree that seeing the feature is more intuitive, in the moment. However, my point is that in order to build a reliable selector query, it would be useful to "see" the "features" of the things you are trying to filter. Sorted lists are especially unreliable, so i tend to use a lambda as such:

        latch_edges = adj.edges().filter_by(
            lambda e: e.geom_type() == "BSPLINE"
            and int(e.center().Z) < -self.height / 2 + 8
            and int(e.center().Z) > -self.height / 2 - 8
            and e.center().X < self.od / 2 + 1
        )

I am not sure I agree with "This would be a lot of work...".
I am happy to do proof of concept for Edge. Can you see any negatives of having this feature? If people don't use it, you won't hear about. Its not depended on by any other feature. If people like it, they might want it replicated on other types.

Why I describe this as "a lot of work" is that there are many different types of Edges. In OpenCascade the TopoDS classes (which are basis for the build123d Shape classes) are built from lower level Geom set of classes which are trimmed. So a circular arc at the TopoDS_Edge level is a Geom_Circle with start/end points (i.e. trimmed). So if the intention is to describe the underlying shape all of the following need to be addressed:

  • GeomAbs_Line,
  • GeomAbs_Circle,
  • GeomAbs_Ellipse,
  • GeomAbs_Hyperbola,
  • GeomAbs_Parabola,
  • GeomAbs_BezierCurve,
  • GeomAbs_BSplineCurve,
  • GeomAbs_OffsetCurve, and
  • GeomAbs_OtherCurve,

The same is true of Faces, etc. so in my mind this all adds up to "a lot of work". I'm not saying there is no value just that on the scale of value for effort I would place this quite low.

With respect to the filter_by selector you've constructed (which is fine) - are you aware that filter_by(GeomType.BSPLINE) and filter_by_position(Axis.Z,-self.height/2-8,-self.height/2+8) exist? lambda's are great for those that are comfortable with them but I know many newer programmers (and some very experienced programmers) don't like them. They are described in the docs (https://build123d.readthedocs.io/en/latest/key_concepts.html#custom-sorting-and-filtering) for folks as they are very powerful and convenient for selectors that can't be done with the standard ones.

I have use them, i just find that instead of chaining method calls, i would rather write a lambda, but i see your point.