#ifndef __DSC_H #define __DSC_H typedef unsigned long DWORD; typedef unsigned char BYTE; class Vector; class Point2d; class hEntity; class hParam; class Quaternion { public: // a + (vx)*i + (vy)*j + (vz)*k double w, vx, vy, vz; static Quaternion From(double w, double vx, double vy, double vz); static Quaternion From(hParam w, hParam vx, hParam vy, hParam vz); static Quaternion From(Vector u, Vector v); Quaternion Plus(Quaternion b); Quaternion Minus(Quaternion b); Quaternion ScaledBy(double s); double Magnitude(void); Quaternion WithMagnitude(double s); // Call a rotation matrix [ u' v' n' ]'; this returns the first and // second rows, where that matrix is generated by this quaternion Vector RotationU(void); Vector RotationV(void); Vector RotationN(void); Vector Rotate(Vector p); Quaternion ToThe(double p); Quaternion Inverse(void); Quaternion Times(Quaternion b); }; class Vector { public: double x, y, z; static Vector From(double x, double y, double z); static Vector From(hParam x, hParam y, hParam z); static Vector AtIntersectionOfPlanes(Vector n1, double d1, Vector n2, double d2); static Vector AtIntersectionOfLines(Vector a0, Vector a1, Vector b0, Vector b1, bool *skew); double Element(int i); bool Equals(Vector v, double tol=LENGTH_EPS); bool EqualsExactly(Vector v); Vector Plus(Vector b); Vector Minus(Vector b); Vector Negated(void); Vector Cross(Vector b); double Dot(Vector b); Vector Normal(int which); Vector RotatedAbout(Vector orig, Vector axis, double theta); Vector RotatedAbout(Vector axis, double theta); Vector DotInToCsys(Vector u, Vector v, Vector n); Vector ScaleOutOfCsys(Vector u, Vector v, Vector n); double DistanceToLine(Vector p0, Vector dp); bool OnLineSegment(Vector a, Vector b); Vector ClosestPointOnLine(Vector p0, Vector dp); double Magnitude(void); double MagSquared(void); Vector WithMagnitude(double s); Vector ScaledBy(double s); Vector ProjectInto(hEntity wrkpl); Vector ProjectVectorInto(hEntity wrkpl); double DivPivoting(Vector delta); Vector ClosestOrtho(void); Point2d Project2d(Vector u, Vector v); }; class Point2d { public: double x, y; Point2d Plus(Point2d b); Point2d Minus(Point2d b); Point2d ScaledBy(double s); double DistanceTo(Point2d p); double DistanceToLine(Point2d p0, Point2d dp, bool segment); double Magnitude(void); Point2d WithMagnitude(double v); }; // A simple list template class List { public: T *elem; int n; int elemsAllocated; void Add(T *t) { if(n >= elemsAllocated) { elemsAllocated = (elemsAllocated + 32)*2; elem = (T *)MemRealloc(elem, elemsAllocated*sizeof(elem[0])); } elem[n++] = *t; } T *First(void) { return (n == 0) ? NULL : &(elem[0]); } T *NextAfter(T *prev) { if(!prev) return NULL; if(prev - elem == (n - 1)) return NULL; return prev + 1; } void ClearTags(void) { int i; for(i = 0; i < n; i++) { elem[i].tag = 0; } } void Clear(void) { if(elem) MemFree(elem); elem = NULL; n = elemsAllocated = 0; } void RemoveTagged(void) { int src, dest; dest = 0; for(src = 0; src < n; src++) { if(elem[src].tag) { // this item should be deleted } else { if(src != dest) { elem[dest] = elem[src]; } dest++; } } n = dest; // and elemsAllocated is untouched, because we didn't resize } void Reverse(void) { int i; for(i = 0; i < (n/2); i++) { SWAP(T, elem[i], elem[(n-1)-i]); } } }; // A list, where each element has an integer identifier. The list is kept // sorted by that identifier, and items can be looked up in log n time by // id. template class IdList { public: T *elem; int n; int elemsAllocated; H AddAndAssignId(T *t) { int i; DWORD id = 0; for(i = 0; i < n; i++) { id = max(id, elem[i].h.v); } t->h.v = (id + 1); Add(t); return t->h; } void Add(T *t) { if(n >= elemsAllocated) { elemsAllocated = (elemsAllocated + 32)*2; elem = (T *)MemRealloc(elem, elemsAllocated*sizeof(elem[0])); } int first = 0, last = n; // We know that we must insert within the closed interval [first,last] while(first != last) { int mid = (first + last)/2; H hm = elem[mid].h; if(hm.v > t->h.v) { last = mid; } else if(hm.v < t->h.v) { first = mid + 1; } else { oops(); } } int i = first; memmove(elem+i+1, elem+i, (n-i)*sizeof(elem[0])); elem[i] = *t; n++; } T *FindById(H h) { T *t = FindByIdNoOops(h); if(!t) { dbp("failed to look up item %08x, searched %d items", h.v, n); oops(); } return t; } T *FindByIdNoOops(H h) { int first = 0, last = n-1; while(first <= last) { int mid = (first + last)/2; H hm = elem[mid].h; if(hm.v > h.v) { last = mid-1; // and first stays the same } else if(hm.v < h.v) { first = mid+1; // and last stays the same } else { return &(elem[mid]); } } return NULL; } T *First(void) { return (n == 0) ? NULL : &(elem[0]); } T *NextAfter(T *prev) { if(!prev) return NULL; if(prev - elem == (n - 1)) return NULL; return prev + 1; } void ClearTags(void) { int i; for(i = 0; i < n; i++) { elem[i].tag = 0; } } void Tag(H h, int tag) { int i; for(i = 0; i < n; i++) { if(elem[i].h.v == h.v) { elem[i].tag = tag; } } } void RemoveTagged(void) { int src, dest; dest = 0; for(src = 0; src < n; src++) { if(elem[src].tag) { // this item should be deleted } else { if(src != dest) { elem[dest] = elem[src]; } dest++; } } n = dest; // and elemsAllocated is untouched, because we didn't resize } void RemoveById(H h) { ClearTags(); FindById(h)->tag = 1; RemoveTagged(); } void MoveSelfInto(IdList *l) { memcpy(l, this, sizeof(*this)); elemsAllocated = n = 0; elem = NULL; } void DeepCopyInto(IdList *l) { l->elem = (T *)MemAlloc(elemsAllocated * sizeof(elem[0])); memcpy(l->elem, elem, elemsAllocated * sizeof(elem[0])); l->elemsAllocated = elemsAllocated; l->n = n; } void Clear(void) { elemsAllocated = n = 0; if(elem) MemFree(elem); elem = NULL; } }; class NameStr { public: char str[64]; inline void strcpy(char *in) { memcpy(str, in, min(strlen(in)+1, sizeof(str))); str[sizeof(str)-1] = '\0'; } }; #endif