]> Shamusworld >> Repos - architektonas/blobdiff - src/fileio.cpp
Added line-to-circle intersection code.
[architektonas] / src / fileio.cpp
index fedddea4fea6729a917fe15510420aa829bef802..e0028cd90228c9d96a6ecd0fddea57f11382183f 100644 (file)
 // JLH = James Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  ------------------------------------------------------------
 // JLH  02/20/2013  Created this file
 //
 
 #include "fileio.h"
 
 //#include <stdio.h>
+#include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 #include <vector>
-#include "arc.h"
-#include "circle.h"
-#include "container.h"
-#include "dimension.h"
-#include "line.h"
+#include "structs.h"
 
-enum ObjectType { OTContainer, OTContainerEnd, OTLine, OTCircle, OTArc, OTDimension,
-       OTPolygon, OTText, OTImage, OTBlock, OTEndOfFile };
+/*
+How to handle connected objects
+-------------------------------
+
+Every Object has a vector<Object *> 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)
@@ -37,7 +121,7 @@ enum ObjectType { OTContainer, OTContainerEnd, OTLine, OTCircle, OTArc, OTDimens
           enumerates all objects within itself. */
 
        fprintf(file, "ARCHITEKTONAS DRAWING V1.0\n");
-#if 1
+#if 0
        object->Enumerate(file);
        fprintf(file, "END\n");
        return true;
@@ -61,7 +145,7 @@ enum ObjectType { OTContainer, OTContainerEnd, OTLine, OTCircle, OTArc, OTDimens
           add objects to it until an "endContainer" marker is found. This will require a
           stack to maintain the current Container. */
 
-#if 1
+#if 0
        std::vector<Container *> containerStack;
        Container * currentTopContainer = drawing;//new Container(Vector(0, 0));
        Object * object;
@@ -78,17 +162,17 @@ enum ObjectType { OTContainer, OTContainerEnd, OTLine, OTCircle, OTArc, OTDimens
                // where the return value tells if it's a valid object, Object * returns the
                // reconstructed object and ObjectType * returns the object type.
 
-               if (objectType == OTEndOfFile)
+               if (objectType == OTFEndOfFile)
                {
-printf("Load: container size = %li\n", drawing->objects.size());
+//printf("Load: container size = %li\n", drawing->objects.size());
                        return true;
                }
-               else if (objectType == OTContainer)
+               else if (objectType == OTFContainer)
                {
                        containerStack.push_back(currentTopContainer);
                        currentTopContainer = new Container(Vector(0, 0), currentTopContainer);
                }
-               else if (objectType == OTContainerEnd)
+               else if (objectType == OTFContainerEnd)
                {
                        Container * containerToAdd = currentTopContainer;
                        currentTopContainer = containerStack.back();
@@ -98,7 +182,7 @@ printf("Load: container size = %li\n", drawing->objects.size());
                else
                {
                        currentTopContainer->Add(object);
-printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.size(), currentTopContainer->objects.size());
+//printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.size(), currentTopContainer->objects.size());
                }
        }
 
@@ -111,10 +195,40 @@ printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.siz
 
 /*static*/ bool FileIO::GetObjectFromFile(FILE * file, Object * parent, Object ** object, int * objectType)
 {
+#if 0
        char buffer[256];
-       fscanf(file, "%s ", buffer);
+       int foundLayer = 0;
+       int num = fscanf(file, "%s", buffer);
        bool recognized = false;
-//printf("Load: buffer = \"%s\"\n", buffer);
+       *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)
        {
@@ -124,7 +238,7 @@ printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.siz
                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 = OTLine;
+               *objectType = OTFLine;
        }
        else if (strcmp(buffer, "CIRCLE") == 0)
        {
@@ -133,7 +247,7 @@ printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.siz
                double r;
                fscanf(file, "(%lf,%lf) %lf", &v.x, &v.y, &r);
                *object = new Circle(v, r, parent);
-               *objectType = OTCircle;
+               *objectType = OTFCircle;
        }
        else if (strcmp(buffer, "ARC") == 0)
        {
@@ -142,7 +256,7 @@ printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.siz
                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 = OTArc;
+               *objectType = OTFArc;
        }
        else if (strcmp(buffer, "DIMENSION") == 0)
        {
@@ -151,24 +265,30 @@ printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.siz
                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 = OTDimension;
+               *objectType = OTFDimension;
        }
        else if (strcmp(buffer, "CONTAINER") == 0)
        {
                recognized = true;
-               *objectType = OTContainer;
+               *objectType = OTFContainer;
        }
        else if (strcmp(buffer, "ENDCONTAINER") == 0)
        {
                recognized = true;
-               *objectType = OTContainerEnd;
+               *objectType = OTFContainerEnd;
        }
        else if (strcmp(buffer, "END") == 0)
        {
                recognized = true;
-               *objectType = OTEndOfFile;
+               *objectType = OTFEndOfFile;
        }
 
+       if (*object)
+               (*object)->layer = foundLayer;
+
        return recognized;
+#else
+       return false;
+#endif
 }