Exit Full View

FooCAD / todo.txt

Foo CAD To Do List
==================

Current
-------

Next
----

Print Tools/ZipTie and ScrewSizes

Add "ThreadedInsert" to Screws extension,
    Just creates holes for standard size inserts.

API for Java preferences within extensions.
    ScriptExtension can return a wrapper for Java's preferences, where the node is for the ScriptExtension's package name.
    Allow finding sub-nodes too, but make sure the name only contains letters (to avoid possible hacks).


Rework ChangeFilament, by including GCode commands on Printer for pausing a print.
    Default it to M??? by default.

Ding and beep on success/failure.
    Either via a new Glok API, or directly using Java APIs???

Bugs
====

Text's spacing isn't supported when converting to a polygon.

Transformations of shapes containing faces with more than 3 points may fail.
    The face may become non-planar.
    Extrusion, Cube...
    I've already ported code which converts a polygon into triangles, but maybe it only handles 2d.
        Therefore, either map to Z=0 and back again, or write/port a 3d version.

Next
====

SmartExtrusion currently extends holes by a tiny amount, which is not suitable when used with aroundCylinder.
    Either add an option, or always add a straight extrusion at the bottom/top of the holes.

SVGDocument to support Text.

Rework PostProcessor / ChangeFilament extension.
    The "find" methods should take a lambda or feather Function to apply???

Multi-pass prints.
    Print 1 colour, pause, change filament, then print the next colour.

Customiser to show which values have been changed, and also a button to reset it to the default value.
    Use the same system for CustomiserDock and ModelExtensionsDock.
    Started work on this in ~/tmp/CustomValues.kt.
    But it is badly designed, as it doesn't consider compound values (such as TextStyle).

Consider .label( str )
    Maybe have a static var renderLabels = false
    And when it is true, it adds a Text. Otherwise, it just returns the original shape.
    Maybe also have a size threshold, so it only shows on the large parts.
    And/Or include an optional "detail" value.
    Option to hide repeated items (e.g. when using .also())
    This could be an extension. A Shape extension which excludes the label objects
        (as well as the Union which holds them)

New extension (or add to existing?) :
    .growY( by : double ) = scaleY( (size.y + by) / size.y )
    .shrinkY( by : double ) = scaleY( size.y - by) / size.y )
    .growSymmetricY( by : double ) = growY( by ).translateY( by / 2 )
    .shrinkSymmetricY( by : double ) = shrinkY( by ).translateY( -by / 2 )

    Ditto for x and z.

Load/Save ModelExtension state?
    Maybe on a per-model basis (as a .ini file)?
    Or on a per-piece basis

Thoughts on join heuristic.
  Consider an iterative process, with scores, rather than a rule based approach.
    Try all offsets, and join up in a simple proportion of the number of points in each shape.
        (breznam style choice of which to increase)
        Pick the one with the best score
    Pick each point, and change the join locally. Keep the change if the score is better.
        (For efficiency, we could probably score just the points affected, rather than the whole join.

    Join "simply" at first
        Find the furthest point from the center of shapeA. Remember its angle from the center.
        Find the point of ShapeB whose angle from the center is most similar.
        Make "fewest" either shapeA or shapeB, based on the number of points.+
        Start from these points, and move clockwise, pairing up points.

Create unit tests for JoinStrategy.

    Give each point an angle from its center (maybe bounding box's center, or maybe center of gravity).
    No we want to minimise the sum of the differences in the angles of pairs.
        Start by pairing them up "unaligned", but equally spaced. i.e. no big gap at the beginning or end.
        Rotate the smaller path finding the "most aligned".
        For each point in the short path, see if we can move it to a better neighbour.
            Shift the point clockwise (other points may also be shifted if they are paired to the same point)
                Compare to the previous sum. If smaller, use it.
                    loop until the sum is worse
            If we didn't shift clockwise shift it anti-clockwise (other points may also need to be shifted)
                Compare to the previous sum. If smaller, use it.
                    loop until the sum is worse
        NOTE. the order that we try shifting the points may be optimised if we "bounce around".
            i.e. use 0, n-1, n/2, 3*n/3 etc.
    Now we have paired the shortest path's points with some of the points from the largest path.
        Unpaired points will map to both of the nearest opposite pairs points.
        In addition, there will be pairing for the "diagonals" between adjacent paired points.
            We need a heuristic to choose which diagonal is best.
                If we think of the two pairs forming a rhombus, then pick the shorter diagonal.

    Consider a PairedJoinStrategy, where the user pairs up SOME of the points (either using indices,
        or using "closest to point ?"
    The Default Join Strategy uses a heuristic to create a PairedJoinStrategy
        The unit tests for DefaultJoinStrategy can interrogate the PairedJoinStrategy

Maybe create a ManualJoinStrategy, which defines for each point of the 1st shape which point of the 2nd shape
it joins to.

Worm. a reimplementation for ExtrusionBuilder that IS a Shape3d, which we can also add to.
    i.e. mySquare.drum( mySquare.offset(-1), 10 ).drum( myCircle, 10 ).extrude( 10 )
    Each "drum" would have to return a new instance.
    Note that we can mix drum and extrude. We would need Extrusion and Worm to share a common interface,
        so that extrude could be the first operation.
    Methods :

        var direction = Vector3d(0,0,1)
        var north = Vector3d(0,1,0)

        bendLeft/Right(degrees)  // only affects direction, not north ??
        bendForwards/Backwards(degrees) // affects direction and north ??
        twist(degrees) // only affects north ??

        extrude(length)
        extrude(length,shape) // Should this be called "drum"? I like that the last parameter is a new shape2d.
        extrudeTo(vector3) // We calculate the bend, length and translation (of the shape2d).
            equivalent to bend, drum( prev.translate(x,y), l )
        close()

    We can extrude around a Path2d without ambiguity (closed or open)
        Two choices - constant cross section, or join.
    We can NOT extrude along a Path3d without ambiguity though???

    Call this new class "Worm" ;)

    Describe bend and twist using a gun shaped hand pointing upwards, then forwards (two routes).

Later
-----

Code review, looking for methods to deprecate. e.g. Shape3d.cutZRatio, toOriginZ etc.
    val Shape3d.middle renamed to fun center()

My bezier curves are currently split into straight lines in a non-optimal manner
    (some corners are sharper than others). Here's some help...
    https://www.youtube.com/watch?v=aVwxzDHniEw

Check for deprecated method calls.
    Feather needs to check for deprecated methods, and store their use and/or write an output a message.
        Could also just set a flag, which can be checked by foocad after compiling.
    What about deprecated methods in extensions? I'd need to add more syntax to feather too.

ExtrusionBuilder
    Has no way to state the 1st orientation when following a shape/path.
    A confusion of methods, some of which aren't compatible with others.
    Existing style is tricky to get right compared to following a 2d path, so
        convert models (especially examples) to use paths with offsets/scales for the profiles.
    Settle on a naming convention for "crossSection" or "profile" (maybe rename crossSection methods to "profile"?)
        with deprecated crossSection methods which call profile.

Later
-----

ExtensionsDock to have a ChoiceBox for which extensions-directory to use,
    with an option of "All"
    Hide it, when there is only 1 extension directory.