Comments (19)
Hey @LingDong- , I tried this out with a particle repulsion system. It actually works OK, check it out in this animated GIF:
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.
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.
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.
@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:
from pembroider.
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.
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.
@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
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.
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.
I was inspired by the idea of Poisson-disc distribution sampling and was curious if it could be extended to a poly-1D world.
from pembroider.
Hi @golanlevin
I think I was able to solve the problem (quite perfectly :) with the cross hatch method I mentioned earlier. 6d8c792
Utilizing some Ancient Greek technology I was able to figure out the correct relative angles and cross-spacing:
from pembroider.
Ha! So much better than my ridiculous particle system.
@tatyanade, could you please test out Lingdong's new hatching (for PARALLEL mode)?
from pembroider.
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?
from pembroider.
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.
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%
@LingDong- , is this something you could try?
Also, @tatyanade , have you tried hatch spacing of 1.5? (Does that work?)
from pembroider.
@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.
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.
@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.
@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:
from pembroider.
Also ran the first row again with stitch length of 50, hatch spacing at 1.5, here is that:
from pembroider.
This appears resolved :)
from pembroider.
Related Issues (20)
- compile with Eclipse HOT 3
- non-closed shapes with E.strokeMode(E.PERPENDICULAR) have connecting line HOT 2
- under layer support stitch HOT 1
- Request toggle to enable/disable generation of connecting lines HOT 3
- .jef file format causes machine confusion HOT 1
- Jump stitches not being cut, but stitched HOT 9
- no menu preview (but editor preview!) of .pes files on the Brother NV800E
- SVG Export leave connecting lines between shapes HOT 1
- Concentric fill error on imported images
- Optimize function altering colors
- Potentially helpful sizing function
- In PEmbroider_lines_1.pde example, the bobbin thread gets tangled HOT 4
- Text partially cut off
- simple E.rect problem HOT 2
- Inaccurate license information HOT 4
- layer names as metadata HOT 1
- option to avoid small bridge stitches HOT 10
- culling question. HOT 3
- getting access to PEmbroiderGraphics polylines HOT 2
- satin hatching does not catch all polygons HOT 7
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pembroider.