Giter Club home page Giter Club logo

Comments (19)

golanlevin avatar golanlevin commented on May 27, 2024 1

Hey @LingDong- , I tried this out with a particle repulsion system. It actually works OK, check it out in this animated GIF:

ezgif-4-71ab9ac3ea9f

Here's my quick filthy code for testing the idea:

int nHatches = 34; 
HatchLine hatches[];
float SL = 25; 
float friction = 0.975;

void setup() {
  size(400, 400); 
  
  hatches = new HatchLine[nHatches];
  for (int i=0; i<nHatches; i++) {
    float ay = map(i, 0, nHatches-1, height*0.25, height*0.75);
    float by = ay; 

    float dr = 100; 
    float dy = height/2 - ay; 
    float dx = sqrt(dr*dr - dy*dy); 
    float ax = width/2 - dx;
    float bx = width/2 + dx;
    PVector A = new PVector(ax, ay);  
    PVector B = new PVector(bx, by); 
    hatches[i] = new HatchLine(A, B);
  }
}


void draw() {
  background(255); 
  pushMatrix();
  translate( width/2, height/2); 
  rotate(radians(-30)); 
  translate(-width/2, -height/2);
  for (int i=0; i<nHatches; i++) {
    hatches[i].draw();
  }
  
  popMatrix(); 
  simulate();
}

void simulate() {
  float R = 3.3 * SL; 
  float STRENGTH = 0.001; 

  noFill(); 
  for (int i=0; i<nHatches; i++) {
    HatchLine H = hatches[i];
    for (int ip=0; ip<H.N; ip++) {
      float px = H.pts[ip].x;
      float py = H.pts[ip].y;

      for (int j=0; j<nHatches; j++) {
        HatchLine K = hatches[j];
        for (int jq=0; jq<K.N; jq++) {

          if (!((i == j) && (ip == jq))) {
            float qx = K.pts[jq].x;
            float qy = K.pts[jq].y;

            float dx = qx - px; 
            float dy = qy - py; 
            float dh = sqrt(dx*dx + dy*dy); 
            if ((dh < R) && (dh > 0)) {

              float F = STRENGTH/(dh*dh);
              float fx = dx/dh * F;

              if ((ip != 0) && (ip < (H.N-1))) {
                H.varray[ip] -= fx; // add acc
                H.varray[ip] *= friction; // add fric
                H.parray[ip] += H.varray[ip]; // add acc
                H.parray[ip] = constrain(H.parray[ip], 0,1); 
              }

              if ((jq != 0) && (jq < (K.N-1))) {
                K.varray[jq] += fx;
                K.varray[jq] *= friction; // add fric
                K.parray[jq] += K.varray[jq];
                K.parray[jq] = constrain(K.parray[jq], 0,1); 
              }
            }
          }
        }
      }
    }
  }
}


class HatchLine {
  PVector A; 
  PVector B; 
  int N; 
  float parray[];
  float varray[];
  PVector pts[];

  HatchLine (PVector a, PVector b) {
    A = a;
    B = b;
    N = 2 + (int)(dist(A.x, A.y, B.x, B.y)/SL); 
    parray = new float[N]; 
    varray = new float[N]; 
    pts = new PVector[N];

    for (int i=0; i<N; i++) {
      float t = map(i, 0, N-1, 0, 1); 
      float nt = 0; 
      if ((i > 0) && (i < N-1)) {
        nt = 0.75 * (noise(i/10.0 + A.x, A.y) - 0.5);
      }
      float tnt =  constrain(t + nt, 0, 1); 
      parray[i] = tnt;
      varray[i] = 0;
      pts[i] = new PVector(0, 0);
    }
  }

  void draw() {
    
    stroke(0); 
    line(A.x, A.y, B.x, B.y);
    fill(0); 
    noStroke(); 
    
    for (int i=0; i<N; i++) {
      float t = parray[i];
      float tx = lerp(A.x, B.x, t); 
      float ty = lerp(A.y, B.y, t); 
      pts[i].set(tx, ty);
    }
    for (int i=0; i<N; i++) {
      float px = pts[i].x;
      float py = pts[i].y;
      ellipse(px, py, 5, 4);
    }
  }
}

from pembroider.

golanlevin avatar golanlevin commented on May 27, 2024

Thanks @tatyanade, the staggered stitch endpoints is a very helpful suggestion. (@LingDong- , please see above). Also, Tatyana, please be aware of the setStitch() function,

E.setStitch( float min_stitch_length, float stitch_length, float resample_noise);
With larger resample noise, there's more variation among stitches, and therefore less of the problematic stitch alignment patterns. The default noise value is = 0.5.

from pembroider.

LingDong- avatar LingDong- commented on May 27, 2024

0ca31e8 added some improvement (?) to resample_noise with a weighted random, which will favour extreme values over mediocre values, as opposed to the uniform random that was used. Seems to help a bit.

maybe we need to rethink the resample algorithm

from pembroider.

golanlevin avatar golanlevin commented on May 27, 2024

@LingDong- , what if alternate (every other) hatch lines simply began with a half-length stitch? Then we wouldn't have to depend on noise, and could implement Tatyana's suggestion precisely:

IMG_8680

from pembroider.

LingDong- avatar LingDong- commented on May 27, 2024

I tried that already.

However it doesn't seem to help much because the circles curvature is quite large compared to stitch length, so these offsets get cancelled out very soon.

