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;
}