Giter Club home page Giter Club logo

chalk's People

Contributors

biogeek avatar danoneata avatar punchfox avatar srush avatar sugatoray avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

chalk's Issues

Support for sub-diagrams / arrows

Following the spirit of the Diagrams API this will add named/withName functions that will allow the user to get the transformed location of named elements to draw connections.

Correct and update the `Makefile`

The Makefile has a few problems, and also it is not well documented and well organized. If properly worked on, it could simplify a lot of steps.

  1. .PHONY declarations are either nonexistent or the commands that should have been updated, are not there.
  2. Parametrization of the make commands with variables could lead to lesser human-error. This will require some reorganization.
  3. Add make commands that can directly run several steps such as flake, black, type, clean, etc.
  4. Add doctest checker interrogate to the workflow. For now set the requirement at 0% to pass interrogate runs.
  5. Add documentation to various sections to clearly explain what they are for.

Add GitHub actions workflow to `self-assign` issues by repository members

Add GitHub actions workflow selfassign.

  • This will allow repo-members to self-assign issues with a comment containing #self-assign on any open-issue in this repository.
  • This also reduces any maintainer ToDo items for assigning issues.
  • This will be helpful to allow self-motivated repository members to self-assign the issues they want to work on, as more and more people start contributing to this repository.

Clean up the docs

Replace a bunch of the placeholders in the docs with more descriptive string.

Place the connecting arrow between the centers of two diagrams on their corresponding bounding boxes

I don't know if this would improve the visuals of the arrows, but I was wondering whether it would help to emulate the behaviour of connectOutside from diagrams (but using bounding boxes instead of traces):

The arrow lies on the line between the centres of the diagrams, but is drawn so that it stops at the boundaries of the diagrams

Ideally, I would like to be able to draw something like this

but without manually specifying the "cardinal" points of each arrow.

@srush What do you think? Is it worth investing time in something like this?

Multiple interpretations

Haskell's diagrams allows for multiple interpretations of the domain specific language (DSL). For example, the code

mconcat . iterateN 3 (rotateBy (1/9)) $ triangle 1

can yield various outputs depending on how it is interpreted: the image on left, if interpreted as a diagram, or the third image, if interpreted as a trail.
image
(See their manual for more information.)

This feature might be nice to have (it will allow drawing something like the Hilbert curve), but I expect to be rather involved.

Geometry Library

I looked at a couple of Geometry libraries today to see if we could pull that part out of chalk. My conclusion is that the best one to use would be Planar. https://pythonhosted.org/planar/

It's a weird choice, because it is unsupported, and hasn't been updated since 2011. However, I found it because it is where our Affine class comes from which I really like.

Benefits of Planar:

  • Simple API that looks like what you built.
  • Optionally has a C implementation
  • Very similar vector, segments, polygons, bounding boxes to what we have.
  • Additional functionality for convex hulls etc.
  • Has a fast Vec2Array class that we could use for long path/trails.
  • Includes Affine.

Downsides:

  • No support for circles, arcs
  • On pip and works, but not currently supported (but how much has 2d geometry changed in 10 years)

Add docstrings to `chalk.bounding_box.BoundingBox`

Add docstring to all the methods under chalk.bounding_box.BoundingBox.

import chalk
print('\n'.join([f"- [x] `{e}()`" for e in dir(chalk.bounding_box.BoundingBox) if not e.startswith("_")]))

The methods of chalk.core.Diagram:

  • apply_transform()
  • bl()
  • bottom()
  • cardinal()
  • center()
  • empty()
  • enclose()
  • from_limits()
  • height()
  • left()
  • reflect_x()
  • reflect_y()
  • right()
  • rotate()
  • rotate_by()
  • scale()
  • scale_x()
  • scale_y()
  • shear_x()
  • shear_y()
  • top()
  • tr()
  • translate()
  • translate_by()
  • union()
  • width()

Sync line widths across backends

Following diagrams plan is to use "normalized" units for setting line_widths and arrow sizes.

The way this works is that there will be two commands line_width_local and line_width. The first will scale with the transformations applied to it, and the second will be a scale_invariant, but will be a fraction of the final document size.

This is implemented for the SVG backend using the vector-effect command. For PNG and PDF need to think through the best way to do it.

Add docstrings to `chalk.core.Diagram`

Add docstring to all the methods under chalk.core.Diagram.

import chalk
print('\n'.join([f"- [x] `{e}()`" for e in dir(chalk.core.Diagram) if not e.startswith("_")]))

The methods of chalk.core.Diagram:

