2008-03-25 10:02:13 +00:00
|
|
|
|
|
|
|
#ifndef __SOLVESPACE_H
|
|
|
|
#define __SOLVESPACE_H
|
|
|
|
|
2008-03-28 10:00:37 +00:00
|
|
|
// Debugging functions
|
|
|
|
#define oops() do { dbp("oops at line %d, file %s", __LINE__, __FILE__); \
|
2008-05-17 23:21:02 +00:00
|
|
|
if(1) *(char *)0 = 1; exit(-1); } while(0)
|
2008-03-28 10:00:37 +00:00
|
|
|
#ifndef min
|
|
|
|
#define min(x, y) ((x) < (y) ? (x) : (y))
|
|
|
|
#endif
|
|
|
|
#ifndef max
|
|
|
|
#define max(x, y) ((x) > (y) ? (x) : (y))
|
|
|
|
#endif
|
|
|
|
|
2008-06-03 18:28:41 +00:00
|
|
|
#define isnan(x) (((x) != (x)) || (x > 1e11) || (x < -1e11))
|
|
|
|
|
2008-05-26 03:39:45 +00:00
|
|
|
inline int WRAP(int v, int n) {
|
|
|
|
while(v >= n) v -= n;
|
|
|
|
while(v < 0) v += n;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2008-05-11 10:40:37 +00:00
|
|
|
#define SWAP(T, a, b) do { T temp = (a); (a) = (b); (b) = temp; } while(0)
|
2008-05-19 09:23:49 +00:00
|
|
|
#define ZERO(v) memset((v), 0, sizeof(*(v)))
|
2008-05-22 10:28:28 +00:00
|
|
|
#define CO(v) (v).x, (v).y, (v).z
|
|
|
|
|
2008-05-26 03:39:45 +00:00
|
|
|
#define LENGTH_EPS (0.0000001)
|
2008-05-11 10:40:37 +00:00
|
|
|
|
2008-04-17 06:42:32 +00:00
|
|
|
#define isforname(c) (isalnum(c) || (c) == '_' || (c) == '-' || (c) == '#')
|
|
|
|
|
2008-04-18 11:11:48 +00:00
|
|
|
typedef signed long SDWORD;
|
|
|
|
|
2008-03-25 10:02:13 +00:00
|
|
|
#include <stdlib.h>
|
2008-04-17 06:42:32 +00:00
|
|
|
#include <ctype.h>
|
2008-03-25 10:02:13 +00:00
|
|
|
#include <string.h>
|
2008-03-26 09:18:12 +00:00
|
|
|
#include <stdio.h>
|
2008-03-27 09:53:51 +00:00
|
|
|
#include <math.h>
|
2008-04-01 10:48:44 +00:00
|
|
|
#include <windows.h> // required for GL stuff
|
|
|
|
#include <gl/gl.h>
|
|
|
|
#include <gl/glu.h>
|
|
|
|
|
2008-04-14 10:28:32 +00:00
|
|
|
class Expr;
|
2008-04-22 13:14:15 +00:00
|
|
|
class ExprVector;
|
2008-05-05 06:18:01 +00:00
|
|
|
class ExprQuaternion;
|
2008-04-14 10:28:32 +00:00
|
|
|
|
2008-05-29 10:10:12 +00:00
|
|
|
|
2008-04-14 10:28:32 +00:00
|
|
|
// From the platform-specific code.
|
2008-05-28 10:10:31 +00:00
|
|
|
#define MAX_RECENT 8
|
|
|
|
#define RECENT_OPEN (0xf000)
|
|
|
|
#define RECENT_IMPORT (0xf100)
|
|
|
|
extern char RecentFile[MAX_RECENT][MAX_PATH];
|
|
|
|
void RefreshRecentMenus(void);
|
|
|
|
|
2008-04-18 11:11:48 +00:00
|
|
|
int SaveFileYesNoCancel(void);
|
2008-05-29 10:10:12 +00:00
|
|
|
#define SLVS_PATTERN "SolveSpace Models (*.slvs)\0*.slvs\0All Files (*)\0*\0\0"
|
|
|
|
#define SLVS_EXT "slvs"
|
2008-06-18 08:35:14 +00:00
|
|
|
#define PNG_PATTERN "PNG (*.png)\0*.png\0All Files (*)\0*\0\0"
|
|
|
|
#define PNG_EXT "png"
|
2008-04-18 11:11:48 +00:00
|
|
|
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern);
|
|
|
|
BOOL GetOpenFile(char *file, char *defExtension, char *selPattern);
|
|
|
|
|
2008-04-14 10:28:32 +00:00
|
|
|
void CheckMenuById(int id, BOOL checked);
|
2008-04-18 07:06:37 +00:00
|
|
|
void EnableMenuById(int id, BOOL checked);
|
2008-04-18 11:11:48 +00:00
|
|
|
|
2008-04-21 10:12:04 +00:00
|
|
|
void ShowGraphicsEditControl(int x, int y, char *s);
|
|
|
|
void HideGraphicsEditControl(void);
|
|
|
|
BOOL GraphicsEditControlIsVisible(void);
|
2008-05-27 06:36:59 +00:00
|
|
|
void ShowTextEditControl(int hr, int c, char *s);
|
|
|
|
void HideTextEditControl(void);
|
|
|
|
BOOL TextEditControlIsVisible(void);
|
2008-04-21 10:12:04 +00:00
|
|
|
|
2008-04-27 05:00:12 +00:00
|
|
|
void ShowTextWindow(BOOL visible);
|
2008-04-14 10:28:32 +00:00
|
|
|
void InvalidateText(void);
|
2008-04-27 05:00:12 +00:00
|
|
|
void InvalidateGraphics(void);
|
2008-04-18 11:11:48 +00:00
|
|
|
void PaintGraphics(void);
|
2008-06-12 07:31:41 +00:00
|
|
|
void GetGraphicsWindowSize(int *w, int *h);
|
2008-04-27 05:00:12 +00:00
|
|
|
SDWORD GetMilliseconds(void);
|
2008-04-18 11:11:48 +00:00
|
|
|
|
2008-04-14 10:28:32 +00:00
|
|
|
void dbp(char *str, ...);
|
2008-05-30 07:32:30 +00:00
|
|
|
#define DBPTRI(tri) \
|
|
|
|
dbp("tri: (%.3f %.3f %.3f) (%.3f %.3f %.3f) (%.3f %.3f %.3f)", \
|
|
|
|
CO((tri).a), CO((tri).b), CO((tri).c))
|
|
|
|
|
2008-04-14 10:28:32 +00:00
|
|
|
void Error(char *str, ...);
|
2008-06-03 18:48:47 +00:00
|
|
|
void ExitNow(void);
|
2008-06-11 04:22:52 +00:00
|
|
|
void CnfFreezeString(char *str, char *name);
|
|
|
|
void CnfFreezeDWORD(DWORD v, char *name);
|
|
|
|
void CnfThawString(char *str, int maxLen, char *name);
|
|
|
|
DWORD CnfThawDWORD(DWORD v, char *name);
|
2008-04-18 11:11:48 +00:00
|
|
|
|
2008-04-25 10:11:29 +00:00
|
|
|
void *AllocTemporary(int n);
|
|
|
|
void FreeAllTemporary(void);
|
2008-04-18 07:06:37 +00:00
|
|
|
void *MemRealloc(void *p, int n);
|
|
|
|
void *MemAlloc(int n);
|
|
|
|
void MemFree(void *p);
|
2008-05-07 04:17:29 +00:00
|
|
|
void vl(void); // debug function to validate
|
2008-04-14 10:28:32 +00:00
|
|
|
|
|
|
|
|
2008-03-25 10:02:13 +00:00
|
|
|
#include "dsc.h"
|
2008-04-23 07:29:19 +00:00
|
|
|
#include "polygon.h"
|
2008-05-29 10:10:12 +00:00
|
|
|
|
|
|
|
class Entity;
|
|
|
|
class hEntity;
|
|
|
|
typedef IdList<Entity,hEntity> EntityList;
|
|
|
|
|
2008-03-26 09:18:12 +00:00
|
|
|
#include "sketch.h"
|
2008-04-12 14:12:26 +00:00
|
|
|
#include "ui.h"
|
2008-04-08 12:54:53 +00:00
|
|
|
#include "expr.h"
|
2008-03-25 10:02:13 +00:00
|
|
|
|
2008-03-27 09:53:51 +00:00
|
|
|
|
2008-04-11 11:13:47 +00:00
|
|
|
// Utility functions that are provided in the platform-independent code.
|
|
|
|
void glxVertex3v(Vector u);
|
2008-05-22 10:28:28 +00:00
|
|
|
#define GLX_CALLBACK __stdcall
|
|
|
|
typedef void GLX_CALLBACK glxCallbackFptr(void);
|
|
|
|
void glxTesselatePolygon(GLUtesselator *gt, SPolygon *p);
|
2008-04-25 07:04:09 +00:00
|
|
|
void glxFillPolygon(SPolygon *p);
|
2008-06-02 03:31:37 +00:00
|
|
|
void glxFillMesh(int color, SMesh *m, DWORD h, DWORD s1, DWORD s2);
|
2008-05-19 09:23:49 +00:00
|
|
|
void glxDebugPolygon(SPolygon *p);
|
|
|
|
void glxDebugEdgeList(SEdgeList *l);
|
2008-05-22 10:28:28 +00:00
|
|
|
void glxDebugMesh(SMesh *m);
|
2008-05-05 09:47:23 +00:00
|
|
|
void glxMarkPolygonNormal(SPolygon *p);
|
2008-04-11 11:13:47 +00:00
|
|
|
void glxWriteText(char *str);
|
2008-04-30 08:14:32 +00:00
|
|
|
void glxWriteTextRefCenter(char *str);
|
2008-05-07 08:19:37 +00:00
|
|
|
double glxStrWidth(char *str);
|
|
|
|
double glxStrHeight(void);
|
2008-04-11 11:13:47 +00:00
|
|
|
void glxTranslatev(Vector u);
|
2008-04-27 03:26:27 +00:00
|
|
|
void glxOntoWorkplane(Vector u, Vector v);
|
2008-04-19 11:09:47 +00:00
|
|
|
void glxLockColorTo(double r, double g, double b);
|
|
|
|
void glxUnlockColor(void);
|
2008-04-25 07:04:09 +00:00
|
|
|
void glxColor3d(double r, double g, double b);
|
|
|
|
void glxColor4d(double r, double g, double b, double a);
|
2008-06-17 19:12:25 +00:00
|
|
|
void glxDepthRangeOffset(int units);
|
|
|
|
void glxDepthRangeLockToFront(bool yes);
|
2008-03-27 09:53:51 +00:00
|
|
|
|
2008-03-25 10:02:13 +00:00
|
|
|
|
2008-03-26 09:18:12 +00:00
|
|
|
#define arraylen(x) (sizeof((x))/sizeof((x)[0]))
|
2008-03-27 09:53:51 +00:00
|
|
|
#define PI (3.1415926535897931)
|
|
|
|
void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
|
|
|
|
double a21, double a22, double a23, double a24,
|
|
|
|
double a31, double a32, double a33, double a34,
|
|
|
|
double a41, double a42, double a43, double a44);
|
|
|
|
|
2008-04-20 11:35:10 +00:00
|
|
|
class System {
|
|
|
|
public:
|
|
|
|
#define MAX_UNKNOWNS 200
|
|
|
|
|
|
|
|
IdList<Entity,hEntity> entity;
|
|
|
|
IdList<Param,hParam> param;
|
|
|
|
IdList<Equation,hEquation> eq;
|
|
|
|
|
|
|
|
// In general, the tag indicates the subsys that a variable/equation
|
2008-05-07 07:10:20 +00:00
|
|
|
// has been assigned to; these are exceptions for variables:
|
2008-06-04 10:22:30 +00:00
|
|
|
static const int VAR_SUBSTITUTED = 10000;
|
2008-05-07 07:10:20 +00:00
|
|
|
// and for equations:
|
|
|
|
static const int EQ_SUBSTITUTED = 20000;
|
2008-04-20 11:35:10 +00:00
|
|
|
|
2008-04-21 01:26:36 +00:00
|
|
|
// The system Jacobian matrix
|
2008-04-20 11:35:10 +00:00
|
|
|
struct {
|
2008-04-21 01:26:36 +00:00
|
|
|
// The corresponding equation for each row
|
|
|
|
hEquation eq[MAX_UNKNOWNS];
|
2008-04-20 11:35:10 +00:00
|
|
|
|
2008-04-21 01:26:36 +00:00
|
|
|
// The corresponding parameter for each column
|
|
|
|
hParam param[MAX_UNKNOWNS];
|
2008-05-01 06:25:38 +00:00
|
|
|
|
2008-04-21 01:26:36 +00:00
|
|
|
bool bound[MAX_UNKNOWNS];
|
2008-04-20 11:35:10 +00:00
|
|
|
|
2008-04-21 01:26:36 +00:00
|
|
|
// We're solving AX = B
|
2008-04-20 11:35:10 +00:00
|
|
|
int m, n;
|
2008-04-21 01:26:36 +00:00
|
|
|
struct {
|
|
|
|
Expr *sym[MAX_UNKNOWNS][MAX_UNKNOWNS];
|
|
|
|
double num[MAX_UNKNOWNS][MAX_UNKNOWNS];
|
|
|
|
} A;
|
2008-05-01 06:25:38 +00:00
|
|
|
|
2008-05-13 02:35:31 +00:00
|
|
|
double scale[MAX_UNKNOWNS];
|
|
|
|
|
2008-05-12 07:29:50 +00:00
|
|
|
// Some helpers for the least squares solve
|
|
|
|
double AAt[MAX_UNKNOWNS][MAX_UNKNOWNS];
|
|
|
|
double Z[MAX_UNKNOWNS];
|
|
|
|
|
2008-04-21 01:26:36 +00:00
|
|
|
double X[MAX_UNKNOWNS];
|
2008-05-01 06:25:38 +00:00
|
|
|
|
2008-04-21 01:26:36 +00:00
|
|
|
struct {
|
|
|
|
Expr *sym[MAX_UNKNOWNS];
|
|
|
|
double num[MAX_UNKNOWNS];
|
|
|
|
} B;
|
|
|
|
} mat;
|
2008-04-20 11:35:10 +00:00
|
|
|
|
|
|
|
bool Tol(double v);
|
2008-05-12 07:29:50 +00:00
|
|
|
int GaussJordan(void);
|
|
|
|
static bool SolveLinearSystem(double X[], double A[][MAX_UNKNOWNS],
|
|
|
|
double B[], int N);
|
|
|
|
bool SolveLeastSquares(void);
|
2008-04-20 11:35:10 +00:00
|
|
|
|
|
|
|
void WriteJacobian(int eqTag, int paramTag);
|
|
|
|
void EvalJacobian(void);
|
|
|
|
|
2008-05-26 09:56:50 +00:00
|
|
|
void WriteEquationsExceptFor(hConstraint hc, hGroup hg);
|
|
|
|
void FindWhichToRemoveToFixJacobian(Group *g);
|
2008-05-07 07:10:20 +00:00
|
|
|
void SolveBySubstitution(void);
|
|
|
|
|
|
|
|
static bool IsDragged(hParam p);
|
2008-05-01 06:25:38 +00:00
|
|
|
|
2008-04-20 11:35:10 +00:00
|
|
|
bool NewtonSolve(int tag);
|
2008-05-26 09:56:50 +00:00
|
|
|
void Solve(Group *g);
|
2008-04-20 11:35:10 +00:00
|
|
|
};
|
|
|
|
|
2008-03-26 09:18:12 +00:00
|
|
|
|
2008-03-28 10:00:37 +00:00
|
|
|
class SolveSpace {
|
|
|
|
public:
|
2008-03-26 09:18:12 +00:00
|
|
|
TextWindow TW;
|
|
|
|
GraphicsWindow GW;
|
|
|
|
|
2008-04-14 10:28:32 +00:00
|
|
|
// These lists define the sketch, and are edited by the user.
|
|
|
|
IdList<Group,hGroup> group;
|
|
|
|
IdList<Request,hRequest> request;
|
|
|
|
IdList<Constraint,hConstraint> constraint;
|
|
|
|
|
|
|
|
// These lists are generated automatically when we solve the sketch.
|
|
|
|
IdList<Entity,hEntity> entity;
|
|
|
|
IdList<Param,hParam> param;
|
|
|
|
|
|
|
|
inline Constraint *GetConstraint(hConstraint h)
|
|
|
|
{ return constraint.FindById(h); }
|
|
|
|
inline Request *GetRequest(hRequest h) { return request.FindById(h); }
|
|
|
|
inline Entity *GetEntity (hEntity h) { return entity. FindById(h); }
|
|
|
|
inline Param *GetParam (hParam h) { return param. FindById(h); }
|
2008-04-20 11:35:10 +00:00
|
|
|
inline Group *GetGroup (hGroup h) { return group. FindById(h); }
|
2008-04-13 14:28:35 +00:00
|
|
|
|
2008-06-04 10:22:30 +00:00
|
|
|
// The state for undo/redo
|
|
|
|
typedef struct {
|
|
|
|
IdList<Group,hGroup> group;
|
|
|
|
IdList<Request,hRequest> request;
|
|
|
|
IdList<Constraint,hConstraint> constraint;
|
|
|
|
IdList<Param,hParam> param;
|
|
|
|
hGroup activeGroup;
|
|
|
|
} UndoState;
|
|
|
|
static const int MAX_UNDO = 16;
|
|
|
|
typedef struct {
|
|
|
|
UndoState d[MAX_UNDO];
|
|
|
|
int cnt;
|
|
|
|
int write;
|
|
|
|
} UndoStack;
|
|
|
|
UndoStack undo;
|
|
|
|
UndoStack redo;
|
|
|
|
void UndoEnableMenus(void);
|
|
|
|
void UndoRemember(void);
|
|
|
|
void UndoUndo(void);
|
|
|
|
void UndoRedo(void);
|
|
|
|
void PushFromCurrentOnto(UndoStack *uk);
|
|
|
|
void PopOntoCurrentFrom(UndoStack *uk);
|
|
|
|
void UndoClearState(UndoState *ut);
|
|
|
|
void UndoClearStack(UndoStack *uk);
|
|
|
|
|
2008-06-11 04:22:52 +00:00
|
|
|
// Little bits of extra configuration state
|
|
|
|
static const int MODEL_COLORS = 8;
|
|
|
|
int modelColor[MODEL_COLORS];
|
2008-06-11 04:30:18 +00:00
|
|
|
Vector lightDir[2];
|
2008-06-11 04:22:52 +00:00
|
|
|
double lightIntensity[2];
|
|
|
|
double meshTol;
|
2008-06-17 19:12:25 +00:00
|
|
|
double cameraTangent;
|
2008-06-14 09:51:25 +00:00
|
|
|
int CircleSides(double r);
|
|
|
|
typedef enum {
|
|
|
|
UNIT_MM = 0,
|
|
|
|
UNIT_INCHES,
|
|
|
|
} Unit;
|
|
|
|
Unit viewUnits;
|
|
|
|
char *MmToString(double v);
|
|
|
|
double ExprToMm(Expr *e);
|
|
|
|
|
|
|
|
// The platform-dependent code calls this before entering the msg loop
|
2008-06-11 04:22:52 +00:00
|
|
|
void Init(char *cmdLine);
|
|
|
|
void Exit(void);
|
|
|
|
|
2008-06-04 10:22:30 +00:00
|
|
|
// File load/save routines, including the additional files that get
|
|
|
|
// loaded when we have import groups.
|
2008-04-18 11:11:48 +00:00
|
|
|
FILE *fh;
|
2008-05-28 10:10:31 +00:00
|
|
|
void AfterNewFile(void);
|
|
|
|
static void RemoveFromRecentList(char *file);
|
|
|
|
static void AddToRecentList(char *file);
|
2008-04-24 06:22:16 +00:00
|
|
|
char saveFile[MAX_PATH];
|
|
|
|
bool unsaved;
|
|
|
|
typedef struct {
|
|
|
|
char type;
|
|
|
|
char *desc;
|
|
|
|
char fmt;
|
|
|
|
void *ptr;
|
|
|
|
} SaveTable;
|
|
|
|
static const SaveTable SAVED[];
|
|
|
|
void SaveUsingTable(int type);
|
2008-04-27 10:01:23 +00:00
|
|
|
void LoadUsingTable(char *key, char *val);
|
2008-04-24 06:22:16 +00:00
|
|
|
struct {
|
|
|
|
Group g;
|
|
|
|
Request r;
|
|
|
|
Entity e;
|
|
|
|
Param p;
|
|
|
|
Constraint c;
|
|
|
|
} sv;
|
2008-04-18 11:11:48 +00:00
|
|
|
static void MenuFile(int id);
|
2008-06-03 18:28:41 +00:00
|
|
|
bool GetFilenameAndSave(bool saveAs);
|
|
|
|
bool OkayToStartNewFile(void);
|
2008-06-02 11:43:27 +00:00
|
|
|
hGroup CreateDefaultDrawingGroup(void);
|
2008-04-24 06:22:16 +00:00
|
|
|
void NewFile(void);
|
2008-04-18 11:11:48 +00:00
|
|
|
bool SaveToFile(char *filename);
|
|
|
|
bool LoadFromFile(char *filename);
|
2008-05-29 10:10:12 +00:00
|
|
|
bool LoadEntitiesFromFile(char *filename, EntityList *le, SMesh *m);
|
|
|
|
void ReloadAllImported(void);
|
2008-06-18 08:35:14 +00:00
|
|
|
// And the PNG export too
|
|
|
|
void ExportAsPngTo(char *file);
|
2008-04-20 11:35:10 +00:00
|
|
|
|
2008-06-02 09:31:26 +00:00
|
|
|
void MarkGroupDirty(hGroup hg);
|
2008-06-02 11:43:27 +00:00
|
|
|
void MarkGroupDirtyByEntity(hEntity he);
|
2008-06-02 09:31:26 +00:00
|
|
|
|
2008-06-04 10:22:30 +00:00
|
|
|
// Consistency checking on the sketch: stuff with missing dependencies
|
|
|
|
// will get deleted automatically.
|
2008-05-17 06:04:55 +00:00
|
|
|
struct {
|
|
|
|
int requests;
|
|
|
|
int groups;
|
|
|
|
int constraints;
|
|
|
|
} deleted;
|
|
|
|
bool GroupExists(hGroup hg);
|
|
|
|
bool PruneOrphans(void);
|
|
|
|
bool EntityExists(hEntity he);
|
|
|
|
bool GroupsInOrder(hGroup before, hGroup after);
|
|
|
|
bool PruneGroups(hGroup hg);
|
|
|
|
bool PruneRequests(hGroup hg);
|
|
|
|
bool PruneConstraints(hGroup hg);
|
2008-04-27 09:03:01 +00:00
|
|
|
|
2008-06-02 09:31:26 +00:00
|
|
|
void GenerateAll(void);
|
|
|
|
void GenerateAll(int first, int last);
|
2008-05-26 09:56:50 +00:00
|
|
|
void SolveGroup(hGroup hg);
|
2008-04-27 09:03:01 +00:00
|
|
|
void ForceReferences(void);
|
|
|
|
|
2008-04-20 11:35:10 +00:00
|
|
|
// The system to be solved.
|
|
|
|
System sys;
|
2008-06-03 18:28:41 +00:00
|
|
|
|
|
|
|
struct {
|
|
|
|
bool showTW;
|
|
|
|
bool generateAll;
|
|
|
|
} later;
|
|
|
|
void DoLater(void);
|
2008-03-28 10:00:37 +00:00
|
|
|
};
|
2008-03-25 10:02:13 +00:00
|
|
|
|
|
|
|
extern SolveSpace SS;
|
|
|
|
|
|
|
|
#endif
|