UDPBase.cpp

#include <math.h>

#include <stdlib.h>

 

#include "../Headers/UDPBase.h"

 

// used to get parameter names in DisplayInfo() function

extern UDPPrimitiveParameterDefinition primParams[];

 

const double PI = 3.1415926535897932;

 

//***************************************

// Basic functions

//***************************************

int getVerNum(char *ver)

{

if (!ver) return 0;

double verD = 0;

sscanf(ver, "%lf", &verD);

return int(verD*100 + 0.5);

}

 

double getDistance(UDPPosition p0, UDPPosition p1)

{

double dx = p0.x - p1.x;

double dy = p0.y - p1.y;

double dz = p0.z - p1.z;

 

return sqrt(dx*dx + dy*dy + dz*dz);

}

 

// filter segments with length < minD from a polyline

void purifyPolyline(UDPPolylineDefinition& polylineDefinition, double minD)

{

int noOfSegments = polylineDefinition.noOfSegments;

int noOfPoints = polylineDefinition.noOfPoints;

UDPPosition* pos = polylineDefinition.arrayOfPosition;

UDPPolylineSegmentDefinition* edge = polylineDefinition.arrayOfSegmentDefinition;

 

int i0=0, j0=0, i, j;

for (j=0; j<noOfSegments; j++) {

int i1 = edge[j].segmentStartIndex;

int i2 = i1 + 1;

if (edge[j].segmentType == kUDPArcSegment) i2++;

double length = getDistance(pos[i1], pos[i2 % noOfPoints]);

if (length <= minD) continue;

if (j0 == j) {j0++; i0=i2; continue;}

 

edge[j0].segmentStartIndex = i0;

edge[j0++].segmentType = edge[j].segmentType;

for (i=i1+1; i<=i2; i++) pos[++i0] = pos[i % noOfPoints];

}

polylineDefinition.noOfPoints = i0;

polylineDefinition.noOfSegments = j0;

}

 

//***********************************************

// Member function definition for base class

//***********************************************

CUDPBase::CUDPBase() {

minD = 0;

 

paramValues = 0;

checkOK = 0;

 

functionLib = 0;

callbackData = 0;

}

 

bool CUDPBase::GetValue(int i, char *s, double& v)

{

if (strcmp(primParams[i].name, s) == 0) {

v = paramValues[i];

return 1;

}

return 0;

}

 

bool CUDPBase::PutValue(int i, char *s, double& v)

{

if (strcmp(primParams[i].name, s) == 0) {

paramValues[i] = v;

return 1;

}

return 0;

}

 

bool CUDPBase::GetValue(int i, char *s, int& v)

{

if (strcmp(primParams[i].name, s) == 0) {

v = (int)paramValues[i];

return 1;

}

return 0;

}

 

bool CUDPBase::PutValue(int i, char *s, int& v)

{

if (strcmp(primParams[i].name, s) == 0) {

paramValues[i] = v;

return 1;

}

return 0;

}

 

bool CUDPBase::GetValue(int i, char *s, bool& v)

{

if (strcmp(primParams[i].name, s) == 0) {

v = paramValues[i] > 0;

return 1;

}

return 0;

}

 

bool CUDPBase::PutValue(int i, char *s, bool& v)

{

if (strcmp(primParams[i].name, s) == 0) {

paramValues[i] = v ? 1.0 : 0;

return 1;

}

return 0;

}

 

// set oriParams pointer, and make a copy of data to paramValues

void CUDPBase::IniParameters(double* paramValues0, int num)

{

oriParams = paramValues0;

numOfParams = num;

delete[] paramValues;

paramValues = new double [num];

for (int i=0; i<num; i++) paramValues[i] = oriParams[i];

}

 

// map parameter values of old version to new version based on keywords

void CUDPBase::MapParameters(UDPPrimitiveParameterDefinition* params, int oldNum)

{

if (!primParams) return;

int i, j, j0=0;

for (i=0; i<numOfParams; i++) {

oriParams[i] = primParams[i].defaultValue;

if (j0<oldNum && strcmp(primParams[i].name, params[j0].name)==0) {

oriParams[i] = params[j0++].defaultValue;

continue;

}

for (j=0; j<oldNum; j++) {

if (strcmp(primParams[i].name, params[j].name) == 0) {

oriParams[i] = params[j].defaultValue;

j0 = j+1;

break;;

}

}

}

}

 

// set default values based the keyword of *key

void CUDPBase::SetDefaultParameter(double *returnParam, char *key, double defVal)

{

for (int i=0; i<numOfParams; i++) {

if (strcmp(primParams[i].name, key) == 0) {

returnParam[i] = defVal;

return;

}

}

}

 

int CUDPBase::AreParametersValid(char ** error)

{

GetParameters();

checkOK = 0;

char *err = ValidateParameters();

if (err) {

*error = err;

return 0;

}

PutParameters();

checkOK = 1;

 

return 1;

}

 

void CUDPBase::SetFunctionLib(UDPFunctionLib* functionLib0, void* callbackData0)

{

functionLib = functionLib0;

callbackData = callbackData0;

}

 

void CUDPBase::DisplayInfo(char *msg0)

{

if (msg0) {

functionLib->addMessage(kUDPInfoMessage, msg0, callbackData);

return;

}

 

char msg[BUFSIZ];

for (int i=0; i<numOfParams; i++) {

double err = primParams[i].unitType==kUDPLengthUnit ? minD : 1e-6;

if (fabs(paramValues[i] - oriParams[i]) <= err) continue;

sprintf(msg, "%s is modified from %g to %g",

primParams[i].name, oriParams[i], paramValues[i]);

functionLib->addMessage(kUDPInfoMessage, msg, callbackData);

}

}

 