Legend: 🟠 Not Applicable

  • above()
  • above2()
  • align_b()
  • align_bl()
  • align_br()
  • align_l()
  • align_r()
  • align_t()
  • align_tl()
  • align_tr()
  • apply_transform()
  • at_center()
  • atop()
  • beside()
  • center_xy()
  • dashing()
  • display()
  • fill_color()
  • fill_opacity()
  • get_bounding_box()
  • get_subdiagram_bounding_box() 🟠
  • line_color()
  • line_width()
  • named()
  • pad()
  • pad_b()
  • pad_l()
  • pad_r()
  • pad_t()
  • reflect_x()
  • reflect_y()
  • render()
  • render_svg()
  • rotate()
  • rotate_by()
  • scale()
  • scale_uniform_to_x()
  • scale_uniform_to_y()
  • scale_x()
  • scale_y()
  • shear_x()
  • shear_y()
  • show_bounding_box()
  • show_origin()
  • to_list()
  • to_svg() 🟠
  • translate()
  • translate_by()

Placing elements based on a list of points or another diagram

For the placement of the nodes, it might be useful to have a counterpart of the functions position or atPoints from diagrams. These would allow to place node elements at a given location based on a list of coordinates or the points from a given diagram:

nodes = [circle(0.3) + text(str(i), 0.2) for i in range(6)]
diagram = place_at_points(regular_polygon(6, 1).as_points(), nodes)
# or alternatively
diagram = regular_polygon(6, 1).place(nodes)

Doing the effective placement should be straightforward; the harder bit is to to get the "points" of a diagram.

Right side operators

One thing I have been needing a lot is right-headed version of composition. I am not sure of the language for this in terms of monoids, but I want it to be like :

d1 / d2 where the origin stays at d2 instead of moving to d1.

I was thinking of notating this like

d1 // d2 , but maybe that is confusing. I guess the alternative would be to have a left facing below operator d2 \ d1 if that is possible in python.

Any thoughts.

Add a `dev_requirements.txt` file

