Navigation

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Users
    • Groups
    • Solved
    • Unsolved
    • Search
    1. Home
    2. habakuk
    3. Posts
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Posts made by habakuk

    • RE: Even-Odd Fill Rule

      Hey @monomonnik
      The problem is, that the rose is made of a single path and not two overlapping objects. I hoped there is some kind of a blend mode to clear overlapping colors.

      posted in General Discussion
      habakuk
      habakuk
    • Even-Odd Fill Rule

      Subject: Help Needed with Even-Odd Fill Rule for Maurer Rose Animation

      Hello DrawBot Community,

      Me and my imaginary friend (AI) are reaching out for human intellignce once again. 😉 I'm currently working on creating an animated Moire Effect based on a Maurer Rose using DrawBot and have encountered an issue with applying the even-odd fill rule. The animation is supposed to alternate fills correctly to mimic the visual effect seen in examples like the one on this website. https://www.sqrt.ch/Buch/Maurer/maurerrosesanim.html However, doe to the missing even-odd filling rule, we haven't been able to achieve the desired effect.

      Here's what I’ve tried so far:

      Initial Attempt Without Even-Odd Fill Rule: (be carefull running this script, it takes ages to render. reduce the z variable to a low prime number)

      # Parameters for the Maurer Rose
      n = 5
      d = 1
      z = 853
      ms = 90
      dStroke = 1
      dFarbe = (0, 0, 1)  # Blue stroke color
      cFarbe = (1, 0, 0)  # Red fill color 
      
      newDrawing()
      
      for frame in range(z):
          newPage(1010, 1010)
          frameDuration(ms / 1000)
          translate(width() / 2, height() / 2)
      
          fill(0)
          rect(-width() / 2, -height() / 2, width(), height())
      
          path = BezierPath()
          for theta in range(z + 1):
              k = (theta * d * 2 * pi) / z
              r = -500 * sin(n * k)
              x = r * cos(k)
              y = r * sin(k)
              if theta == 0:
                  path.moveTo((x, y))
              else:
                  path.lineTo((x, y))
      
          path.closePath()
      
          fill(*cFarbe)
          drawPath(path)
      
          stroke(*dFarbe)
          strokeWidth(dStroke)
          lineJoin('round')
          drawPath(path)
      
          d += 1
      
      saveImage("maurer_rose_animation.gif")
      endDrawing()
      
      

      Attempt Without Unsupported Methods:

      # Draw the fill and stroke
      def draw_maurer_rose(d, n, z, dStroke, dFarbe, cFarbe):
          path = BezierPath()
          for theta in range(z + 1):
              k = (theta * d * 2 * pi) / z
              r = -500 * sin(n * k)
              x = r * cos(k)
              y = r * sin(k)
              if theta == 0:
                  path.moveTo((x, y))
              else:
                  path.lineTo((x, y))
          path.closePath()
      
          fill(*cFarbe)
          drawPath(path)
      
          stroke(*dFarbe)
          strokeWidth(dStroke)
          lineJoin('round')
          drawPath(path)
      
      # Animation loop
      for frame in range(z):
          newPage(1010, 1010)
          frameDuration(ms / 1000)
          translate(width() / 2, height() / 2)
      
          fill(1)
          rect(-width() / 2, -height() / 2, width(), height())
      
          draw_maurer_rose(d, n, z, dStroke, dFarbe, cFarbe)
      
          d += 1
      
      saveImage("maurer_rose_animation.gif")
      endDrawing()
      
      

      ...despite several attempts, I haven't been able to achieve the desired even-odd fill rule effect. I would appreciate any guidance or suggestions on how to properly implement the even-odd fill rule for this animation in DrawBot.

      Thank you in advance for your help!

      posted in General Discussion
      habakuk
      habakuk
    • RE: extracting anchor and control points in a variable font

      Thank you @mmonomonnik ! Your sample code helped solving the issue I was facing with correctly visualizing the on-curve and off-curve points for a variable font.

      Me and my imaginary friend now got the correct method for extracting and differentiating between on-curve and off-curve pointsand are able to correctly identifying and iterating through the segments of each contour. An important fix was ensuring that lines were drawn only between appropriate points, avoiding unnecessary connections that had previously cluttered the visualization.!

      points_animation_with_final_path_s.gif

      posted in General Discussion
      habakuk
      habakuk
    • extracting anchor and control points in a variable font

      Hi there
      I have to reach out for real human natural intelligence - since the imaginary intelligence called AI is not able to help in this case. 😉 thank you in advance!

      Issue: Difficulty extracting and drawing anchor and control points in a variable font using DrawBot.

      Font: RobotoFlex VariableFont

      Initial situation:
      I want to extract and draw the anchor and control points of a variable font. I tried different approaches to extracting and plotting the points but kept running into problems. Here are the details of the attempts and the errors encountered:

      Script 1

      # Set up canvas
      canvas_width = 500
      canvas_height = 500
      txt = "H"
      variable_font_path = "/Users/tobiasulrich/Downloads/Roboto_Flex/RobotoFlex-VariableFont_GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght.ttf"
      fontSize = 400
      point_size = 10  # Größere Punktgröße für bessere Sichtbarkeit
      
      newPage(canvas_width, canvas_height)
      fill(1)  # Weißer Hintergrund
      rect(0, 0, canvas_width, canvas_height)
      fill(0)  # Schwarzer Text
      stroke(0)
      strokeWidth(1)
      
      # Create a FormattedString with the text and variable font
      formattedString = FormattedString(txt, font=variable_font_path, fontSize=fontSize)
      
      # Get the Bézier path of the text using FormattedString
      path = BezierPath()
      path.text(formattedString, (50, 50))
      
      # Draw the text path
      drawPath(path)
      
      # Initialize lists to hold on-curve and off-curve points
      on_curve_points = []
      off_curve_points = []
      
      # Iterate through contours and segments to extract points
      output = ""
      for contour in path.contours:
          for segment in contour:
              # Debug print to check the structure of the segment
              print("Segment:", segment)
              if hasattr(segment, 'points'):
                  if segment.type == 'moveTo':
                      x, y = segment.points[0]
                      output += f"moveTo: ({x}, {y})\n"
                      on_curve_points.append((x, y))
                  elif segment.type == 'lineTo':
                      x, y = segment.points[0]
                      output += f"lineTo: ({x}, {y})\n"
                      on_curve_points.append((x, y))
                  elif segment.type == 'curveTo':
                      cp1 = segment.points[0]
                      cp2 = segment.points[1]
                      pt = segment.points[2]
                      output += f"curveTo: control point 1: ({cp1[0]}, {cp1[1]}), control point 2: ({cp2[0]}, {cp2[1]}), on-curve point: ({pt[0]}, {pt[1]})\n"
                      off_curve_points.append((cp1[0], cp1[1]))
                      off_curve_points.append((cp2[0], cp2[1]))
                      on_curve_points.append((pt[0], pt[1]))
      
      # Draw on-curve points
      fill(1, 0, 0)  # Rot für on-curve Punkte
      stroke(None)
      for (x, y) in on_curve_points:
          print("Drawing on-curve point at:", x, y)
          oval(x - point_size / 2, y - point_size / 2, point_size, point_size)
      
      # Draw off-curve points
      fill(0, 1, 0)  # Grün für off-curve Punkte
      stroke(None)
      for (x, y) in off_curve_points:
          print("Drawing off-curve point at:", x, y)
          oval(x - point_size / 2, y - point_size / 2, point_size, point_size)
      
      # Save the image
      saveImage("H_with_anchor_points.png")
      
      # Ausgabe der Koordinaten
      print(output)
      
      

      Error

      Traceback (most recent call last):
        File "<untitled>", line 35, in <module>
      AttributeError: 'list' object has no attribute 'type'
      
      

      Script 2

      # Set up canvas
      canvas_width = 500
      canvas_height = 500
      txt = "O"
      variable_font_path = "/Users/tobiasulrich/Downloads/Roboto_Flex/RobotoFlex-VariableFont_GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght.ttf"
      fontSize = 400
      point_size = 10  # Größere Punktgröße für bessere Sichtbarkeit
      
      newPage(canvas_width, canvas_height)
      fill(1)  # Weißer Hintergrund
      rect(0, 0, canvas_width, canvas_height)
      fill(0)  # Schwarzer Text
      stroke(0)
      strokeWidth(1)
      
      # Create a FormattedString with the text and variable font
      formattedString = FormattedString(txt, font=variable_font_path, fontSize=fontSize)
      
      # Get the Bézier path of the text using FormattedString
      path = BezierPath()
      path.text(formattedString, (50, 50))
      
      # Draw the text path
      drawPath(path)
      
      # Initialize lists to hold on-curve and off-curve points
      on_curve_points = []
      off_curve_points = []
      
      # Iterate through contours and segments to extract points
      for contour in path.contours:
          for segment in contour:
              # Debug print to check the structure of the segment
              print("Segment:", segment)
              if hasattr(segment, 'points'):
                  if segment.type == 'moveTo':
                      x, y = segment.points[0]
                      print("moveTo:", x, y)
                      on_curve_points.append((x, y))
                  elif segment.type == 'lineTo':
                      x, y = segment.points[0]
                      print("lineTo:", x, y)
                      on_curve_points.append((x, y))
                  elif segment.type == 'curveTo':
                      cp1 = segment.points[0]
                      cp2 = segment.points[1]
                      pt = segment.points[2]
                      print("curveTo:", cp1, cp2, pt)
                      off_curve_points.append(cp1)
                      off_curve_points.append(cp2)
                      on_curve_points.append(pt)
      
      # Draw on-curve points
      fill(1, 0, 0)  # Red for on-curve points
      stroke(None)
      for (x, y) in on_curve_points:
          print("Drawing on-curve point at:", x, y)
          oval(x - point_size / 2, y - point_size / 2, point_size, point_size)
      
      # Draw off-curve points
      fill(0, 1, 0)  # Green for off-curve points
      stroke(None)
      for (x, y) in off_curve_points:
          print("Drawing off-curve point at:", x, y)
          oval(x - point_size / 2, y - point_size / 2, point_size, point_size)
      
      # Save the image
      saveImage("O_with_anchor_points.png")
      
      

      Error: No error, but no points visible

      Konsole

      Segment: [(79.296875, 50.0)]
      Segment: [(81.25, 50.0)]
      Segment: [(81.25, 197.265625)]
      Segment: [(247.265625, 197.265625)]
      Segment: [(247.265625, 50.0)]
      Segment: [(249.21875, 50.0)]
      Segment: [(249.21875, 334.375)]
      Segment: [(247.265625, 334.375)]
      Segment: [(247.265625, 198.828125)]
      Segment: [(81.25, 198.828125)]
      Segment: [(81.25, 334.375)]
      Segment: [(79.296875, 334.375)]
      
      

      Script 3

      # Set up canvas
      canvas_width = 500
      canvas_height = 500
      txt = "H"
      variable_font_path = "/Library/Fonts/RobotoFlex-VariableFont_GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght.ttf"
      font_size = 400
      
      # Neue Seite erstellen und Hintergrund setzen
      newPage(canvas_width, canvas_height)
      fill(1)  # Weißer Hintergrund
      rect(0, 0, canvas_width, canvas_height)
      fill(0)  # Schwarzer Text
      
      # Schriftart setzen und prüfen, ob sie korrekt geladen wird
      font(variable_font_path)
      fontSize(font_size)
      
      # Alle Achsen der aktuellen Schriftart auflisten
      variations = listFontVariations()
      for axis, data in variations.items():
          print(f"Axis: {axis}, Data: {data}")
      
      # Eine Variation der aktuellen Schriftart auswählen
      if 'wght' in variations:
          fontVariations(wght=500)
      
      # Create a FormattedString with the text and variable font
      formattedString = FormattedString(txt, font=variable_font_path, fontSize=font_size)
      
      # Get the Bézier path of the text using FormattedString
      path = BezierPath()
      path.text(formattedString, (50, 50))
      
      # Initialize lists to hold on-curve and off-curve points
      on_curve_points = []
      off_curve_points = []
      
      # Iterate through contours and segments to extract points
      output = ""
      for contour in path.contours:
          for segment in contour:
              # Debug print to check the structure of the segment
              if hasattr(segment, 'points'):
                  points = segment.points
                  if segment.type == 'moveTo':
                      x, y = points[0]
                      output += f"moveTo: ({x}, {y})\n"
                      on_curve_points.append((x, y))
                  elif segment.type == 'lineTo':
                      x, y = points[0]
                      output += f"lineTo: ({x}, {y})\n"
                      on_curve_points.append((x, y))
                  elif segment.type == 'curveTo':
                      cp1 = points[0]
                      cp2 = points[1]
                      pt = points[2]
                      output += f"curveTo: control point 1: ({cp1[0]}, {cp1[1]}), control point 2: ({cp2[0]}, {cp2[1]}), on-curve point: ({pt[0]}, {pt[1]})\n"
                      off_curve_points.append((cp1[0], cp1[1]))
                      off_curve_points.append((cp2[0], cp2[1]))
                      on_curve_points.append((pt[0], pt[1]))
      
      # Draw on-curve points
      fill(1, 0, 0)  # Rot für on-curve Punkte
      stroke(None)
      for (x, y) in on_curve_points:
          print("Drawing on-curve point at:", x, y)
          oval(x - point_size / 2, y - point_size / 2, point_size, point_size)
      
      # Draw off-curve points
      fill(0, 1, 0)  # Grün für off-curve Punkte
      stroke(None)
      for (x, y) in off_curve_points:
          print("Drawing off-curve point at:", x, y)
          oval(x - point_size / 2, y - point_size / 2, point_size, point_size)
      
      # Save the image
      saveImage("H_with_anchor_points.png")
      
      # Ausgabe der Koordinaten
      print(output)
      
      

      Error

      Traceback (most recent call last):
        File "<untitled>", line 42, in <module>
      AttributeError: 'list' object has no attribute 'type'
      
      posted in General Discussion
      habakuk
      habakuk
    • RE: How to mirror/flip a object?

      Hallo @jo thanks alot - at the moment i use the lissajus only to create different nice looking loops. I changed the values as you suggested and of course it is working now and delivers a new nice looking loop. 😉
      I`d love to make some more loops with more "natural, subtle and slow" movements. I saw your great visualisations of the different variable font movements and hoped to create a custom path to do so - but i failed...

      if you like to play around with my very first 5 letter variable font (HABKU) you are very welcome. http://habaland.ch/images/habaroll8GX.ttf

      i added the the plus and minus to avoid the font doing the whole move to the min and max, because the backgraound would be visible then. (but most likely i created only a mess 😄 ) and by the way, i hate the black circle i had to ad "behind the scene" - id love o have a cleaner solution.

      ...at the moment i am trying to figure out where to append the savedState() without messing everything up...

      greetings from Bern

      posted in General Discussion
      habakuk
      habakuk
    • RE: How to mirror/flip a object?
      # --------------------------
      #  imports
      
      import sys
      sys.path.append("..")
      from helper_functions import *
      
      # --------------------------
      #  settings
      
      p_w, p_h = 1000, 1000
      margin = 40
      dia = 4
      steps = 600
      
      # lissajous values
      a = 2 # 2, 3, 4 are decent values
      b = a + 1
      delta = 0 # pi/2, pi/3, pi/4
      
      f_name = "habaroll8"
      
      axes = ['wght', 'wdth'] 
      
      # --------
      axis1_min = listFontVariations(f_name)[axes[0]]['minValue']
      axis1_def = listFontVariations(f_name)[axes[0]]['defaultValue']
      axis1_max = listFontVariations(f_name)[axes[0]]['maxValue']
      
      axis2_min = listFontVariations(f_name)[axes[1]]['minValue']
      axis2_def = listFontVariations(f_name)[axes[1]]['defaultValue']
      axis2_max = listFontVariations(f_name)[axes[1]]['maxValue']
      
      
      axis_w = p_w - 2 * margin
      axis_h = p_h - 2 * margin
      
      def_x = map_val(axis1_def, axis1_min, axis1_max, 0, axis_w)
      def_y = map_val(axis2_def, axis2_min, axis2_max, 0, axis_h)
      
      # --------------------------
      #  functions 
      
      def a_page():
          newPage(p_w,p_h)
          fill(1)
          rect(0, 0, p_w, p_h)
          translate(margin, margin)
      
          fill(0.92, 0.90, 0.87)
          rect(0, 0, axis_w, axis_h)
      
          font(f_name)
          fontSize(820 )
      
      
      # --------------------------
      #  Drawings 
      
      pts = []
      for st in range(steps):
      
          # newDrawing()
          a_page()
      
          angle = 2 * pi / steps * st
      
          x = .5 + .5 * sin( a * angle + delta )
          y = .5 + .5 * sin( b * angle )
      
      
      
          curr_axis1 = ip(axis1_min + 20, axis1_max - 20, x)
          curr_axis2 = ip(axis2_min + 20, axis2_max - 20, y)
          var_values = { axes[0] : curr_axis1, axes[1] : curr_axis2 }    
          fontVariations(**var_values)
          
          #black ring to avoid the background "bleed through"
          fill(None)
          stroke(0)
          strokeWidth(60)
          oval(125, 95, 700, 700) 
          
          # the black part (fake 3D)
          stroke(0)
          strokeWidth(4)
          fill(0)
          text('A', (axis_w/2, axis_h/8), align = 'center') 
          
          # the pink blob letter
          stroke(None)
          fill(0.79, 0.52, 0.67)
          scale(x=1.25, y=1.25)
          translate(x=-95, y=-80)
          text('A', (axis_w/2, axis_h/8), align = 'center') 
          
          # the blob shadow (would be great to have the shadow behind the pink blob!) 
          fill(0)
          translate(-120, 110)
          scale(x=0.9, y=-.05)
          skew(25, 0)
          rotate(-3)
          text('A', (axis_w/2, axis_h/8), align = 'center') 
      
      
        
      saveImage('lissajous_var_test12.gif')
      
      
      posted in General Discussion
      habakuk
      habakuk
    • RE: How to mirror/flip a object?

      Hey @jo - thank you very much! That was the issue - damn, i am still in trouble with the the basics. Actually i am pretty stoked to have you here responding, because i am messing around with your code... 😉 i`d love to ad different lissajous curves to my blobbish letters, and i hoped changing the numbers (a = 2 # 2, 3, 4 are decent values) would do the trick - but it does not really change that much - sometimes even the loop is not longer working. Would you mind having a look at my codemess? (i mean, your code - and my mess 😄 )

      A-Blob

      posted in General Discussion
      habakuk
      habakuk
    • RE: How to mirror/flip a object?

      Hello @ricardov Yes, i tried negative scaling, but it gives no result. It gives no error, but there is also nothing happening...

      posted in General Discussion
      habakuk
      habakuk
    • RE: How to mirror/flip a object?

      My goal is to draw a shadow, so I have to mirror the letter. (i achieved scaling, skewing, but not flipping)

      newPage(1000, 1000)
      
      font('Skia')
      fontSize(600)
      fill(0.79, 0.52, 0.67)
      text('A', (300, 200))
      fill(0)
      scale(x=1, y=0.05)
      text('A', (300, 800))
      
      posted in General Discussion
      habakuk
      habakuk
    • How to mirror/flip a object?

      Hello World, i have a struggle on a very simple task - how can i mirror/flip a bezier path object (or a text) horizontal and vertical?

      thanks in advance

      posted in General Discussion
      habakuk
      habakuk
    • RE: stuck in the code

      Hello @gferreira

      I know how to move the blob and the hole separately. (Last example in my first post) My question is, if there is any way to move a group of objects together? I like to have a blob with several holes that act as one object? (If I change the movement of the blob, the holes will change too).

      Sorry, my english is not very good ...

      posted in Code snippets
      habakuk
      habakuk
    • RE: stuck in the code

      Hello @michelangelo

      Thank you very much, your code is very inspiring. I played around and it moves just how it should - except the "hole". Can the hole somehow act related to the blob and move just as it would be a part of the blob? (clipping?)

      michelangelo_blob2s.gif

      # Define a function to draw your shape
      def Blob(offset):
          
          # Let's make a Bezier Path shape
          bez = BezierPath()
          bez.qCurveTo((80 + offset, 80 + 0.2 * offset), (80 + offset, 920 + 0.8 * offset), (920 + 0.1 * offset, 920 + 0.3 * offset), (920 + 3 * offset, 80 + 0.5 * offset), None)
          # Here I make Another shape, but it's going the opposite direction
          bez.moveTo((700, 300))
          bez.lineTo((700, 700))
          bez.lineTo((300, 700))
          bez.lineTo((300, 300))
          bez.closePath()
          fill(0.79, 0.52, 0.67)
          stroke(None)
          drawPath(bez)
          translate(60, 15)
          scale(x=0.8, y=0.03)
          fill(0)
      
          # Drawing the shape here
          drawPath(bez)
          
      numFrames = 60
          
      for i in range(numFrames):
          t = i / numFrames
      
          newPage(1000, 1000)
          fill(0.92, 0.90, 0.87)
          stroke(1)
          strokeWidth(80)
          rect(0, 0, 1000, 1000)
      
          
          
          
          # The function takes an argument "offset" to create the movement (it loops at * 50, * 25 * 12.5, * 6.25, 3.125
          offset = sin(t * 12.5) * 10
          print(offset)
          Blob(offset)
      
      saveImage("michelangelo_blob2.gif")
      
      posted in Code snippets
      habakuk
      habakuk
    • RE: stuck in the code

      @michelangelo @michelangelo Heyho! Thank you so much for responding 🙂 I had a whole mess of code in here, after a month or so with no reaction i deleted it - i felt ashamed, i thought my code mess must look hopeless to you guys. i will have a look at your example, and reupload some bits and pieces. Greetings

      posted in Code snippets
      habakuk
      habakuk
    • RE: stuck in the code

      ...beneath the "counter/holes" i am trying hard, to animate each cornerpoint (off line point) of the qcurve-path seperatly, to get e more irregular movement. I am open to every new inspiration from you guys, thanks in advance.

      posted in Code snippets
      habakuk
      habakuk
    • stuck in the code

      Hello World :::-)

      Let me explain... I know nothing about code or coding.
      As a graphic designer i am familiar with vector path, and i use to know some basics in html and css - just enough to have had a glimpse at the beauty of code, once upon a time late at night. Then i stumbled upon the drawbot app and id seems like the time has come for me to learn something new. Coding animations with drawbot/python.
      I looked at the nice works you guys creating, played with your shared codes and had some succsess. I love to learn stuff by myself.
      Soon i realised, that my recent all-pink procreate doodles probably can be animated. I found a nice Blob animation and somehow managed to create my own blob, with bits and parts of code. Have a look at my instagram: https://www.instagram.com/das_habakuk/

      blobb1.gif

      i turned the blob into my signature letter/character "H" and everthing seemed to be allright...

      (blob8.gif

      ...and now it seems like i`m stuck - no more succsess, no more progression. I really dont like to share my beginner-codes, but maybe i have to do it.

      i wrote that all, to let you know what my goals are - it is not possible to write down every single question i have. I try to dance my name, somehow. :::-)

      I know, that several parts of my codes are useless, i figured out, that i dont need to import math and many other things. Altough, i havent managed yet, to fit the "counters" (holes) into my blob, to make it look like this:

      IMG_0350.jpg

      i managed to create two "counters/holes", and they even move, but they act like two little blobs, instead of being "clipped" to the movement of the main blob.

      blob22s.gif

      i know, for you guys this must be a terrible mess - please be kind!

      thanks in andvance, greetings from switzerland
      tobias aka. habakuk

      edit: sorry, i posted in the wrong forum - this used to be in the "general discussion"

      posted in Code snippets
      habakuk
      habakuk