Creating a wavy dot pattern in a Cycles shader [Solution at bottom of question]
I'm trying to create a shader to draw dots in a wavy pattern. I have the dots, and I have the waves, but I'm not sure how to combine the two.
I create the dots by adding together 2 wave textures that are 90° apart from each other, and use a Less Than node to draw each dot with a hard border. (Fun fact -- if you rotate the overall dot pattern by 90° you can switch between staggered and non-staggered dots.) This results in a grid of dots.
The &quot;wavy waves&quot; pattern is a combination of two wave textures. One base wave with another wave being added to the X-coordinate of the base wave to create the variation.
Every time I've tried to combine the dots with the waves doesn't work out... the waves always end up squishing or stretching the dots. I don't want that -- I want to keep the circular dots, and only adjust their placement to match the wave pattern.
Any advice? Intended end-result below.
.
Shader nodes to draw plain dots:

Resulting plain dots

Shader nodes to draw wavy waves:

Resulting wavy waves:

End goal:

================================================================
Solution
(thanks to @RobinBetts below)
Using Robin's clever method of UV tiling, I made a small change to achieve just what I wanted. (note - you need 2.81 to open Robin's .blend file)
I wanted to be able to adjust the spacing of the dots in the X and Y, which I think is the next step after Robin's answer. To do this, I changed the Fraction node into a Modulo node, which lets you adjust how quickly the UV space is repeated. Note that the modulo coeff in the X direction must always be a positive integer to keep the correct dot shape. The modulo coeff in the Y direction can be any positive number. And that's it. Adjusting the Scale, Freq, and Amplitude does all the rest.
This tree divides the UV space into XY cells, and samples the sine of X at every cell to stagger the position of the Y cells.



This results in a modified UV space which looks like this: (X->R, Y->G, 0 at the center of each cell)



This space can be used to tile any UV-dependent texture in a sine-wave pattern.

In this case, we use the output vector as the 'Vector' input of a procedural dot:



With this sort of result:



It's actually quite tricky to adjust the frequency and amplitude so the cells sample the sine wave at the right rate to maintain the 'wavy' look, but I don't think that can be constrained to make it easier.. unless we fixed it to make every other row black, or something, so the right dots are associated with the right dots, perceptually. We could tweak it to do that, or something like it, if you like.

EDIT: @natedogg has improved the answer, to make it easier to see the pattern. (See OP) The attached .blend includes the improvement.