solvespace/sketch.h
Jonathan Westhues 364938f332 Add an arc entity. That's not allowed to exist in free space (since
we need something to force the points into plane, and the workplane
supplies that), but otherwise straightforward. And add diameter and
equal radius constraints for the arc.

[git-p4: depot-paths = "//depot/solvespace/": change = 1718]
2008-05-12 02:01:44 -08:00

451 lines
13 KiB
C++

#ifndef __SKETCH_H
#define __SKETCH_H
class hGroup;
class hRequest;
class hEntity;
class hParam;
class Entity;
class Param;
class hEquation;
class Equation;
// All of the hWhatever handles are a 32-bit ID, that is used to represent
// some data structure in the sketch.
class hGroup {
public:
// bits 15: 0 -- group index
DWORD v;
inline hEntity entity(int i);
inline hParam param(int i);
inline hEquation equation(int i);
};
class hRequest {
public:
// bits 15: 0 -- request index
DWORD v;
inline hEntity entity(int i);
inline hParam param(int i);
inline bool IsFromReferences(void);
};
class hEntity {
public:
// bits 15: 0 -- entity index
// 31:16 -- request index
DWORD v;
inline bool isFromRequest(void);
inline hRequest request(void);
inline hGroup group(void);
inline hEquation equation(int i);
};
class hParam {
public:
// bits 15: 0 -- param index
// 31:16 -- request index
DWORD v;
inline hRequest request(void);
};
class EntityId {
public:
DWORD v; // entity ID, starting from 0
};
class EntityMap {
public:
int tag;
EntityId h;
hEntity input;
int copyNumber;
// (input, copyNumber) gets mapped to ((Request)xxx).entity(h.v)
};
// A set of requests. Every request must have an associated group.
class Group {
public:
static const hGroup HGROUP_REFERENCES;
int tag;
hGroup h;
static const int DRAWING_3D = 5000;
static const int DRAWING_WORKPLANE = 5001;
static const int EXTRUDE = 5010;
static const int ROTATE = 5020;
static const int TRANSLATE = 5030;
int type;
bool solved;
hGroup opA;
hGroup opB;
bool visible;
static const int WORKPLANE_BY_POINT_ORTHO = 6000;
static const int WORKPLANE_BY_LINE_SEGMENTS = 6001;
struct {
int type;
Quaternion q;
hEntity origin;
hEntity entityB;
hEntity entityC;
bool swapUV;
bool negateU;
bool negateV;
} wrkpl;
SEdgeList edges;
SList<SPolygon> faces;
struct {
SEdge notClosedAt;
bool yes;
} polyError;
NameStr name;
char *DescriptionString(void);
static void AddParam(IdList<Param,hParam> *param, hParam hp, double v);
void Generate(IdList<Entity,hEntity> *entity, IdList<Param,hParam> *param);
// When a request generates entities from entities, and the source
// entities may have come from multiple requests, it's necessary to
// remap the entity ID so that it's still unique. We do this with a
// mapping list.
IdList<EntityMap,EntityId> remap;
hEntity Remap(hEntity in, int copyNumber);
void CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz,
hParam qw, hParam qvx, hParam qvy, hParam qvz,
bool transOnly, bool isExtrusion);
void GenerateEquations(IdList<Equation,hEquation> *l);
void MakePolygons(void);
void Draw(void);
SPolygon GetPolygon(void);
static void MenuGroup(int id);
};
// A user request for some primitive or derived operation; for example a
// line, or a step and repeat.
class Request {
public:
// Some predefined requests, that are present in every sketch.
static const hRequest HREQUEST_REFERENCE_XY;
static const hRequest HREQUEST_REFERENCE_YZ;
static const hRequest HREQUEST_REFERENCE_ZX;
int tag;
hRequest h;
// Types of requests
static const int WORKPLANE = 100;
static const int DATUM_POINT = 101;
static const int LINE_SEGMENT = 200;
static const int CUBIC = 300;
static const int CIRCLE = 400;
static const int ARC_OF_CIRCLE = 500;
int type;
hEntity workplane; // or Entity::FREE_IN_3D
hGroup group;
NameStr name;
bool construction;
static hParam AddParam(IdList<Param,hParam> *param, hParam hp);
void Generate(IdList<Entity,hEntity> *entity, IdList<Param,hParam> *param);
char *DescriptionString(void);
};
class Entity {
public:
int tag;
hEntity h;
static const hEntity FREE_IN_3D;
static const hEntity NO_ENTITY;
static const int POINT_IN_3D = 2000;
static const int POINT_IN_2D = 2001;
static const int POINT_N_TRANS = 2010;
static const int POINT_N_ROT_TRANS = 2011;
static const int POINT_N_COPY = 2012;
static const int NORMAL_IN_3D = 3000;
static const int NORMAL_IN_2D = 3001;
// This is a normal that lies in a plane; so if the defining workplane
// has basis vectors uw, vw, nw, then
// n = (cos theta)*uw + (sin theta)*vw
// u = (sin theta)*uw - (cos theta)*vw
// v = nw
static const int NORMAL_IN_PLANE = 3002;
static const int NORMAL_N_COPY = 3010;
static const int NORMAL_N_ROT = 3011;
static const int DISTANCE = 4000;
static const int DISTANCE_N_COPY = 4001;
static const int WORKPLANE = 10000;
static const int LINE_SEGMENT = 11000;
static const int CUBIC = 12000;
static const int CIRCLE = 13000;
static const int ARC_OF_CIRCLE = 14000;
int type;
// When it comes time to draw an entity, we look here to get the
// defining variables.
hEntity point[4];
hEntity normal;
hEntity distance;
// The only types that have their own params are points, normals,
// and directions.
hParam param[7];
// Transformed points/normals/distances have their numerical value.
Vector numPoint;
Quaternion numNormal;
double numDistance;
hGroup group;
hEntity workplane; // or Entity::FREE_IN_3D
bool construction;
// For entities that are derived by a transformation, the number of
// times to apply the transformation.
int timesApplied;
bool IsCircle(void);
Expr *CircleGetRadiusExpr(void);
double CircleGetRadiusNum(void);
void ArcGetAngles(double *thetaa, double *thetab, double *dtheta);
bool HasVector(void);
ExprVector VectorGetExprs(void);
Vector VectorGetNum(void);
Vector VectorGetRefPoint(void);
// For distances
double DistanceGetNum(void);
Expr *DistanceGetExpr(void);
void DistanceForceTo(double v);
bool IsWorkplane(void);
// The plane is points P such that P dot (xn, yn, zn) - d = 0
void WorkplaneGetPlaneExprs(ExprVector *n, Expr **d);
ExprVector WorkplaneGetOffsetExprs(void);
Vector WorkplaneGetOffset(void);
Entity *Normal(void);
bool IsPoint(void);
// Applies for any of the point types
Vector PointGetNum(void);
ExprVector PointGetExprs(void);
void PointGetExprsInWorkplane(hEntity wrkpl, Expr **u, Expr **v);
void PointForceTo(Vector v);
bool PointIsFromReferences(void);
// These apply only the POINT_N_ROT_TRANS, which has an assoc rotation
Quaternion PointGetQuaternion(void);
void PointForceQuaternionTo(Quaternion q);
bool IsNormal(void);
// Applies for any of the normal types
Quaternion NormalGetNum(void);
ExprQuaternion NormalGetExprs(void);
void NormalForceTo(Quaternion q);
Vector NormalU(void);
Vector NormalV(void);
Vector NormalN(void);
ExprVector NormalExprsU(void);
ExprVector NormalExprsV(void);
ExprVector NormalExprsN(void);
// Routines to draw and hit-test the representation of the entity
// on-screen.
struct {
bool drawing;
Point2d mp;
double dmin;
SEdgeList *edges;
} dogd; // state for drawing or getting distance (for hit testing)
void LineDrawOrGetDistance(Vector a, Vector b);
void LineDrawOrGetDistanceOrEdge(Vector a, Vector b);
void DrawOrGetDistance(int order);
void Draw(int order);
double GetDistance(Point2d mp);
void GenerateEdges(SEdgeList *el);
void AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index);
void GenerateEquations(IdList<Equation,hEquation> *l);
char *DescriptionString(void);
};
class Param {
public:
int tag;
hParam h;
double val;
bool known;
bool assumed;
// Used only in the solver
hParam substd;
static const hParam NO_PARAM;
};
class hConstraint {
public:
DWORD v;
inline hEquation equation(int i);
};
class Constraint {
public:
static const int USER_EQUATION = 10;
static const int POINTS_COINCIDENT = 20;
static const int PT_PT_DISTANCE = 30;
static const int PT_LINE_DISTANCE = 31;
static const int PT_PLANE_DISTANCE = 32;
static const int PT_IN_PLANE = 40;
static const int PT_ON_LINE = 41;
static const int EQUAL_LENGTH_LINES = 50;
static const int LENGTH_RATIO = 51;
static const int SYMMETRIC = 60;
static const int AT_MIDPOINT = 70;
static const int HORIZONTAL = 80;
static const int VERTICAL = 81;
static const int DIAMETER = 90;
static const int PT_ON_CIRCLE = 100;
static const int SAME_ORIENTATION = 110;
static const int PARALLEL = 120;
static const int EQUAL_RADIUS = 130;
int tag;
hConstraint h;
int type;
hGroup group;
hEntity workplane;
// These are the parameters for the constraint.
Expr *exprA;
Expr *exprB;
hEntity ptA;
hEntity ptB;
hEntity ptC;
hEntity entityA;
hEntity entityB;
// These define how the constraint is drawn on-screen.
struct {
Vector offset;
} disp;
char *DescriptionString(void);
static hConstraint AddConstraint(Constraint *c);
static void MenuConstrain(int id);
struct {
bool drawing;
Point2d mp;
double dmin;
} dogd; // state for drawing or getting distance (for hit testing)
void LineDrawOrGetDistance(Vector a, Vector b);
void DrawOrGetDistance(Vector *labelPos);
double EllipticalInterpolation(double rx, double ry, double theta);
void DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu);
void DoProjectedPoint(Vector *p);
double GetDistance(Point2d mp);
Vector GetLabelPos(void);
void Draw(void);
bool HasLabel(void);
void Generate(IdList<Equation,hEquation> *l);
// Some helpers when generating symbolic constraint equations
void ModifyToSatisfy(void);
void AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index);
static Expr *Distance(hEntity workplane, hEntity pa, hEntity pb);
static Expr *PointLineDistance(hEntity workplane, hEntity pt, hEntity ln);
static Expr *PointPlaneDistance(ExprVector p, hEntity plane);
static Expr *VectorsParallel(int eq, ExprVector a, ExprVector b);
static ExprVector PointInThreeSpace(hEntity workplane, Expr *u, Expr *v);
static void ConstrainCoincident(hEntity ptA, hEntity ptB);
static void Constrain(int type, hEntity ptA, hEntity ptB, hEntity entityA);
};
class hEquation {
public:
DWORD v;
};
class Equation {
public:
int tag;
hEquation h;
Expr *e;
};
inline hEntity hGroup::entity(int i)
{ hEntity r; r.v = 0x80000000 | (v << 16) | i; return r; }
inline hParam hGroup::param(int i)
{ hParam r; r.v = 0x80000000 | (v << 16) | i; return r; }
inline hEquation hGroup::equation(int i)
{ if(i != 0) oops(); hEquation r; r.v = v | 0x80000000; return r; }
inline bool hRequest::IsFromReferences(void) {
if(v == Request::HREQUEST_REFERENCE_XY.v) return true;
if(v == Request::HREQUEST_REFERENCE_YZ.v) return true;
if(v == Request::HREQUEST_REFERENCE_ZX.v) return true;
return false;
}
inline hEntity hRequest::entity(int i)
{ hEntity r; r.v = (v << 16) | i; return r; }
inline hParam hRequest::param(int i)
{ hParam r; r.v = (v << 16) | i; return r; }
inline bool hEntity::isFromRequest(void)
{ if(v & 0x80000000) return false; else return true; }
inline hRequest hEntity::request(void)
{ hRequest r; r.v = (v >> 16); return r; }
inline hGroup hEntity::group(void)
{ hGroup r; r.v = (v >> 16) & 0x3fff; return r; }
inline hEquation hEntity::equation(int i)
{ if(i != 0) oops(); hEquation r; r.v = v | 0x40000000; return r; }
inline hRequest hParam::request(void)
{ hRequest r; r.v = (v >> 16); return r; }
inline hEquation hConstraint::equation(int i)
{ hEquation r; r.v = (v << 16) | i; return r; }
#endif