X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ffileio.cpp;h=503ccc109322dcd41f68b6cc629ad38abc663484;hb=ea7712f342020baf61cf33ba98b12140da6aecf7;hp=7cd6816d4766f63690d14d7ce0dbca13c7bc31b3;hpb=baf67656b97e3d61e9223e66ebe4f554e364cd4a;p=architektonas diff --git a/src/fileio.cpp b/src/fileio.cpp index 7cd6816..503ccc1 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -15,25 +15,280 @@ #include "fileio.h" //#include +#include #include -#include "container.h" +#include +#include +#include "structs.h" + +/* +How to handle connected objects +------------------------------- + +Every Object has a vector which enumerates all Objects connected to +the one we're looking at. So it looks like we'll have to take a two pass +approach to loading and saving. + +Basically, in the saving case, first we write out all objects, keeping a +pointer-to-index-number record. Second, we loop through all the objects we +wrote out, writing connection lists. Format (indices are 1-based): + +CONNECTIONS +1: 12 3 +3: 1 +12: 1 +ENDCONNECTIONS + +In the reading case, we do pretty much the same: we construct pointer-to-index- +number list, then read the connection list. The PTIN connects the index to the +Object pointers we've created. Then we simply call the Object's Connect() +function to connect the objects. + +Small problem though: How does a Dimension know which points on a Line it's +connected to? This approach tells the Dimension it's connected to the Line and +the Line that it's connected to the Dimension, but not which points. + +How to handle them then? Do we list the point with the Object pointed at? A +Line can contain an infinite number of points to connect with besides its +endpoints. + +So with each connection Object in the vector, there would also have to be a +corresponding point to go with it, that would be gotten from the other Object's +Connect() function. Or, instead of a point, a parameter value? + +Doing that, with the Line and a parameter "t", if t == 0 we have endpoint 1. +if t == 1, then we have endpoint 2. With a Circle, the parameter is a number +between 0 and 1 (scaled to 0 to 2π). With an Arc, the parameter goes from 0 to +1, 0 being enpoint 1 and 1 being endpoint 2. + +How does this work for moving objects that are connected? Again, with the Line +and Dimension. The Line's connections looks like this: + +Object *: dim1, t = 0 +Object *: dim1, t = 1 + +Dimension looks like this: + +Object *: line1, t = 0 +Object *: line1, t = 1 + +For Dimensions, it can query the connected object (if any) using something like +GetPointForParameter(). That way it can figure out where its endpoints are. If +there is no connected point, then it uses its internal point. + + +Dimensions are special cases of lines: They have exactly *two* points and none +in between. Therefore, the Dimension object only needs to have two points. But +those points can be connected to multiple objects. The can also be connected to +no points/Objects too. + +How to describe them and their connections (or lack thereof)? + +Would have to be a 2nd pass, after all objects have been written out in order. +Then you could do something like: + +DIMCONNECTIONS +8 (the Dimension #): 1 (the Object # for point 1) 1 (the Object # for point 2) +ENDDIMCONNECTIONS + + + +Connection attributes: E.g., between a Line a Circle, it can be tangent, +perpendicular, or an arbitrary angle. How to encode that information? It's not +intrinsic to either the Line or the Circle, but is a function of the +relationship between them by virtue of their connection. + + +OTHER CONSIDERATIONS: +--------------------- + + - Need to figure out how to store the Layer list (should layer list be optional?) + - Need to figure out how to store the Block list and blocks + + +*/ + +enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFLine, OTFCircle, OTFArc, + OTFDimension, OTFPolygon, OTFText, OTFImage, OTFBlock, OTFEndOfFile }; /*static*/ bool FileIO::SaveAtnsFile(FILE * file, Container * object) { -// QString filename2 = QFileDialog::getSaveFileName(NULL, tr("Save Drawing"), -// "", tr("Architektonas files (*.drawing)")); + /* Approach: loop through the container, doing a depth-first traversal. Any extra + containers found are looped through until there aren't any more down, then + ordinary objects are described. This can be handled by a virtual Object function + that reports the object by itself if it's a non-Container, otherwise it + enumerates all objects within itself. */ + fprintf(file, "ARCHITEKTONAS DRAWING V1.0\n"); +#if 0 + object->Enumerate(file); + fprintf(file, "END\n"); + return true; +#else return false; +#endif } -/*static*/ bool FileIO::LoadAtnsFile(FILE * file, Container * object) +/*static*/ bool FileIO::LoadAtnsFile(FILE * file, Container * drawing) { -// QString filename2 = QFileDialog::getOpenFileName(NULL, tr("Open Drawing"), -// "", tr("Architektonas files (*.drawing)")); +// char buffer[256]; + float version; + + fscanf(file, "ARCHITEKTONAS DRAWING V%f", &version); + +//printf("Load: version = %f\n", version); + if (version != 1.0) + return false; + /* Approach: read each object in the file, one by one. If the object is a Container, + add objects to it until an "endContainer" marker is found. This will require a + stack to maintain the current Container. */ +#if 0 + std::vector containerStack; + Container * currentTopContainer = drawing;//new Container(Vector(0, 0)); + Object * object; +// ObjectType objectType; + int objectType; + + while (!feof(file)) + { + if (FileIO::GetObjectFromFile(file, currentTopContainer, &object, &objectType) == false) + return false; + + // object->type down below can be replaced with objType. + // Above could be: bool FileIO::GetObjectFromFile(FILE *, Object *, ObjectType *); + // where the return value tells if it's a valid object, Object * returns the + // reconstructed object and ObjectType * returns the object type. + + if (objectType == OTFEndOfFile) + { +//printf("Load: container size = %li\n", drawing->objects.size()); + return true; + } + else if (objectType == OTFContainer) + { + containerStack.push_back(currentTopContainer); + currentTopContainer = new Container(Vector(0, 0), currentTopContainer); + } + else if (objectType == OTFContainerEnd) + { + Container * containerToAdd = currentTopContainer; + currentTopContainer = containerStack.back(); + containerStack.pop_back(); + currentTopContainer->Add(containerToAdd); + } + else + { + currentTopContainer->Add(object); +//printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.size(), currentTopContainer->objects.size()); + } + } + + return false; +#else return false; +#endif } +/*static*/ bool FileIO::GetObjectFromFile(FILE * file, Object * parent, Object ** object, int * objectType) +{ +#if 0 + char buffer[256]; + int foundLayer = 0; + int num = fscanf(file, "%s", buffer); + bool recognized = false; + *object = NULL; +//printf("FileIO: fscanf returned %i, buffer = \"%s\"\n", num, buffer); + +// The following fugliness is for troubleshooting. Can remove later. + if ((strcmp(buffer, "END") != 0) && (strcmp(buffer, "ENDCONTAINER") != 0)) +{ +errno = 0; + num = fscanf(file, " %i ", &foundLayer); +//printf("FileIO: fscanf returned %i, foundLayer = %i\n", num, foundLayer); +if (errno) +{ + if (errno == EAGAIN) + printf("EAGAIN\n"); + else if (errno == EBADF) + printf("EBADF\n"); + else if (errno == EILSEQ) + printf("EILSEQ\n"); + else if (errno == EINTR) + printf("EINTR\n"); + else if (errno == EINVAL) + printf("EINVAL\n"); + else if (errno == ENOMEM) + printf("ENOMEM\n"); + else if (errno == ERANGE) + printf("ERANGE\n"); + else + printf("errno = %i\n", errno); +} +} + + if (strcmp(buffer, "LINE") == 0) + { +//printf(" Found LINE.\n"); + recognized = true; + Vector v1, v2; + fscanf(file, "(%lf,%lf) (%lf,%lf)", &v1.x, &v1.y, &v2.x, &v2.y); +//printf(" Number of params recognized: %i\n", n); + *object = new Line(v1, v2, parent); + *objectType = OTFLine; + } + else if (strcmp(buffer, "CIRCLE") == 0) + { + recognized = true; + Vector v; + double r; + fscanf(file, "(%lf,%lf) %lf", &v.x, &v.y, &r); + *object = new Circle(v, r, parent); + *objectType = OTFCircle; + } + else if (strcmp(buffer, "ARC") == 0) + { + recognized = true; + Vector v; + double r, a1, a2; + fscanf(file, "(%lf,%lf) %lf, %lf, %lf", &v.x, &v.y, &r, &a1, &a2); + *object = new Arc(v, r, a1, a2, parent); + *objectType = OTFArc; + } + else if (strcmp(buffer, "DIMENSION") == 0) + { + recognized = true; + Vector v1, v2; + DimensionType type; + fscanf(file, "(%lf,%lf) (%lf,%lf) %i", &v1.x, &v1.y, &v2.x, &v2.y, &type); + *object = new Dimension(v1, v2, type, parent); + *objectType = OTFDimension; + } + else if (strcmp(buffer, "CONTAINER") == 0) + { + recognized = true; + *objectType = OTFContainer; + } + else if (strcmp(buffer, "ENDCONTAINER") == 0) + { + recognized = true; + *objectType = OTFContainerEnd; + } + else if (strcmp(buffer, "END") == 0) + { + recognized = true; + *objectType = OTFEndOfFile; + } + + if (*object) + (*object)->layer = foundLayer; + + return recognized; +#else + return false; +#endif +} +