It is easy to come up with a solution for one situation, but harder to have a resample algorithm that works for all situations, (different hatch modes, outlines, etc.) One way is to make an algorithm for each shape and hatch mode.

from pembroider.

golanlevin avatar golanlevin commented on May 27, 2024

There's an interesting but ....kindof terrible... idea, which is to have the stitch points operate like a particle system, and mutually repel each other, but constrained to move only along their hatch lines, until an equilibrium is reached....

from pembroider.

LingDong- avatar LingDong- commented on May 27, 2024

@golanlevin cool!

Since we're now specifically fixing parallel hatching, I just had another idea while watching your simulation:

The stitches for parallel hatching can actually be the intersection with cross hatching

IMG_0844 copy

I can add some code for a special case when doing parallel hatching. Currently the resampler is ignorant of the nature of the thing it is asked to resample (it just tries its best looking at 1 polyline it is given), but seems like sooner or later we need branching

from pembroider.

golanlevin avatar golanlevin commented on May 27, 2024

I see what you're saying about the cross-hatch, but the relative angles or cross-spacing might need to be tinkered with to achieve the desired stitch length.

I improved my particle algorithm a little by having each particle only look at the two adjacent hatch lines (as opposed to all of them). Ultimately I don't think this simulation algorithm is practical, but it is interesting.

ezgif-4-258a3df60a98

I was inspired by the idea of Poisson-disc distribution sampling and was curious if it could be extended to a poly-1D world.

download

from pembroider.

LingDong- avatar LingDong- commented on May 27, 2024

Hi @golanlevin

I think I was able to solve the problem (quite perfectly :) with the cross hatch method I mentioned earlier. 6d8c792

Screen Shot 2020-06-09 at 10 58 35 PM

Utilizing some Ancient Greek technology I was able to figure out the correct relative angles and cross-spacing:

IMG_0845

from pembroider.

golanlevin avatar golanlevin commented on May 27, 2024

Ha! So much better than my ridiculous particle system.
@tatyanade, could you please test out Lingdong's new hatching (for PARALLEL mode)?

from pembroider.

golanlevin avatar golanlevin commented on May 27, 2024

Hi @LingDong-,
Next challenge: can you use the Ancient Greek Technology to plan stitch points for the cross-hatching method (with the goals of spacing the points as far apart as possible, and minimizing the occurrence of points that are too close together)? And how will this interact with the user being able to set variable stitch lengths?

IMG_8683

from pembroider.

tatyanade avatar tatyanade commented on May 27, 2024

2020-06-12_16h43_34
tests - this is really effective for hatch spacing of 2; with a spacing of 1 it still warps - I think it would be good to have an option for how offset each layer is - right now this offset each alternate by half the stitch length but for denser fills i think it would be appropriate to offset each line by thirds or even fourths.

from pembroider.

golanlevin avatar golanlevin commented on May 27, 2024

Hi @tatyanade , to be clear, do you mean something like the following?

On the left is a sparse hatch, and the threads are offset by 0%-50%-0%.
On the right is a dense hatch, and the threads are offset by 0%-33%-66%-0%

Screen Shot 2020-06-12 at 5 43 38 PM

@LingDong- , is this something you could try?

Also, @tatyanade , have you tried hatch spacing of 1.5? (Does that work?)

from pembroider.

LingDong- avatar LingDong- commented on May 27, 2024

@golanlevin Sure! this is so easy to try, I just need to change one number from 0.5 to 1/3 or 1/4 etc.

I'll accept the challenge of making it work for cross hatching ;) But out of curiosity, would simply applying the algorithm for parallel hatching twice for each direction work? and maybe afterwards we make some micro adjustments to have the points spread out. Or maybe would the stretching in two directions cancel out to become no stretching?

from pembroider.

LingDong- avatar LingDong- commented on May 27, 2024

Screen Shot 2020-06-12 at 9 24 25 PM

Added experimental option E.PARALLEL_RESAMPLING_FACTOR to control the offset: eb069c2

@golanlevin btw, just finished documenting PEmbroiderGraphics with javadoc style comments, all 147 functions. Never realized I wrote so much code until I need to document it ;)

from pembroider.

LingDong- avatar LingDong- commented on May 27, 2024

Screen Shot 2020-06-12 at 11 00 22 PM

@golanlevin I implemented the resampling algorithm for cross hatching in your illustration (again with Greek tech ;) c7c8631

However I don't know what to do about variable stitch length, so the solution I came up with is to round the stitch length to the nearest multiple.

So for user stitch lengths that are higher than the "perfect" spacing shown in your illustration, it will do every two steps, every three steps, every four steps, etc. (See the rightmost center circle in the screenshot) I think that's probably an acceptable compromise for the user?

from pembroider.

golanlevin avatar golanlevin commented on May 27, 2024

@tatyanade , could you kindly test out the new hatching options. In particular, I made a new hatching demo (#3) that shows the effects of changing the offset percentage and the noise amount:

PEmbroider_shape_hatching_3

from pembroider.

tatyanade avatar tatyanade commented on May 27, 2024

2020-06-13_17h45_23

Also ran the first row again with stitch length of 50, hatch spacing at 1.5, here is that:
image
2020-06-13_17h45_26

from pembroider.

golanlevin avatar golanlevin commented on May 27, 2024

This appears resolved :)

from pembroider.

Related Issues (20)

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.