The problem is that data is a pointer to a structure, and for those you need to use the "arrow" operator ->, like in data->x.

There is a worse problem though:

struct dotData *data;
*data = *((struct dotData*)(thisdot));

The pointer data doesn't point anywhere. Uninitialized local (non-static) variables will have an indeterminate value. To use a pointer you actually need to make it point somewhere.

Or, for a simple solution and the one I recommend, not use pointers at all:

struct dotData = *(struct dotData *) thisdot;

You also have another big problem, in how you pass data to the threads. All the threads will get the same pointer to the same structure. So the modifications you make in the thread-creation loop will be set for all the data in all the threads.

This can be solved by dynamically allocating the structure you pass to the threads. You can then just copy the pointer instead of copy the structure. And you must remember to free the data or you will have a memory leak.