Exit Full View

FooCAD / todo.txt

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

Opening and printing a SCAD file probably doesn't work yet.
Ditto for STL.

Current
-------

Load/Save ModelExtension state?

2.0
===

CustomiserDock
    Not all types are supported.

Use InterruptWorker to load scripts at start up
    With a countdown latch? So that compiling models wait until the extensions have loaded (or failed to load).
    ModelExtensionsDock need the extensions at startup :-(
        Maybe a property holding the time the extensions were last reloaded.

Bugs
====

Feather reports a recursive type exception for code such as :
    fun foo() = ...
    val foo = foo()
The workaround :
    val foo : Whatever = foo()

AllPiece.feather arrange(List<Shape3d>, double) couldn't be found.

Next
====

Allows Model/Shape/Script extensions to be edited within the App.
    If the file is inside one of the extensions folders, reload extensions.
    Add an ExtensionsDock.

Building model from the command line uses different code compared with using the GUI, therefore could result in
    different behaviour (easy to introduce bugs in the command line!)

Helper.arrange() methods should probably be an extension.
    Used by the AllPieces extension, but may be used by models too.



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).

Bugs
----

Maybe Cavity is bugged? Tried to use cavities with "insert"s in HingeLayingDown.

The generated html for script extensions are generated in the extensions directory without
    a package name. Therefore, two extensions with the same (unqualified) class name will clash.

ScriptExtension APIs do not include any "javadoc" comments.
    Consider parsing the comments by the Feather compiler (optionally, and off by default),
    and add them to the class (maybe as an Annotation).

Not all slicer settings should be exposed to code. For example, there is no need to change the temperature.

PostProcessors have access to add arbitrary gcode, so printer safety doesn't exist!
    Maybe the "insert" functions should only allow whitelisted GCode commands.
    That still won't prevent malicious gcode from crashing the head.
    The bare minimum is to prompt before calling postProcess.

Font names in the Help menu are wrong? They should use BOLD rather than Liberation Sans:style=Bold
    Also, the non-standard list has duplicates e.g. Comic Sans Bold.

Next
----

A new window where extensions can be edited. (And tested).
    Move the "Reload Extensions" to that window.

ScriptExtensionsDock

Allow "Layer" (in Layers extension) to be @Custom-isable.
    Only height and color are modifiable.

Allow @Custom to be used with special objects, to define things such as screws. hinges etc.
    If the object has vars, then each could itself be @Custom.
    Maybe include a "Customisable" interface, but it wouldn't actually do anything. ???

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

BOMTask should group all lumber which has the same width and thickness.
    This allows a plan to use different Lumber instances for each part of the job,
    but if the same size lumber is used, then it is all taken from the same stock.

Favourite font names???

Check for deprecated method calls, and replace the "ding" with a dull thud, and a status message.
    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.

ChamferedExtrude extension is good, but I've often wanted to chamfer only SOME edges.
    e.g. one face will mate to another piece, and this face shouldn't have a chamfer.
    Is there an elegant solution?

Text to a Union2d, or a List of Shape2d
    So that each character can be separately manipulated.
    Shape2d.parts() : Union2d // Each "solid" as a separate shape2d, but holes stay with their solids, as a Difference2d.
        Check if the hole's bounding box is whole contained in just one solid's bounding box.
            If more than one, then check if the (first) point(s) are inside the solids.

Add a heuristic for the convexity of text???
    number of letters * a constant
    Maybe only consider the longest line for multi-line text.

The latest example shows problem with transforming Shape3d's points.
    Co-planer faces can become non-co-planer.
    When extruding, the choice of which  points to stitch together becomes important.
        It would be better if the triangles were near equilateral rather than long and thin.
    Extruding each part, and then putting together doesn't work well for extrusions, because
    the Difference uses the same plane as the positive part (so we get badly formed solids).

Later
-----

Consider re-writing the construction module as Feather scripts.

SVGParser allows access to File (kind of)...
    It will attempt to open a file anywhere in the system.
    Perhaps the default should be to only allow files from the same directory as the script???
    Also check that feathers "include" does allow the same thing???