// create a line from startPos to endPos

long CUDPBase::CreateLine(UDPPosition startPos, UDPPosition endPos)

{

UDPPosition posArray[2] = {startPos, endPos};

UDPPolylineSegmentDefinition SegArray = {kUDPLineSegment, 0};

UDPPolylineDefinition lineDef = {2, posArray, 1, &SegArray, 0, 0};

return functionLib->createPolyline(&lineDef, callbackData);

}

 

// create a polyline

long CUDPBase::CreatePolyLine(UDPPosition *pos, int numPos)

{

if (numPos <= 1) return -1;

 

long IDs[2] = {-1, -1};

for (int i=0; i<numPos-1; i++) {

IDs[1] = CreateLine(pos[i], pos[i+1]);

IDs[0] = AddObject(IDs[0], IDs[1]);

}

 

return IDs[0];

}

 

// Create a path on z-axis symmetrically with given length for sweeping along a path

long CUDPBase::CreateZAxisPath(double z0, double z1)

{

UDPPosition startPos = {0, 0, z0};

UDPPosition endPos = {0, 0, z1};

return CreateLine(startPos, endPos);

}

 

// create a cover sheet of straight line edges

long CUDPBase::CreateSheet(UDPPosition *pos, int numPos, int isSheet)

{

if (isSheet == 0) return CreatePolyLine(pos, numPos);

 

int numSeg = isSheet==1 ? numPos : numPos-1;

UDPPolylineSegmentDefinition *seg = new UDPPolylineSegmentDefinition [numSeg];

for (int i=0; i<numSeg; i++) {

seg[i].segmentType = kUDPLineSegment;

seg[i].segmentStartIndex = i;

}

 

UDPPolylineDefinition profile = {numPos, pos, numSeg, seg, isSheet, isSheet};

purifyPolyline(profile, minD);

if (profile.noOfPoints < 3) return -1;

long sheet = functionLib->createPolyline(&profile, callbackData);

delete[] seg;

return sheet;

}

 

// sweep along the specified axis within (v0, v1)

long CUDPBase::SweepAlongAxis(long obj, UDPCoordinateSystemAxis axis,

double v0, double v1)

{

if (obj == -1) return obj;

if (functionLib==0 || callbackData==0) return obj;

if (v0 == v1) return obj;

 

UDPPosition startPos = {0, 0, 0};

UDPPosition endPos = {0, 0, 0};

if (axis == kUDPXAxis) {

startPos.x = v0;

endPos.x = v1;

}

if (axis == kUDPYAxis) {

startPos.y = v0;

endPos.y = v1;

}

if (axis == kUDPZAxis) {

startPos.z = v0;

endPos.z = v1;

}

 

UDPSweepOptions sweepOptions = {kUDPRoundDraft, 0.0, 0.0};

long sweepPath = CreateLine(startPos, endPos);

if (sweepPath == -1) return obj;

functionLib->sweepAlongPath(obj, sweepPath, &sweepOptions, callbackData);

 

return obj;

}

 

// sweep around the specified axis for ang degrees without twist

long CUDPBase::SweepAroundAxis(long obj, UDPCoordinateSystemAxis axis, double angle)

{

if (obj == -1) return obj;

if (functionLib==0 || callbackData==0) return obj;

if (angle == 0) return obj;

 

UDPSweepOptions sweepOptions = {kUDPRoundDraft, 0.0, 0.0};

functionLib->sweepAroundAxis(obj, axis, angle, &sweepOptions, callbackData);

 

return obj;

}

 

// rotate around a vector through (x0, y0) in parallel with Z axis

long CUDPBase::RotateAroundZVector(long obj, double angle, double x0, double y0)

{

if (obj == -1) return obj;

angle -= floor(angle/360) * 360;

if (angle == 0) return obj;

 

UDPVector vector = {-x0, -y0, 0};

functionLib->translate(obj, &vector, callbackData);

functionLib->rotate(obj, kUDPZAxis, angle, callbackData);

UDPVector vector2 = {x0, y0, 0};

functionLib->translate(obj, &vector2, callbackData);

return obj;

}

 

// duplicate an object around given axis and return the united part

long CUDPBase::DuplicateAroundAxis(long obj, UDPCoordinateSystemAxis axis,

int num, double angle)

{

if (obj == -1) return obj;

if (num == 1) return obj;

 

long *IDs = new long [num];

if (angle==0) angle = 360.0 / num;

long bSuccess = functionLib->duplicateAroundAxis(obj, axis, angle, num, IDs,

callbackData);

 

long id = IDs[0];

if (bSuccess == 1) {

IDs[num - 1] = obj;

bSuccess = functionLib->unite(IDs, num, callbackData);

}

delete[] IDs;

 

return bSuccess==0 ? obj : id;

}

 

// add objAdd to objBase and unite them together

long CUDPBase::AddObject(long objBase, long objAdd)

{

if (objAdd < 0) return objBase;

if (objBase < 0) return objAdd;

 

long IDs[] = {objBase, objAdd};

functionLib->unite(IDs, 2, callbackData);

return objBase;

}

 

// subject objSub from objBase

long CUDPBase::SubObject(long objBase, long objSub)

{

if (objSub < 0) return objBase;

if (objBase < 0) return -1;

 

long bSuccess = functionLib->subtract(&objBase, 1, &objSub, 1, callbackData);

if (bSuccess == 0) return -1;

 

return objBase;

}