
constraints. And generate the constraint equations for entities (e.g., that our unit quaternions have magnitude one). Numerical troubles there, but it sort of works. Also some stuff to draw projection lines with projected constraints, and to auto-insert more constraints as you draw. [git-p4: depot-paths = "//depot/solvespace/": change = 1711]
408 lines
11 KiB
C++
408 lines
11 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);
|
|
};
|
|
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 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 = 5000;
|
|
static const int EXTRUDE = 5010;
|
|
int type;
|
|
|
|
int solveOrder;
|
|
bool solved;
|
|
|
|
hGroup opA;
|
|
hGroup opB;
|
|
bool visible;
|
|
|
|
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,
|
|
bool isExtrusion);
|
|
|
|
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;
|
|
|
|
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_XFRMD = 2010;
|
|
|
|
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_XFRMD = 3010;
|
|
|
|
static const int DISTANCE = 4000;
|
|
static const int DISTANCE_XFRMD = 4001;
|
|
|
|
static const int WORKPLANE = 10000;
|
|
static const int LINE_SEGMENT = 11000;
|
|
static const int CUBIC = 12000;
|
|
static const int CIRCLE = 13000;
|
|
|
|
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[4];
|
|
|
|
// 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);
|
|
|
|
bool HasDirection(void);
|
|
ExprVector GetDirection(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);
|
|
|
|
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;
|
|
};
|
|
|
|
|
|
class hConstraint {
|
|
public:
|
|
DWORD v;
|
|
|
|
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 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;
|
|
|
|
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 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 hEquation hEntity::equation(int i)
|
|
{ if(i != 0) oops(); hEquation r; r.v = v | 0x80000000; 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
|