Add a dev_requirements.txt file:

  • Add the following requirements to it, as these are not listed anywhere for quick dev-environment setup.
    • black
    • flake8
    • mypy
    • interrogate (necessary for #41)

πŸ”₯ This WILL NOT be source-tracked.

Make PyCairo Dependency Optional

The Cairo API is really nice, but it is a pain to install in many contexts. When working in a notebook, the SVG backend seems fine and has minimal dependencies.

Proposal:

  • Replace the Transformations class with Affine: https://github.com/rasterio/affine
  • Remove all the SVG renderers in transformations.
  • Write converters from Affine to SVG "matrix" and cairo "Matrix"
  • Figure out a better solution for SVG text sizes than calling Cairo.

Inner styles in SVG are not getting overwritten

This code

circle(1).fill_color(papaya).fill_color(black)

generates a black circle when rendered as PNG and a papaya one when rendered as SVG. The expected behaviour should be the former. The generated SVG code seems correct:

<g style="fill: #000000;"><g style="fill: #ff9700;"><g style=";" transform="scale(1)"><circle cx="0" cy="0" r="1" /></g></g></g>

Should we resolve the styling prior to rendering? Or is there a simpler solution?

Better Text bounding boxes

For text bounding boxes we are reliant on calling PyCairo TextExtents. As far as I can tell this function call is just broken, or something else is going wrong:

image

One solution is that if we know the exact font there are ways of calculating sizes. However this might rely on having a font distributed with the library.

Support curves

Connectors need curves to look good.

Not sure how to do this. I like the "bend right" / "bend left" in tikz, but maybe Diagrams has a better API.

PGF/TikZ backend

I would really like to never have to write TikZ again. Looking at the PGF API it seems similar to Cairo, and we could draw to it. Diagrams has a PGF backend, but it does look like it needs to setup a connection to a PGF server of some sort to measure font sizes.

`Planar` install issue.

It seems like planar relies on a conversion library 'build_py_2to3' that is deprecated in the latest versions of distutils. This is a note to myself to fix this.

I think the best way to do this may be to just host a modern version of this code. My fault for using an old library.

@renhaofan

I try to run command pip install git+https://github.com/danoneata/chalk@srush-patch-1, But an error occurred:

Γ— python setup.py egg_info did not run successfully.
β”‚ exit code: 1
╰─> [13 lines of output]
Traceback (most recent call last):
File "/tmp/pip-install-ofq9w8yg/planar_3384c07b07cb49e694e3d9f59655d633/setup.py", line 11, in
from distutils.command.build_py import build_py_2to3 as build_py
ImportError: cannot import name 'build_py_2to3' from 'distutils.command.build_py' (/home/steve/.conda/envs/py37/lib/python3.7/site-packages/setuptools/_distutils/command/build_py.py)

  During handling of the above exception, another exception occurred:
  
  Traceback (most recent call last):
    File "<string>", line 36, in <module>
    File "<pip-setuptools-caller>", line 34, in <module>
    File "/tmp/pip-install-ofq9w8yg/planar_3384c07b07cb49e694e3d9f59655d633/setup.py", line 14, in <module>
      raise ImportError("build_py_2to3 not found in distutils - it is required for Python 3.x")
  ImportError: build_py_2to3 not found in distutils - it is required for Python 3.x
  [end of output]

And my python version is totally the same with Colab.

sys.version
'3.7.13 (default, Mar 29 2022, 02:18:16) \n[GCC 7.5.0]'

Add a display method to `chalk.core.Diagram`

Adding a display method to chalk.core.Diagram object could be very helpful in visualizing the diagram, without having to save it on disk.

The chalk.utils.imgen() function will be used here.

Name?

Kind of goofy, but made in pydi[agrams]

image

SVG backend

Cairo is really powerful in that it let's you export to a lot of backends, but there are some cases when just SVG would be simpler and allow for more features. For example arrow heads are trivial in SVG and basically impossible in Cairo.

The plan is to include a render_svg function on shapes / style, using svgwrite. Since SVG is heirarchical this also means to_list is not necessary for this backend.

Envelopes

Notes on Envelopes from reading Pearl.

  • Replace cached bounding box on Diagrams with Envelope class.
  • Primitives can still return bounding boxes, ie for rect, spacer, etc. Diagram will wrap these in a function that returns distance to boundaries from origin.
  • For paths of segments, we compute convex hull? Envelope computes distance to nearest half space.
  • For circle it returns L2 * radius of vector?
  • For arcs it is l2 is pointing in. -l2 if pointing out, and otherwise ...? (Distance to tangent at last angle?)
  • For text, the envelope always returns 0
  • Transformables are implemented for envelopes like Traces.
  • For atop, simply max the resulting envelope (since origin is shared).
  • For concat, we should special case it for efficiency. Take the max of all diagrams in one function to avoid n-calls.
  • Envelope class might have some of the same properties as bounding box. Left, right, width, height. Although perhaps this is misleading if it is rotated.

Questions:

  • Does additive pad make sense any longer? Diagrams uses multiplicative.
  • Should we add directionally oriented atop? Is that useful?
  • How do we envelope paths with arcs in them? Or just arcs?
  • Should we allow using bounding boxes still? Might be more efficient in some cases.

Add docstrings to `chalk.point.Vector`

Add docstring to all the methods under chalk.point.Vector.

import chalk
print('\n'.join([f"- [x] `{e}()`" for e in dir(chalk.point.Vector) if not e.startswith("_")]))

The methods of chalk.point.Vector:

  • angle()
  • apply_transform()
  • from_polar()
  • length()
  • reflect_x()
  • reflect_y()
  • rotate()
  • rotate_by()
  • scale()
  • scale_x()
  • scale_y()
  • shear_x()
  • shear_y()
  • translate()
  • translate_by()

Support Images

Plan is to follow the diagrams API with a image / Image class. Use cairo to get a size estimate. In svg they will just be symbolically imported and in cairo they will be rendered in.

update `setup.py` for more informative source (PyPI) packaging

Currently setup.py uses distutils but the GitHub workflow installs setuptools.

Additionally, update various optional keyword parameters in setup() function call to make the PyPI package publishing more informative.

  • update setup function parameters
    • add classifiers
    • add license_files
    • add project_urls
    • add packages (use find_packages() from setuptools)
  • add a pyproject.toml to the repository root

Add diagram display utilities, with or without saving image files on disk

  • Add a new chalk.utils module. This module will offer various diagram display utilities as follows.

    • utils.show(filepath: str):

      Use this function for displaying saved images from disk.

    • utils.imgen(d: Diagram, **kwargs):

      Use this function to display a diagram, without creating any permanent file on disk.
      πŸ‘‰ This function does the following:

      1. Creates a temporary file.
      2. If necessary, it also creates a temporary folder for storing the temporary file.
      3. Displays the temporary-image-file for a user-specified (optional) 5 seconds.
      4. Clears up both the temporary file and folder after the 5 seconds have elapsed.
    • utils.quick_probe(**kwargs):

      Use this function to quickly generate a default sample Diagram (or a user-provided Diagram) and display it without saving it.

I believe, with these utilities it will be quite easy to visualize diagrams without having to save them on the disk.

Add docstrings to `chalk.point.Point`

Add docstring to all the methods under chalk.point.Point.

import chalk
print('\n'.join([f"- [x] `{e}()`" for e in dir(chalk.point.Point) if not e.startswith("_")]))

The methods of chalk.point.Point:

  • apply_transform()
  • reflect_x()
  • reflect_y()
  • rotate()
  • rotate_by()
  • scale()
  • scale_x()
  • scale_y()
  • shear_x()
  • shear_y()
  • translate()
  • translate_by()

Add docstrings to `chalk.trail.Trail`

Add docstring to all the methods under chalk.trail.Trail.

import chalk
print('\n'.join([f"- [x] `{e}()`" for e in dir(chalk.trail.Trail) if not e.startswith("_")]))

The methods of chalk.trail.Trail:

  • apply_transform()
  • from_path()
  • reflect_x()
  • reflect_y()
  • rotate()
  • rotate_by()
  • scale()
  • scale_x()
  • scale_y()
  • shear_x()
  • shear_y()
  • stroke()
  • to_path()
  • transform()
  • translate()
  • translate_by()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.