/*********************************************************************** * * ELMER, A Computational Fluid Dynamics Program. * * Copyright 1st April 1995 - , Center for Scientific Computing, * Finland. * * All rights reserved. No part of this program may be used, * reproduced or transmitted in any form or by any means * without the written permission of CSC. * * Address: Center for Scientific Computing * Tietotie 6, P.O. BOX 405 * 02101 Espoo, Finland * Tel. +358 0 457 2001 * Telefax: +358 0 457 2302 * EMail: Jari.Jarvinen@csc.fi ************************************************************************/ /*********************************************************************** Program: ELMER Front Module: ecif_geometry.cpp Language: C++ Date: 01.10.98 Version: 1.00 Author(s): Martti Verho Revisions: Abstract: Implementation ************************************************************************/ #include "ecif_def_stl.h" #include "ecif_boundbox.h" #include "ecif_bodyElement.h" #include "ecif_bodyElement1D.h" #include "ecif_control.h" #include "ecif_geometry.h" #include "ecif_model.h" #include "ecif_nurbs.h" #include "ecif_renderer.h" #include "ecif_userinterface.h" // Typedefs for safer calling typedef int (Callbackp dllCircleFunc)(enum egf_FuncType ft, int argc, double* argv, egf_Point3* start, egf_Point3* end, int& nof_circles, egf_Circle*& circles); typedef int (Callbackp dllPolyLineFunc)(enum egf_FuncType ft, int argc, double* argv, egf_Point3* start, egf_Point3* end, int& nof_polylines, egf_PolyLine*& polylines); // Static class variables // Model* Geometry::model = NULL; ecif_geometryType GcCircle::type = ECIF_CIRCLE; ecif_geometryType GcLine::type = ECIF_LINE; ecif_geometryType GcPlane::type = ECIF_LINE; ecif_geometryType GcPoint::type = ECIF_NODIM; ecif_geometryType GcPolyLine::type = ECIF_POLYLINE; ecif_geometryType GcNurbsCurve::type = ECIF_NURBS; ecif_geometryType GcNurbsSurface::type = ECIF_NURBS; //extern const float colorValues[][4]; RayHit::RayHit() { count = 0; min_value = 1.0e+100; } RayHit::~RayHit() { Point3List::iterator itr; for (itr = points.begin(); itr != points.end(); itr++) { delete *itr; } points.clear(); } //*************************** //*****Geometry methods ***** //*************************** Geometry::Geometry() { boundbox = NULL; geometryOk = true; } Geometry::~Geometry() { delete boundbox; } void Geometry::calcLinearizingPoints(int& nof_points_u, int& nof_points_v, GcPoint**& points, double delta_u, double delta_v) { nof_points_u = 0; nof_points_v = 0; points = NULL; } // Just cover function to call a more specific form void Geometry::draw(Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction) { draw(renderer, dmode, dstate); } // Just cover function to call a more specific form void Geometry::draw(Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id) { draw(renderer, dmode, dstate, direction); } // Just cover function to call a more specific form void Geometry::draw(Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id, bool is_first_loop) { draw(renderer, dmode, dstate, direction, elem_id); } // Just cover function to call a more specific form void Geometry::draw(int gmtr_index, Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction) { if ( gmtr_index < 0 ) return; if ( isMultiGeometry() ) { draw(gmtr_index, renderer, dmode, dstate); } else { draw(renderer, dmode, dstate, direction); } } // Just cover function to call a more specific form void Geometry::draw(int gmtr_index, Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id) { if ( gmtr_index < 0 ) return; if ( isMultiGeometry() ) { draw(gmtr_index, renderer, dmode, dstate, direction); } else { draw(renderer, dmode, dstate, direction, elem_id); } } // Just cover function to call a more specific form void Geometry::draw(int gmtr_index, Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id, bool is_first_loop) { if ( gmtr_index < 0 ) return; if ( isMultiGeometry() ) { draw(gmtr_index, renderer, dmode, dstate, direction, elem_id); } else { draw(renderer, dmode, dstate, direction, elem_id, is_first_loop); } } void Geometry::getBoundaryPoints(int& count, BoundaryPoint**& points) { points = NULL; count = 0; } void Geometry::getDiscretizationData(int& nof_components, linDeltaType*& types, double*& valuesU, double*& valuesV, bool*& useFixedN) { nof_components = 0; types = NULL; valuesU = NULL; valuesV = NULL; useFixedN = NULL; } // Finds 'nice' positions for the label point void Geometry::getLabelPoint(Point3& point) { GcPoint* p = param2Point(0.5, 0.5); if (p != NULL) { point[0] = p->Pos(X); point[1] = p->Pos(Y); point[2] = p->Pos(Z); } else { point[0] = point[1] = point[2] = NSVD; } } void Geometry::getMifTags(int& nof_tags, int*& tags) { nof_tags = 0; tags = NULL; } //************************************************************************** // Geometry1D methods //************************************************************************** Geometry1D::Geometry1D() { } Geometry1D::~Geometry1D() { } //**************************** //***** GcPoint methods ***** //**************************** GcPoint::GcPoint() { posit[X] = 0; posit[Y] = 0; posit[Z] = 0; } GcPoint GcPoint::average(GcPoint &p2, GcPoint&p3) { GcPoint res; for (char i = 0; i < MAX_DIMENSION; i++) res.posit[i] = (posit[i] + p2.posit[i] + p3.posit[i]) / 3; return res; } void GcPoint::draw(Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate) { renderer->drawPoint(dmode, dstate, &posit); } // Searching for space: if GcPoint is outside space extend the space void GcPoint::find_space(GcPoint &pmin, GcPoint &pmax) { for (char i = 0; i < MAX_DIMENSION; i++) { if (pmin.posit[i] > posit[i]) pmin.posit[i] = posit[i]; if (pmax.posit[i] < posit[i]) pmax.posit[i] = posit[i]; } } // Finds 'nice' positions for the label point void GcPoint::getLabelPoint(Point3& point) { point[0] = posit[0]; point[1] = posit[1]; point[2] = posit[2]; } int GcPoint::hashKey() { return int(posit[X]); } bool GcPoint::isBetween(GcPoint* p1, GcPoint* p2) { GcPoint tmp1 = *this - *p1; GcPoint tmp2 = *p2 - *this; GcPoint tmp = *p2 - *p1; return ((tmp1 < tmp) && (tmp2 < tmp)); } bool GcPoint::isParallel(GcPoint* other_vector) { //We check if cross product is zero-vector. GcPoint* ov = other_vector; double tmp1 = fabs(posit[Y] * ov->posit[Z] - posit[Z] * ov->posit[Y]); double tmp2 = fabs(posit[X] * ov->posit[Z] - posit[Z] * ov->posit[X]); double tmp3 = fabs(posit[X] * ov->posit[Y] - posit[Y] * ov->posit[X]); return ((tmp1 < POINT_EPSILON) && (tmp2 < POINT_EPSILON) && (tmp3 < POINT_EPSILON)); } void GcPoint::normalize(double norm[3], double shift[3]) { for (int i = 0; i < 3 ; i++) { if ( norm[i] > 0 ) posit[i] = (posit[i] + shift[i]) / norm[i]; } } void GcPoint::de_normalize(double norm[3], double shift[3]) { posit[0] = (posit[0] * norm[0]) - shift[0]; posit[1] = (posit[1] * norm[1]) - shift[1]; posit[2] = (posit[2] * norm[2]) - shift[2]; } ostream& GcPoint::output_emf(ostream& out, short indent_size, short indent_level) { LibFront::output_vector(out, indent_size, indent_level, "Point", NULL, 3, posit, false); return out; } // *** System operators bool GcPoint::operator==(const GcPoint& p2) { GcPoint hlp; double tmp; hlp = *this - p2; if ((hlp.posit[X] < POINT_EPSILON) && (hlp.posit[X] > -POINT_EPSILON) && (hlp.posit[Y] < POINT_EPSILON) && (hlp.posit[Y] > -POINT_EPSILON) && (hlp.posit[Z] < POINT_EPSILON) && (hlp.posit[Z] > -POINT_EPSILON)) return true; else return false; tmp = sqrt(hlp.posit[X] * hlp.posit[X] + hlp.posit[Y] * hlp.posit[Y] + hlp.posit[Z] * hlp.posit[Z]); if (tmp < POINT_EPSILON && tmp > -POINT_EPSILON) return true; else return false; } ostream & operator<<(ostream& stream, const GcPoint& p) { stream << p.posit[X] << " "; stream << p.posit[Y] << " "; stream << p.posit[Z]; return stream; } // *** Arithmetic operators GcPoint operator+(const GcPoint& p1, const GcPoint& p2) { double p[MAX_DIMENSION]; for (short i = 0; i < MAX_DIMENSION; i++) p[i] = p1.posit[i] + p2.posit[i]; return GcPoint(p[X], p[Y], p[Z]); } GcPoint operator-(const GcPoint& p1, const GcPoint& p2) { double p[MAX_DIMENSION]; for (short i = 0; i < MAX_DIMENSION; i++) p[i] = p1.posit[i] - p2.posit[i]; return GcPoint(p[X], p[Y], p[Z]); } GcPoint operator*(int num, const GcPoint& p) { double tmp[MAX_DIMENSION]; for (short i = 0; i < MAX_DIMENSION; i++) tmp[i] = num * p.posit[i]; return GcPoint(tmp[X], tmp[Y], tmp[Z]); } GcPoint operator/(const GcPoint& p, int num) { double tmp[MAX_DIMENSION]; for (short i = 0; i < MAX_DIMENSION; i++) if ( num != 0 ) tmp[i] = p.posit[i] / num; return GcPoint(tmp[X], tmp[Y], tmp[Z]); } // *** Relational operators bool operator==(const GcPoint &p1, const GcPoint &p2) { GcPoint hlp; hlp = p1 - p2; if ((hlp.posit[X] < POINT_EPSILON) && (hlp.posit[X] > -POINT_EPSILON) && (hlp.posit[Y] < POINT_EPSILON) && (hlp.posit[Y] > -POINT_EPSILON) && (hlp.posit[Z] < POINT_EPSILON) && (hlp.posit[Z] > -POINT_EPSILON)) return true; else return false; } bool operator!=(const GcPoint& p1, const GcPoint& p2) { if (p1 == p2) return true; else return false; } bool operator<(const GcPoint& p1, const GcPoint& p2) { if ((p1.Pos(X) < p2.Pos(X)) && (p1.Pos(Y) < p2.Pos(Y)) && (p1.Pos(Z) < p2.Pos(Z))) return true; else return false; } bool operator>(const GcPoint& p1, const GcPoint& p2) { if ((p1.posit[X] > p2.posit[X]) && (p1.posit[Y] > p2.posit[Y]) && (p1.posit[Z] > p2.posit[Z])) return true; else return false; } bool operator<=(const GcPoint& p1, const GcPoint& p2) { if ((p1.posit[X] <= p2.posit[X]) && (p1.posit[Y] <= p2.posit[Y]) && (p1.posit[Z] <= p2.posit[Z])) return 1; else return 0; } bool operator>=(const GcPoint& p1, const GcPoint& p2) { if ((p1.posit[X] >= p2.posit[X]) && (p1.posit[Y] >= p2.posit[Y]) && (p1.posit[Z] >= p2.posit[Z])) return 1; else return 0; } //*end GcPoint methods //****************************** // Methods for TransMatrix class TransfMatrix::TransfMatrix() { AA = 1; EE = 1; II = 1; BB = 0; CC = 0; DD = 0; FF = 0; GG = 0; HH = 0; JJ = 0; KK = 0; LL = 0; } TransfMatrix::TransfMatrix(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j, double k, double l) { AA = a; BB = b; CC = c; DD = d; EE = e; FF = f; GG = g; HH = h; II = i; JJ = j; KK = k; LL = l; } TransfMatrix::TransfMatrix(TransfMatrix &m) { *this = m; } void TransfMatrix::transform(GcPoint& oldp, GcPoint& newp) { double tmpx = AA * oldp.Pos(X) + DD * oldp.Pos(Y) + GG * oldp.Pos(Z) + JJ; double tmpy = BB * oldp.Pos(X) + EE * oldp.Pos(Y) + HH * oldp.Pos(Z) + KK; double tmpz = CC * oldp.Pos(X) + FF * oldp.Pos(Y) + II * oldp.Pos(Z) + LL; newp = GcPoint(tmpx, tmpy, tmpz); } TransfMatrix & TransfMatrix::operator=(const TransfMatrix& m) { AA = m.AA; BB = m.BB; CC = m.CC; DD = m.DD; EE = m.EE; FF = m.FF; GG = m.GG; HH = m.HH; II = m.II; JJ = m.JJ; KK = m.KK; LL = m.LL; return *this; } //************************************************************************** // Geometry2D methods //************************************************************************** Geometry2D::Geometry2D() { nofBoundaryPoints = 0; boundaryPoints = NULL; } Geometry2D::~Geometry2D() { } // Linearize geometry and store points in boundaryPoints array // void Geometry2D::calcBoundaryPoints() { int i; for (i = 0; i < nofBoundaryPoints; i++) { delete boundaryPoints[i]; } delete[] boundaryPoints; nofBoundaryPoints = 0; boundaryPoints = NULL; int nof_points; GcPoint** points; double delta = getParamDeltaU(); calcLinearizingPoints(nof_points, points, delta); model->updateMinimumEdgeSize(nof_points, points); if (nof_points == 0) return; boundaryPoints = new BoundaryPoint*[nof_points]; for (i = 0; i < nof_points; i++) { BoundaryPoint* bp = new BoundaryPoint; boundaryPoints[i] = bp; // Check if bp is an existing vertex! //BodyElement* v = model->getVertex(points[i]); BodyElement* v = model->findVertex(points[i]); if ( v != NULL ) { bp->tag = v->Tag(); bp->vertexTag = v->Tag(); } //bp->boundaryTag = boundary_tag; bp->point = points[i]; } // Handle possibly closed geometry // ------------------------------- //-Copy start points to end point if U-closed // if ( isClosedU() ) { boundaryPoints[nof_points - 1]->copy(*boundaryPoints[0]); boundaryPoints[nof_points - 1]->activeInMeshing = false; } nofBoundaryPoints = nof_points; // NOTE: Delete only array, not the points!!! delete[] points; } void Geometry2D::calcLinearizingPoints(int& nof_points, GcPoint**& points, double delta_u) { nof_points = 0; points = NULL; } void Geometry2D::calcLinearizingPoints(int& nof_points_u, int& nof_points_v, GcPoint**& points, double delta_u, double delta_v) { nof_points_u = 0; nof_points_v = 0; points = NULL; calcLinearizingPoints(nof_points_u, points, delta_u); } void Geometry2D::getBoundaryPoints(int& count, BoundaryPoint**& points) { points = NULL; count = nofBoundaryPoints; if ( count > 0 ) { points = new BoundaryPoint*[count]; for (int i = 0; i < count; i++) { points[i] = boundaryPoints[i]; } } } void Geometry2D::getDiscretizationData(int nof_components, char*& types, double*& valuesU, double*& valuesV, bool*& useFixedN) { nof_components = 0; types = NULL; valuesU = NULL; valuesV = NULL; useFixedN = NULL; } void Geometry2D::getMifTags(int& nof_tags, int*& tags) { nof_tags = 1; tags = new int[1]; tags[0] = mifTag; } // Output boundary point tags (for Elmer Mesh input file) // ostream& Geometry2D::outputBoundaryPointTags(ostream& out, int indent_size) { int max_per_line = 20; //--Normal vertices if ( nofBoundaryPoints == 0 ) { for (int i = 0; i < nofVertices; i++) { out << vertexTags[i] << " "; } //--Boundary points } else { int counter = 0; BoundaryPoint* bp; for (int i = 0; i < nofBoundaryPoints; i++) { if ( isClosedU() && i == nofBoundaryPoints - 1 ) { bp = boundaryPoints[0]; } else { bp = boundaryPoints[i]; } if ( bp != NULL ) { out << bp->tag << " "; counter++; } // Continue from next line if ( counter >= max_per_line ) { out << endl; indent(out, indent_size); counter = 0; } } } return out; } // Output boundary points for Elmer Mesh input file (mif-file) // ostream& Geometry2D::output_mif(ostream& out, const char* hdr, bool useFxdMeshN) { int nof_points = 0; //--Find nof nodes (verices or linearizing points) // if ( nofBoundaryPoints > 0 ) { nof_points = nofBoundaryPoints; } else { nof_points = nofVertices; } // Print positions before and after printing fixed data // (for getting the indent size for ids) int pos1, pos2; pos1 = out.tellp(); //---Mif-tag and boundary tag // out << "EdgeId: " << mifTag << " " << hdr; // If fixed discretation if ( useFxdMeshN && this->useFixedMeshN() ) { out << " N: " << nof_points - 1; } //---Nof points and point (vertex or bpoint) tags // out << " " << nof_points << " "; pos2 = out.tellp(); outputBoundaryPointTags(out, pos2 - pos1); out << endl; return out; } //**************************** //***** GcCircle methods ***** //**************************** // Constructor (for egf-files) // GcCircle::GcCircle(ecif_ElementComponent_X& tx, IdList& vertex_tags) { Point3** points = NULL; nofVertices = tx.nof_vertices; vertexTags = NULL; if ( nofVertices > 0 ) { points = new Point3*[nofVertices]; vertexTags = new int[nofVertices]; for (int i = 0; i < nofVertices; i++) { BodyElement* v = model->getVertexByTag(tx.vertex_tags[i]); vertex_tags.push_back(v->Tag()); vertexTags[i] = v->Tag(); points[i] = ((GcPoint*)v->getGeometry())->getPoint(); } } if ( !create(nofVertices, points, tx.geometry.edge, tx.lin_delta_type, tx.lin_delta[0]) ){ geometryOk = false; return; } delete[] points; data.useFixedMeshN = (bool)tx.use_fixed_mesh_n; init(); copyMatcValueTable(tx.matcTable, data.matcTable); copyMatcValueTable(tx.geometry.edge->matcTable, data.matcTable); } // Constructor // NOTE: no vertices // GcCircle::GcCircle(Point3& center ,Point3& start, Point3& stop, bool do_linearize) { nofVertices = 0; vertexTags = NULL; Point3** points = new Point3*[2]; points[0] = &start; points[1] = &stop; ecif_EdgeGeometry_X* param = new ecif_EdgeGeometry_X; init_trx_data(*param); param->location = new Point3[1]; param->location[0][0] = center[0]; param->location[0][1] = center[1]; param->location[0][2] = center[2]; if ( !create(2, points, param, LIN_DELTA_NONE, -1.0, do_linearize) ) { geometryOk = false; } delete[] points; if (!geometryOk) return; init(do_linearize); reset_trx_data(*param); delete param; } // Constructor // NOTE: no vertices // GcCircle::GcCircle(int nof_points, Point3** points, ecif_EdgeGeometry_X* params, bool do_linearize) { int i; nofVertices = 0; vertexTags = NULL; if ( !create(nof_points, points, params, LIN_DELTA_NONE, -1.0, do_linearize) ) { geometryOk = false; } if (!geometryOk) return; init(do_linearize); } // Constructor // GcCircle::GcCircle(BodyElement* vertex1, BodyElement* vertex2, ecif_EdgeGeometry_X* edge, bool do_linearize) { if ( vertex1 == vertex2 ) { nofVertices = 1; } else { nofVertices = 2; } vertexTags = new int[2]; vertexTags[0] = vertex1->Tag(); vertexTags[1] = vertex2->Tag(); Point3** points = new Point3*[2]; points[0] = ((GcPoint*)vertex1->getGeometry())->getPoint(); points[1] = ((GcPoint*)vertex2->getGeometry())->getPoint(); if ( !create(nofVertices, points, edge, LIN_DELTA_NONE, -1.0, do_linearize) ) { geometryOk = false; } delete[] points; if (!geometryOk) return; init(do_linearize); } // Create circle bool GcCircle::create(int nof_points, Point3** points, ecif_EdgeGeometry_X* params, enum linDeltaType lin_delta_type, double lin_delta, bool do_linearize) { bool center_given = false; bool radius_given = false; Point3 p1, p2; // Pick parameters // --------------- //--Circle arc if ( nof_points == 2 ) { data.start = new GcPoint(points[0]); data.end = new GcPoint(points[1]); data.start->getPoint(p1); data.end->getPoint(p2); if ( isZero(dist3(p1, p2)) ) { data.isClosed = true; } else { data.isClosed = false; } //--Full circle } else { data.isClosed = true; if ( params->start != NULL ) { data.start = new GcPoint(params->start); } if ( params->end != NULL ) { data.end = new GcPoint(params->end); } data.start_u = 0.0; data.end_u = TWO_PI; } // If center given if (params->location != NULL) { data.centerGiven = true; copy3(*params->location, data.center); } // If radius given if (params->radius1 > 0 ) { data.radiusGiven = true; data.radius = params->radius1; } // Copy possible defining points data.nofDefiningPoints = params->nofDefiningPoints; if ( data.nofDefiningPoints > 0 ) { data.definingPoints = new Point3[data.nofDefiningPoints]; for (int i = 0; i < data.nofDefiningPoints; i++) { for (int j = 0; j < 3; j++) { data.definingPoints[i][j] = params->definingPoints[i][j]; } } } data.deltaType = lin_delta_type; data.delta = lin_delta; // Set final data parameters // ------------------------- if ( !updateData() ) return false; setDeltaU(lin_delta_type, lin_delta); nofBoundaryPoints = 0; boundaryPoints = NULL; return true; } void GcCircle::getDiscretizationData(int& nof_components, linDeltaType*& types, double*& valuesU, double*& valuesV, bool*& useFixedN) { nof_components = 1; types = new enum linDeltaType[1]; types[0] = data.deltaType; valuesU = new double[1]; valuesU[0] = data.delta; valuesV = NULL; useFixedN = new bool[1]; useFixedN[0] = data.useFixedMeshN; } bool GcCircle::getLine(int index, GcLine*& line) { if ( index < 0 || index >= nofBoundaryPoints - 1) { return false; } Point3* p1 = boundaryPoints[index]->point->getPoint(); Point3* p2 = boundaryPoints[index + 1]->point->getPoint(); line = new GcLine(p1, p2); return true; } void GcCircle::init(bool do_linearize) { if (do_linearize) { calcBoundaryPoints(); } boundbox = calcBoundBox(); } // Destructor. GcCircle::~GcCircle() { delete[] vertexTags; } // Calculates bounding box for the circle. BoundBox* GcCircle::calcBoundBox() { RangeVector range; BoundBox* bbox = new BoundBox; Point3* bp1; Point3* bp2; if ( nofBoundaryPoints == 0 ) { calcBoundaryPoints(); } // Arc if ( !data.isClosed ) { for (int i = 0; i < nofBoundaryPoints; i++) { bbox->extendByPoint(boundaryPoints[i]->point); } // Full circle } else { RangeVector rv; rv[0] = data.center[0] - data.radius; rv[1] = data.center[0] + data.radius; rv[2] = data.center[1] - data.radius; rv[3] = data.center[1] + data.radius; rv[4] = 0; rv[5] = 0; bbox->extendByRange(rv); } return bbox; } // Calculate linearized boundary // Store result in the points-buffer // NOTE: Buffer is allocated here, client should take care of its deletion!!! // void GcCircle::calcLinearizingPoints(int& nof_points, GcPoint**& points, double delta_u) { nof_points = 0; points = NULL; PointList all_points; // NOTE: Start point is added already here // all_points.push_back(data.start); calcLinearizingPoints(data.start_u, data.end_u, delta_u, all_points); // NOTE: End point is added not until here // if ( data.isClosed ) { all_points.push_back(data.start); } else { all_points.push_back(data.end); } //---Collect all points to the result nof_points = all_points.size(); points = new GcPoint*[nof_points]; PointList::iterator itr = all_points.begin(); for (int i = 0; i < nof_points; i++, itr++) { points[i] = *itr; } } // Helper function // void GcCircle::calcLinearizingPoints(double start_u, double end_u, double delta_u, PointList& all_points) { //-If no positive delta_u given, use the default if (delta_u <= 0) { delta_u = deltaU; } //-Create points double pos_u = start_u + delta_u; while (true) { // At end! if ( isEqual(pos_u, end_u) || isGreater(pos_u, end_u)) { break; } double x = data.radius * cos(pos_u) + data.center[0]; double y = data.radius * sin(pos_u) + data.center[1]; double z = 0.0; all_points.push_back(new GcPoint(x, y, z)); pos_u += delta_u; } } void GcCircle::draw(Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id) { const Point3* p1; const Point3* p2; int n; // A pair of consequtive points as a line if ( direction == 1 ) { for (n = 0; n < nofBoundaryPoints-1; n++) { p1 = boundaryPoints[n]->point->getPoint(); p2 = boundaryPoints[n+1]->point->getPoint(); renderer->drawLine(dmode, dstate, 1, p1, p2, elem_id); } } else { for (n = nofBoundaryPoints-1; n > 0; n--) { p1 = boundaryPoints[n]->point->getPoint(); p2 = boundaryPoints[n-1]->point->getPoint(); renderer->drawLine(dmode, dstate, 1, p1, p2, elem_id); } } } #if 0 void GcCircle::draw(Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id) { const Point3* p1; const Point3* p2; int n; // A pair of consequtive points as a line if ( direction == 1 ) { for (n = 0; n < nofLinearizingPoints-1; n++) { p1 = linearizingPoints[n]->getPoint(); p2 = linearizingPoints[n+1]->getPoint(); renderer->drawLine(dmode, dstate, 1, p1, p2, elem_id); } } else { for (n = nofLinearizingPoints-1; n > 0; n--) { p1 = linearizingPoints[n]->getPoint(); p2 = linearizingPoints[n-1]->getPoint(); renderer->drawLine(dmode, dstate, 1, p1, p2, elem_id); } } } #endif #if 0 // Counts the number of intersections with a line which is parallel to // xy-plane and x-axis and which starts from point *startp* towards right. // Returns a structure where there is the nof intersection and // the minimum x-coordinate for the intersections. RayHit* GcCircle::isectionsWithXdir(GcPoint* xdir_startp, bool& negative_on_left) { RayHit* result = new RayHit; negative_on_left = false; result->count = 0; result->min_value = 1.0e+100; int nof_values; double* values; isectionsWithXdir(xdir_startp, nof_values, values, negative_on_left); result->count = nof_values; for (int i = 0; i < nof_values; i++) { if ( isLess(values[i], result->min_value) ) { result->min_value = values[i]; } } if (result->count == 0) { delete result; result = NULL; } delete[] values; return result; } #endif // Counts the number of intersections with a line which is parallel to // xy-plane and x-axis and which starts from point *startp* towards right. // Returns a structure where there is the nof intersection and // the minimum x-coordinate for the intersections. RayHit* GcCircle::isectionsWithXdir(GcPoint* xdir_startp, bool& negative_on_left) { RayHit* result = new RayHit; int index = 0; GcLine* line; while (true) { // No more lines! if ( !getLine(index++, line) ) { break; } bool neg_on_left; RayHit* hits = line->isectionsWithXdir(xdir_startp, neg_on_left); if ( hits != NULL ) { result->count++; result->points.push_back(hits->points.front()); if ( hits->min_value < result->min_value ) { result->min_value = hits->min_value; // NOTE: Negative on left indicator is picked // from the "leftmost" hit, this way we can conclude the // possible loop orientation correctly negative_on_left = neg_on_left; } } delete line; delete hits; } if (result->count == 0) { delete result; result = NULL; } return result; } // Counts the number of intersections with a line which is parallel to // xy-plane and x-axis and which starts from point *startp* towards right. // Returns nof-intersection and the corresponding x-values in the arguments void GcCircle::isectionsWithXdir(GcPoint* xdir_startp, int& nof_values , double*& values) { nof_values = 0; // Intersection point(s): // line_x = center[0] + radius * sin(u) // line_y = center[1] + radius * cos(u) double px = xdir_startp->Pos(X); double py = xdir_startp->Pos(Y); // If no chances! if ( isGreater(py, data.center[1] + data.radius) || isLess(py, data.center[1] - data.radius) ) { return; } values = new double[2]; // Line-y is constant: // cos(u) = (line_y - center[1]) / radius double u1 = asin( (py - data.center[1]) / data.radius ); double u2 = PI - u1; // Other possible solution // X values // ======== if ( !isLess(u1, data.start_u) || !isGreater(u1, data.end_u) ) { values[nof_values++] = data.center[0] + data.radius * cos(u1); } if ( !isLess(u2, data.start_u) || !isGreater(u2, data.end_u) ) { values[nof_values++] = data.center[0] + data.radius * cos(u2); } // Make the nearest intersection point the first if ( nof_values == 2 ) { double d1 = fabs(values[0] - px); double d2 = fabs(values[1] - px); if ( isLess(d2, d1) ) { double tmp = values[0]; values[0] = values[1]; values[1] = tmp; } } } // Counts the number of intersections with a line which is parallel to // xy-plane and y-axis and which starts from point *startp* towards right. // Returns nof-intersection and the corresponding y-values in the arguments void GcCircle::isectionsWithYdir(GcPoint* ydir_startp, int& nof_values , double*& values) { nof_values = 0; // Intersection point(s): // line_x = center[0] + radius * sin(u) // line_y = center[1] + radius * cos(u) double px = ydir_startp->Pos(X); double py = ydir_startp->Pos(Y); // If no chances! if ( isGreater(px, data.center[0] + data.radius) || isLess(px, data.center[0] - data.radius) ) { return; } values = new double[2]; // Line-x is constant: // sin(u) = (line_x - center[0]) / radius double u1 = acos( (px - data.center[0]) / data.radius ); double u2 = -u1; // Other possible solution // Y-values // ======== if ( !isLess(u1, data.start_u) || !isGreater(u1, data.end_u) ) { values[nof_values++] = data.center[1] + data.radius * sin(u1); } if ( !isLess(u2, data.start_u) || !isGreater(u2, data.end_u) ) { values[nof_values++] = data.center[1] + data.radius * sin(u2); } } ostream& GcCircle::output_emf(ostream& out, short indent_size, short indent_level) { const char* def; LibFront::output_scalar(out, indent_size, indent_level, EMF_GEOMETRY, NULL, "Circle", true); if ( nofVertices > 0 ) { LibFront::output_vector(out, indent_size, indent_level, EMF_VERTICES, NULL, nofVertices, vertexTags, false); } def = getMatcString(data.matcTable, EMF_CENTER); if ( model->keepMatcDefinitions() && def != NULL ) { LibFront::output_matcDef(out, indent_size, indent_level, EMF_CENTER, NULL, def); } else { LibFront::output_vector(out, indent_size, indent_level, EMF_CENTER, NULL, 3, data.center, false); } def = getMatcString(data.matcTable, EMF_RADIUS); if ( model->keepMatcDefinitions() && def != NULL ) { LibFront::output_matcDef(out, indent_size, indent_level, EMF_RADIUS, NULL, def); } else { LibFront::output_scalar(out, indent_size, indent_level, EMF_RADIUS, NULL, data.radius); } if ( data.deltaType != LIN_DELTA_NONE && data.delta > 0.0 ) { switch ( data.deltaType ) { case LIN_DELTA_H: LibFront::output_scalar(out, indent_size, indent_level, EMF_DELTA_H, NULL, data.delta); break; case LIN_DELTA_N: LibFront::output_scalar(out, indent_size, indent_level, EMF_DELTA_N, NULL, int(data.delta)); break; case LIN_DELTA_U: LibFront::output_scalar(out, indent_size, indent_level, EMF_DELTA_U, NULL, data.delta); break; } } if ( data.useFixedMeshN ) { LibFront::output_scalar(out, indent_size, indent_level, EMF_USE_MESH_N, NULL, 1); } return out; } // Calculate the point corresponding parametric values given as arguments. // NOTE: Argument parameters are in [0,1], but circle's own parametric // representation is between [0, 2PI] void GcCircle::param2Point(double u_p, double v_p, Point3& point) { double u = data.start_u + u_p * (data.end_u - data.start_u); param2Point_own(u, point); } // Calculate the point corresponding paramtric values given as arguments. // NOTE: Argument parameters are in [0,1], but circle's own parametric // representation is between [0, 2PI] GcPoint* GcCircle::param2Point(double u_p, double v_p) { Point3 pp; double u = data.start_u + u_p * (data.end_u - data.start_u); param2Point_own(u, pp); GcPoint* p = new GcPoint(pp); return p; } // Calculate the point corresponding circle's own paramtric values given as argument. // NOTE: Argument parameters are in [0,2PI] bool GcCircle::param2Point_own(double u, Point3& point) { if (u < data.start_u || u > data.end_u) return false; point[0] = data.radius * cos(u) + data.center[0]; point[1] = data.radius * sin(u) + data.center[1]; point[2] = 0.0; return true; } // Parameter value for the point (0...1) void GcCircle::point2Param(Point3*point, double& u, double& v) { Point3 p; if ( isClosedU() ) { Point3 sp; param2Point(0, 0, sp); diff3(*point, sp, p); } else { diff3(*point, *data.start->getPoint(), p); } double len = length3(p); if ( isZero(len) ) { u = 0.0; } else { // "Center angle" is twice the "arc angle" u = 2 * asin(len / (2 * data.radius)); } if ( p[1] < 0 ) { u = TWO_PI - u; } // Normed 0...1 u = u / (data.end_u - data.start_u); v = 0.0; } // Calculates the paramtetric values corresponding the argument-point. ParamPair* GcCircle::point2Param(GcPoint* point) { double u, v; point2Param(point->getPoint(), u, v); // Point not in the circle if ( u < 0 ) { return NULL; } else { ParamPair* ppair = new ParamPair; ppair->u = u; ppair->v = v; return ppair; } } // NOTE: Do not update data-structure values in this function // This should be called after data-structure values are set!!! // void GcCircle::setDeltaU(enum linDeltaType lin_delta_type, double lin_delta) { double arc_angle = data.end_u - data.start_u; // Max delta-h arc is limited to a half circle double max_angle = min(PI, arc_angle); double max_h = 2 * data.radius * sin(max_angle / 2); double delta_h; int delta_n; double delta_u; // Linearization switch (lin_delta_type) { case LIN_DELTA_H: // Check that given delta-h is not too large delta_h = min(max_h, lin_delta); delta_u = 2 * asin( delta_h / (data.radius * 2) ); break; case LIN_DELTA_N: delta_u = arc_angle / lin_delta; break; case LIN_DELTA_U: delta_u = lin_delta * arc_angle; break; case LIN_DELTA_NONE: default: int n = int(arc_angle / (TWO_PI / 72) + 0.5); delta_u = arc_angle / n; break; } // Make an equidistance division delta_n = int(0.5 + arc_angle / delta_u); // If full circle, we need at least three edges to // linearize it if ( data.isClosed ) { delta_n = (delta_n < 3)?3:delta_n; } deltaU = arc_angle / delta_n; deltaH = 2 * data.radius * sin(0.5 * deltaU); } void GcCircle::setDiscretizationData(int nof_components, linDeltaType* types, double* valuesU, double* valuesV, bool* useFixedN) { if ( nof_components = 0 ) return; data.deltaType = types[0]; data.delta = valuesU[0]; data.useFixedMeshN = useFixedN[0]; // Update also deltaU which is always in radians // setDeltaU(data.deltaType, data.delta); } bool GcCircle::updateData() { UserInterface* gui = (UserInterface*)model->getGui(); strstream strm; // Calc center if not given // ------------------------ // NOTE: We need 2 or 3 points for this, depending if the radius is // given or not! // if (!data.centerGiven) { Point3 *p1, *p2, *p3; p1 = p2 = p3 = NULL; //--Pick the two points anyway needed // // For an arc we can use the two vertices if (!data.isClosed) { p1 = data.start->getPoint(); p2 = data.end->getPoint(); // For a full circle we must have at least two defining points } else if ( data.nofDefiningPoints >= 2 ) { p1 = &(data.definingPoints[0]); p2 = &(data.definingPoints[1]); // ERROR: No way to calculate the Center! } else { strm << "Cannot calculate the circle center!" << ends; gui->showMsg(strm.str()); return false; } //--Next use the radius or a third point // // If radius given, direction and two point is needed if (data.radiusGiven) { circle_center(data.radius, *p1, *p2, data.center); // Otherwise we need the third point (we pick the last defining point for p3, // first two must anyway be given and they were already used!) } else if (data.nofDefiningPoints >= 3 ) { p3 = &(data.definingPoints[data.nofDefiningPoints - 1]); circle_center(*p1, *p2, *p3, data.center); // ERROR: No way to calculate the Center! } else { strm << "Cannot calculate the circle center!" << ends; gui->showMsg(strm.str()); return false; } } // Calc radius if not given // ------------------------ if ( !data.radiusGiven ) { Point3* p = NULL; if ( data.nofDefiningPoints > 0 ) { p = &data.definingPoints[0]; } else if ( data.start != NULL ) { p = data.start->getPoint(); } else if ( data.end != NULL ) { p = data.end->getPoint(); } // ERROR: No way to calculate the Radius! if ( p == NULL ) { strm << "Cannot calculate the circle radius!" << ends; gui->showMsg(strm.str()); return false; } Point3 len; diff3(*p, data.center, len); data.radius = length3(len); } // Set parametrics // --------------- if ( data.radius > 0 ) { //--Circle arc if ( !data.isClosed ) { // Normalize start double start_x = (data.start->Pos(X) - data.center[X]) / data.radius; double start_y = (data.start->Pos(Y) - data.center[Y]) / data.radius; data.start_u = acos(start_x) * (start_y < 0?-1:1); // Normalize end double end_x = (data.end->Pos(X) - data.center[X]) / data.radius; double end_y = (data.end->Pos(Y) - data.center[Y]) / data.radius; data.end_u = acos(end_x) * (end_y < 0?-1:1); if (data.end_u < data.start_u) { data.end_u += TWO_PI; } //--Full circle } else { Point3 p; param2Point(0.0, 0.0, p); data.start = new GcPoint(p); data.end = new GcPoint(p); } // ERROR: Radius is zero! } else { strm << "Circle radius is zero!" << ends; gui->showMsg(strm.str()); return false; } return true; } // Update geometry. Relevant when Matc-parameters have been changed! // bool GcCircle::updateGeometry(int parent_tag, IdList& vertex_tags) { static char buffer[1025]; const char* def; char* val; def = getMatcString(data.matcTable, EMF_CENTER); if ( def != NULL ) { val = mtc_domath((char*)def); if ( val != NULL && val[0] != '\0' && !LibFront::isMatcError(val) ) { strstream strm; strm << val << ends; strm >> data.center[0] >> data.center[1] >> data.center[2]; } } def = getMatcString(data.matcTable, EMF_RADIUS); if ( def != NULL ) { val = mtc_domath((char*)def); if ( val != NULL && val[0] != '\0' && !LibFront::isMatcError(val) ) { strstream strm; strm << val << ends; strm >> data.radius; } } def = getMatcString(data.matcTable, EMF_START_POINT); if ( def != NULL ) { val = mtc_domath((char*)def); if ( val != NULL && val[0] != '\0' && !LibFront::isMatcError(val) ) { data.start->setPos(val); } } def = getMatcString(data.matcTable, EMF_END_POINT); if ( def != NULL ) { val = mtc_domath((char*)def); if ( val != NULL && val[0] != '\0' && !LibFront::isMatcError(val) ) { data.end->setPos(val); } } def = getMatcString(data.matcTable, EMF_MESH_H); if ( def != NULL ) { val = mtc_domath((char*)def); if ( val != NULL && val[0] != '\0' && !LibFront::isMatcError(val) ) { strstream strm; strm << val << ends; strm >> data.delta; } } def = getMatcString(data.matcTable, EMF_MESH_N); if ( def != NULL ) { val = mtc_domath((char*)def); if ( val != NULL && val[0] != '\0' && !LibFront::isMatcError(val) ) { strstream strm; strm << val << ends; strm >> data.delta; } } if ( !updateData() ) return false; setDeltaU(data.deltaType, data.delta); init(true); calcBoundaryPoints(); return true; } //************************** //*****GcLine methods ***** //************************** GcLine::GcLine(ecif_ElementComponent_X& tx, IdList& vertex_tags) { nofVertices = 2; vertexTags = new int[2]; GcPoint** points = new GcPoint*[2]; for (int i = 0; i < 2; i++) { int vtag = tx.vertex_tags[i]; vertexTags[i] = vtag; vertex_tags.push_back(vtag); BodyElement* v = model->getVertexByTag(vtag); points[i] = (GcPoint*)v->getGeometry(); } data.hasVertexTies = true; data.useFixedMeshN = (bool)tx.use_fixed_mesh_n; create(points[0], points[1]); delete[] points; copyMatcValueTable(tx.matcTable, data.matcTable); } // Constructor GcLine::GcLine(BodyElement* vertex1, BodyElement* vertex2) { nofVertices = 2; vertexTags = new int[2]; vertexTags[0] = vertex1->Tag(); vertexTags[1] = vertex2->Tag(); GcPoint* gp1 = (GcPoint*)vertex1->getGeometry(); GcPoint* gp2 = (GcPoint*)vertex2->getGeometry(); data.hasVertexTies = true; create(gp1, gp2); } // Constructor // NOTE: no vertices GcLine::GcLine(Point3* p1, Point3* p2) { GcPoint* gp1 = new GcPoint(p1); GcPoint* gp2 = new GcPoint(p2); create(gp1, gp2); } // Create line void GcLine::create(GcPoint* gp1, GcPoint* gp2) { data.start = gp1; data.end = gp2; updateData(); } #if 0 // Create line void GcLine::create(Point3* p1, Point3* p2) { data.start = new GcPoint(p1); data.end = new GcPoint(p2); Point3 len; diff3(*(data.end->getPoint()), *(data.start->getPoint()), len); data.length = length3(len); data.dir = new GcPoint(len); data.normal[0] = len[0]; data.normal[1] = len[1]; data.normal[2] = len[2]; normalize(data.normal); double tmp = data.normal[0]; data.normal[0] = -data.normal[1]; data.normal[1] = tmp; boundbox = calcBoundBox(); } #endif // Destructor. GcLine::~GcLine() { //delete[] vertexTags; } // Calculates bounding box for the line. BoundBox* GcLine::calcBoundBox() { RangeVector range; range[0] = data.start->Pos(X); range[1] = data.end->Pos(X); range[2] = data.start->Pos(Y); range[3] = data.end->Pos(Y); range[4] = data.start->Pos(Z); range[5] = data.end->Pos(Z); BoundBox* bbox = new BoundBox(range); return bbox; } #if 0 void GcLine::calcLinearizingPoints(int& nof_points_u, int& nof_points_v, GcPoint**& points, double delta_u, double delta_v) { PointList all_points; calcEdgePoints(data.start_u, data.end_u, all_points); //---Add line end-point all_points.push_back(data.end); //---Collect all points to the result nof_points_u = all_points.size(); nof_points_v = 0; points = new GcPoint*[nof_points_u]; PointList::iterator itr = all_points.begin(); for (int i = 0; i < nof_points_u; i++, itr++) { points[i] = *itr; } } #endif #if 0 void GcLine::calcLinearizingPoints(int& nof_points_u, int& nof_points_v, GcPoint**& points, double delta_u, double delta_v) { nof_points_v = 0; if ( nofPatterns == 0 ) { nof_points_u = 2; points = new GcPoint*[2]; points[0] = data.start; points[1] = data.end; return; } // Points with patterns // ==================== PointList all_points; all_points.push_back(data.start); GcPoint* ebase = data.start; calcEdgePointsWithPatterns(this, ebase, nofPatterns, patterns, all_points); //---Remove last point from the list if it at the line end point GcPoint* lastp = *(--all_points.end()); if ( ((*data.end) == *lastp) ) { all_points.pop_back(); } //---Add line end-point all_points.push_back(data.end); //---Collect all points to the result nof_points_u = all_points.size(); points = new GcPoint*[nof_points_u]; PointList::iterator itr = all_points.begin(); for (int i = 0; i < nof_points_u; i++, itr++) { points[i] = *itr; } } #endif void GcLine::draw(Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id) { const Point3* p1; const Point3* p2; p1 = data.start->getPoint(); p2 = data.end->getPoint(); renderer->drawLine(dmode, dstate, direction, p1, p2, elem_id); } void GcLine::getDiscretizationData(int& nof_components, linDeltaType*& types, double*& valuesU, double*& valuesV, bool*& useFixedN) { nof_components = 1; types = NULL; valuesU = NULL; valuesV = NULL; useFixedN = new bool[1]; useFixedN[0] = data.useFixedMeshN; } // Counts the number of intersections with a line which is parallel to // xy-plane and x-axis and which starts from point *startp* towards right. // Returns a structure where there is the nof intersection and // the minimum x-coordinate for the intersections. // (For a line-segment (as this one) nof intersections is of course 0 or 1) // RayHit* GcLine::isectionsWithXdir(GcPoint* xdir_startp, bool& negative_on_left) { // Parameters t,w are solutions for the following equations: // csx + t = clx + klx * w; // csy = cly + kly * w; // csz = clz + kly * w; negative_on_left = false; // Constant parameters for *xdir_startp*-line: double csx = xdir_startp->Pos(X); double csy = xdir_startp->Pos(Y); double csz = xdir_startp->Pos(Z); // Constant parameters for *this*-line: double clx = data.start->Pos(X); double cly = data.start->Pos(Y); double clz = data.start->Pos(Z); // Deflection parameters for *this*-line: double klx = data.dir->Pos(X); double kly = data.dir->Pos(Y); double klz = data.dir->Pos(Z); // Lines are parallel (klx !=0 and kly = 0) if ( ( klx < -EPSILON || klx > EPSILON) && ( kly > -EPSILON && kly < EPSILON) ) { return NULL; } // Intersection-point's domain-parametervalue on *this*-line: double w; if ( kly != 0 ) { w = (csy - cly) / kly; } else { w = 0.0; } // If w not in (0,1), intersection-point can't be on *this*-line. if (w < -EPSILON || w > 1+EPSILON) return NULL; // Intersection-point's domain-parametetrvalue on *xdir_startp*-line. // It should be positive because we are looking only to right: double t = (clx - csx) + klx * w; if (t < -EPSILON ) return NULL; RayHit* result = new RayHit; Point3* p = new Point3[1]; (*p)[0] = clx + klx * w; (*p)[1] = cly + kly * w; (*p)[2] = clz + klz * w; result->count = 1; result->points.push_back(p); result->min_value = csx + t; negative_on_left = kly > 0; return result; } // Counts the number of intersections with a line which is parallel to // xy-plane and x-axis and which starts from point *startp*. // Returns the intersection x-coordinate value in the argument // (For a line-segment (as this one) nof intersections is of course 0 or 1) void GcLine::isectionsWithXdir(GcPoint* xdir_startp, int& nof_values, double*& values) { // Parameters t,w are solution for the following equations: // csx + t = clx + klx * w; // csy = cly + kly * w; // csz = clz + kly * w; nof_values = 0; // Constant parameters for *xdir_startp*-line: double csx = xdir_startp->Pos(X); double csy = xdir_startp->Pos(Y); double csz = xdir_startp->Pos(Z); // Constant parameters for *this*-line: double clx = data.start->Pos(X); double cly = data.start->Pos(Y); double clz = data.start->Pos(Z); // Deflection parameters for *this*-line: double klx = data.dir->Pos(X); double kly = data.dir->Pos(Y); double klz = data.dir->Pos(Z); // Lines are parallel (klx !=0 and kly = 0) if ( !isZero(klx) && isZero(kly) ) { return; } // Intersection-point's domain-parametervalue on *this*-line: double w; if ( !isZero(kly) ) { w = (csy - cly) / kly; } else { w = 0.0; } // If w not in (0,1), intersection-point can't be on *this*-line. if ( isLess(w, 0.0) || isGreater(w, 1.0) ) { return; } // Intersection-point's domain-parametetrvalue on *xdir_startp*-line. double t = (clx - csx) + klx * w; // Set result values nof_values = 1; values = new double[1]; values[0] = csx + t; } // Counts the number of intersections with a line which is parallel to // xy-plane and y-axis and which starts from point *startp*. // Returns the intersection x-coordinate value in the argument // (For a line-segment (as this one) nof intersections is of course 0 or 1) void GcLine::isectionsWithYdir(GcPoint* ydir_startp, int& nof_values, double*& values) { // Parameters t,w are soluition for the following equations: // csx + t = clx + klx * w; // csy = cly + kly * w; // csz = clz + kly * w; nof_values = 0; // Constant parameters for *xdir_startp*-line: double csx = ydir_startp->Pos(X); double csy = ydir_startp->Pos(Y); double csz = ydir_startp->Pos(Z); // Constant parameters for *this*-line: double clx = data.start->Pos(X); double cly = data.start->Pos(Y); double clz = data.start->Pos(Z); // Deflection parameters for *this*-line: double klx = data.dir->Pos(X); double kly = data.dir->Pos(Y); double klz = data.dir->Pos(Z); // Lines are parallel (klx =0 and kly != 0) if ( isZero(klx) && !isZero(kly) ) { return; } // Intersection-point's domain-parametervalue on *this*-line: double w; if ( !isZero(klx) ) { w = (csx - clx) / klx; } else { w = 0.0; } // If w not in (0,1), intersection-point can't be on *this*-line. if ( isLess(w, 0.0) || isGreater(w, 1.0) ) { return; } // Intersection-point's domain-parametetrvalue on *xdir_startp*-line. double t = (cly - csy) + kly * w; // Set result values nof_values = 1; values = new double[1]; values[0] = csy + t; } bool GcLine::isOnSameAxis(GcPoint& p1, GcPoint& p2) { GcPoint dir_12 = p1 - p2; GcPoint dir_1s = p1 - *data.start; return ( dir_12.isParallel(data.dir) && dir_1s.isParallel(data.dir) ); } ostream& GcLine::output_emf(ostream& out, short indent_size, short indent_level) { LibFront::output_vector(out, indent_size, indent_level, "Vertices", NULL, nofVertices, vertexTags, false); if ( data.useFixedMeshN ) { LibFront::output_scalar(out, indent_size, indent_level, EMF_USE_MESH_N, NULL, 1); } return out; } // Calculate the point corresponding the paramtric values given as arguments. void GcLine::param2Point(double u_p, double v_p, Point3& point) { // For line only parametr *u_p* is relevant. point[0] = data.start->Pos(X) + ( u_p * data.dir->Pos(X)); point[1] = data.start->Pos(Y) + ( u_p * data.dir->Pos(Y)); point[2] = data.start->Pos(Z) + ( u_p * data.dir->Pos(Z)); } // Calculate the point corresponding the paramtric values given as arguments. GcPoint* GcLine::param2Point(double u_p, double v_p) { // For line only parametr *u_p* is relevant. double x = data.start->Pos(X) + ( u_p * data.dir->Pos(X)); double y = data.start->Pos(Y) + ( u_p * data.dir->Pos(Y)); double z = data.start->Pos(Z) + ( u_p * data.dir->Pos(Z)); GcPoint* p = new GcPoint(x,y,z); return p; } void GcLine::point2Param(Point3* point, double& u, double& v) { Point3* start = data.start->getPoint(); Point3* end = data.end->getPoint(); // Start point if ( samepoint(*point, *start) ) { u = 0; // End point } else if ( samepoint(*point, *end) ) { u = 1; // Point is possibly within line } else { Point3 len; Point3 part; diff3(*end, *start, len); diff3(*point, *start, part); // We return negative value if the point is not // geometrically on the line Point3 p; cross3(len, part, p); if ( !isZero(length3(p)) ) { u = -1.0; // Now we can pick the parameter value from the first nonzero component. } else if ( !isZero(len[0]) ) { u = part[0] / len[0]; } else if ( !isZero(len[1]) ) { u = part[1] / len[1]; } else { u = 0.0; } } v = 0.0; } // Calculates the paramtetric values corresponding the argument-point. ParamPair* GcLine::point2Param(GcPoint* p) { double u, v; point2Param(p->getPoint(), u, v); // Point not in the line! if ( u < 0 ) { return NULL; } else { // Create the result-object. ParamPair* ppair = new ParamPair; ppair->u = u; ppair->v = v; return ppair; } } void GcLine::setDiscretizationData(int nof_components, linDeltaType* types, double* valuesU, double* valuesV, bool* useFixedN) { if ( nof_components = 0 ) return; data.useFixedMeshN = useFixedN[0]; } bool GcLine::updateData() { Point3 len; diff3(*(data.end->getPoint()), *(data.start->getPoint()), len); data.length = length3(len); data.dir = new GcPoint(len); data.normal[0] = len[0]; data.normal[1] = len[1]; data.normal[2] = len[2]; normalize(data.normal); double tmp = data.normal[0]; data.normal[0] = -data.normal[1]; data.normal[1] = tmp; boundbox = calcBoundBox(); return true; } // Update geometry. Relevant when Matc-parameters have been changed! // bool GcLine::updateGeometry(int parent_tag, IdList& vertex_tags) { return updateData(); } //**************************** //***** GcMulti2D methods **** //**************************** GcMulti2D::GcMulti2D(ecif_Element_X& tx, IdList& vertex_tags) { int i,j; data.nofComponents = tx.nof_components; data.components = new Geometry2D*[data.nofComponents]; int final_nof_cmpnts = 0; for (i = 0; i < data.nofComponents; i++) { data.components[i] = NULL; Geometry2D* ptrGmtr = NULL; switch ( tx.components[i]->gmtr_type ) { case ECIF_CIRCLE: //-Function circle // if ( tx.components[i]->isFunction ) { if ( tx.components[i]->isCpp ) ptrGmtr = createFunctionCircleC(tx.tag, *tx.components[i], vertex_tags); else if (tx.components[i]->isF95 ) ;//ptrGmtr = createFunctionCircleF(tx.tag, *tx.components[i], vertex_tags); else if (tx.components[i]->isMatc ) ptrGmtr = createFunctionCircleM(tx.tag, *tx.components[i], vertex_tags); //-Normal circle // } else { ptrGmtr = new GcCircle(*tx.components[i], vertex_tags); } break; case ECIF_LINE: ptrGmtr = new GcLine(*tx.components[i], vertex_tags); break; case ECIF_POLYLINE: //-Function polyline // if ( tx.components[i]->isFunction ) { if ( tx.components[i]->isCpp ) ptrGmtr = createFunctionPolyLineC(tx.tag, *tx.components[i], vertex_tags); else if (tx.components[i]->isF95 ) ;//ptrGmtr = createFunctionPolyLineF(tx.tag, *tx.components[i], vertex_tags); else if (tx.components[i]->isMatc ) ptrGmtr = createFunctionPolyLineM(tx.tag, *tx.components[i], vertex_tags); //-Normal polyline // } else { ptrGmtr = new GcPolyLine(*tx.components[i], vertex_tags); } break; case ECIF_NURBS: ptrGmtr = new GcNurbsCurve(*tx.components[i], vertex_tags); break; default: ptrGmtr = NULL; break; } // Error in geometry! // if ( ptrGmtr == NULL || !ptrGmtr->geometryIsOk() ) { delete ptrGmtr; geometryOk = false; return; } data.components[i] = ptrGmtr; int ccount = ptrGmtr->getNofComponents(); final_nof_cmpnts += ccount; } // Init other data init(); // Collect all (simple) components into one array // Geometry2D** tmp = new Geometry2D*[final_nof_cmpnts]; data.isDeletable = new bool[final_nof_cmpnts]; int idx = 0; for (i = 0; i < data.nofComponents; i++) { Geometry2D* pg = data.components[i]; // If a component is simple, take as it is // if ( !pg->isMultiGeometry() ) { tmp[idx] = pg; data.isDeletable[idx] = false; idx++; // If a component is a Multi2D, copy its subcomponents! // NOTE: Sub components should have been already unpurged // recursively! // } else { for (j = 0; j < pg->getNofComponents(); j++) { tmp[idx] = (Geometry2D*)pg->getComponent(j); data.isDeletable[idx] = true; idx++; } } } // Store original components as components to be output to // emf file // data.nofEmfComponents = data.nofComponents; data.emfComponents = data.components; // These are components which all are geometry primitives (polylines,circles etc) data.nofComponents = final_nof_cmpnts; data.components = tmp; // Finally linearize and calc boundbox // updateData(); } // Destructor. GcMulti2D::~GcMulti2D() { int i; for (i = 0; i < data.nofComponents; i++) { delete data.components[i]; data.components[i] = NULL; } for (i = 0; i < data.nofEmfComponents; i++) { //delete data.emfComponents[i]; //data.emfComponents[i] = NULL; } } // Calculates bounding box for the line. BoundBox* GcMulti2D::calcBoundBox() { return data.components[0]->calcBoundBox(); } // Calculate linearized boundary void GcMulti2D::calcBoundaryPoints() { for (int i = 0; i < data.nofComponents; i++) { data.components[i]->calcBoundaryPoints(); } } // Calculate linearized boundary // Store result in the points-buffer // NOTE: Buffer is allocated here, client should take care of its // deletion!!! void GcMulti2D::calcLinearizingPoints(int& nof_points, GcPoint**& points, double delta_u) { for (int i = 0; i < data.nofComponents; i++) { data.components[i]->calcLinearizingPoints(nof_points, points, delta_u); } } // ================================================================ // C++-function calls // ================================================================ //=========================== // Create egf function-CIRCLE // ========================== // C++-version // GcMulti2D* GcMulti2D::createFunctionCircleC(int edge_tag, ecif_ElementComponent_X& txc, IdList& vertex_tags) { UserInterface* gui = (UserInterface*)model->getGui(); strstream strm, strm1, strm2; int i,j; bool is_ok = true; Hdll hDLL = NULL; // Handle to DLL library Hfunc hFunc = NULL; // Handle to dll function char* err_msg = NULL; is_ok = loadDllFunction(txc.libraryName, txc.functionName, hDLL, hFunc, err_msg); int nof_circles = 0; egf_Circle* circles = NULL; dllCircleFunc userFunc; if ( is_ok ) { userFunc = (dllCircleFunc)hFunc; } else { strm2 << err_msg << endl; } // Ok, try to call the circle fucntion if (is_ok ) { int rc = userFunc(EGF_CIRCLE, txc.argc, txc.argv, txc.startPoint, txc.endPoint, nof_circles, circles); // Error: function cal failed if ( rc != 0 ) { strm2 << "Function call failed with return code " << rc; is_ok = false; } } if ( is_ok && nof_circles == 0 ) { is_ok = false; strm2 << "Nof circles is zero!"; } // Error // if ( !is_ok ) { strm1 << "***ERROR in C++ circle function for edge " << edge_tag << ends; strm2 << ends; gui->showMsg(strm1.str()); gui->showMsg(strm2.str()); if ( hDLL != NULL ) { closeDllLibrary(hDLL); } return NULL; } GcMulti2D* ptrG = createFunctionCircle(nof_circles, circles, txc, vertex_tags); ptrG->data.funcType = ECIF_CPP; if ( hDLL != NULL ) { closeDllLibrary(hDLL); } if ( ptrG == NULL ) { strm1 << "***ERROR in Front when processing circle function for edge " << edge_tag << ends; gui->showMsg(strm1.str()); return NULL; } return ptrG; } // ============================ // Create egf function-POLYLINE // ============================ // C++-version // GcMulti2D* GcMulti2D::createFunctionPolyLineC(int edge_tag, ecif_ElementComponent_X& txc, IdList& vertex_tags) { UserInterface* gui = (UserInterface*)model->getGui(); strstream strm, strm1, strm2; int i,j; Hdll hDLL = NULL; // Handle to DLL library Hfunc hFunc = NULL; // Handle to dll function char* err_msg = NULL; bool is_ok = loadDllFunction(txc.libraryName, txc.functionName, hDLL, hFunc, err_msg); int nof_polylines = 0; egf_PolyLine* polylines = NULL; dllPolyLineFunc userFunc; if ( is_ok ) { userFunc = (dllPolyLineFunc)hFunc; } else { strm2 << err_msg << endl; } if ( is_ok ) { int rc = userFunc(EGF_POLYLINE, txc.argc, txc.argv, txc.startPoint, txc.endPoint, nof_polylines, polylines); // Error: function call failed if ( rc != 0 ) { strm2 << "Function call failed with return code " << rc; is_ok = false; } } if ( is_ok && nof_polylines == 0 ) { is_ok = false; strm2 << "Nof polylines is zero!"; } // Error in library or function call, stop // ======================================= if ( !is_ok ) { strm1 << "***ERROR in C++ polyline function for edge " << edge_tag << ends; strm2 << ends; gui->showMsg(strm1.str()); gui->showMsg(strm2.str()); if ( hDLL != NULL ) { closeDllLibrary(hDLL); } return NULL; } GcMulti2D* ptrG = createFunctionPolyLine(nof_polylines, polylines, txc, vertex_tags); ptrG->data.funcType = ECIF_CPP; if ( hDLL != NULL ) { closeDllLibrary(hDLL); } if ( ptrG == NULL ) { strm1 << "***ERROR in Front when processing polyline function for edge " << edge_tag << ends; gui->showMsg(strm1.str()); return NULL; } return ptrG; } #if 0 // ================================================================ // Fortan95-function calls // ================================================================ // ========================== // Create egf function-CIRCLE // ========================== // F95-version // GcMulti2D* GcMulti2D::createFunctionCircleF(int edge_tag, ecif_ElementComponent_X& txc, IdList& vertex_tags) { UserInterface* gui = (UserInterface*)model->getGui(); strstream strm, strm1, strm2; int i,j; bool is_ok = true; Hdll hDLL; // Handle to DLL int nof_circles = 0; egf_Circle* circles = NULL; // Load library hDLL = LoadLibrary(txc.libraryName); // Error, library not found // if (hDLL == NULL) { is_ok = false; strm2 << "Cannot open dll-library: " << txc.libraryName; } // Typedef for a safer function call typedef int (Callbackp dllFunc)(int argc, double* argv, egf_Point3* start, egf_Point3* end, int& nof_circles, egf_Circle*& circles); dllFunc userFunc; // Function pointer to the user's function // Try first decorated name (_name@n) strm << "_" << txc.functionName << "@24" << ends; userFunc = (dllFunc)GetProcAddress(hDLL, strm.str()); // Next try undecorated name if ( userFunc == NULL ) { userFunc = (dllFunc)GetProcAddress(hDLL, txc.functionName); } // if (is_ok ) { // Error: function not found if ( userFunc == NULL ) { is_ok = false; strm2 << "Cannot open function " << txc.functionName; // Ok, try to call the function } else { int rc = userFunc(txc.argc, txc.argv, txc.startPoint, txc.endPoint, nof_circles, circles); // Error: function cal failed if ( rc != 0 ) { strm2 << "Function call failed with return code " << rc; is_ok = false; } } } if ( is_ok && nof_circles == 0 ) { is_ok = false; strm2 << "Nof circles is zero!"; } // Error // if ( !is_ok ) { strm1 << "***ERROR in F95 circle function for edge " << edge_tag << ends; strm2 << ends; gui->showMsg(strm1.str()); gui->showMsg(strm2.str()); if ( hDLL != NULL ) { closeDllLibrary(hDLL); } return NULL; } GcMulti2D* ptrG = createFunctionCircle(nof_circles, circles, txc, vertex_tags); ptrG->data.funcType = ECIF_F95; if ( hDLL != NULL ) { closeDllLibrary(hDLL); } if ( ptrG == NULL ) { strm1 << "***ERROR in Front when processing polyline function for edge " << edge_tag << ends; gui->showMsg(strm1.str()); return NULL; } return ptrG; } // ============================ // Create egf function-POLYLINE // ============================ // F95-version // GcMulti2D* GcMulti2D::createFunctionPolyLineF(int edge_tag, ecif_ElementComponent_X& txc, IdList& vertex_tags) { UserInterface* gui = (UserInterface*)model->getGui(); strstream strm, strm1, strm2; int i,j; Hdll hDLL = NULL; // Handle to DLL // Typedef for a safer function call typedef int (Callbackp dllFunc)(int argc, double* argv, egf_Point3* start, egf_Point3* end, int& nof_polylines, egf_PolyLine*& polylines); dllFunc userFunc = NULL; // Function pointer to the user's function int nof_polylines = 0; egf_PolyLine* polylines = NULL; bool is_ok = true; // Load the library hDLL = LoadLibrary(txc.libraryName); // Error, library not found if (hDLL == NULL) { is_ok = false; strm2 << "Cannot open dll-library: " << txc.libraryName; } if ( is_ok ) { // Try first decorated name (_name@n) strm << "_" << txc.functionName << "@24" << ends; userFunc = (dllFunc)GetProcAddress(hDLL, strm.str()); // Next try undecorated name if ( userFunc == NULL ) { userFunc = (dllFunc)GetProcAddress(hDLL, txc.functionName); } } if ( is_ok ) { // Error: function not found if ( userFunc == NULL ) { is_ok = false; strm2 << "Cannot open function " << txc.functionName; // Ok, try to call the function } else { int rc = userFunc(txc.argc, txc.argv, txc.startPoint, txc.endPoint, nof_polylines, polylines); // Error: function call failed if ( rc != 0 ) { strm2 << "Function call failed with return code " << rc; is_ok = false; } } } if ( is_ok && nof_polylines == 0 ) { is_ok = false; strm2 << "Nof polylines is zero!"; } // Error in library or function call, stop // ======================================= if ( !is_ok ) { strm1 << "***ERROR in F95 polyline function for edge " << edge_tag << ends; strm2 << ends; gui->showMsg(strm1.str()); gui->showMsg(strm2.str()); if ( hDLL != NULL ) { closeDllLibrary(hDLL); } return NULL; } GcMulti2D* ptrG = createFunctionPolyLine(nof_polylines, polylines, txc, vertex_tags); ptrG->data.funcType = ECIF_F95; if ( hDLL != NULL ) { closeDllLibrary(hDLL); } if ( ptrG == NULL ) { strm1 << "***ERROR in Front when processing polyline function for edge " << edge_tag << ends; gui->showMsg(strm1.str()); return NULL; } return ptrG; } #endif // ================================================================ // Matc-function calls // ================================================================ // ========================== // Create egf function-CIRCLE // ========================== // Matc-version // GcMulti2D* GcMulti2D::createFunctionCircleM(int edge_tag, ecif_ElementComponent_X& txc, IdList& vertex_tags) { UserInterface* gui = (UserInterface*)model->getGui(); strstream strm, strm1, strm2; char* matc_result = NULL; int i,j; LibFront::initMatcFrmt(); bool is_ok = true; int nof_circles = 0; egf_Circle* circles = NULL; // Check that matc function exists (call help("name") // strm << "help(\""; // Copy function name until first left parnethesis for (i = 0; i < strlen(txc.functionName) ; i++) { char c = txc.functionName[i]; if ( c != '(' ) { strm << c; } else { break; } } strm << "\")" << ends; char* fnm = strm.str(); if ( LibFront::isMatcError(mtc_domath(fnm)) ) { is_ok = false; strm2 << "MATC function: " << txc.functionName << " not defined!"; } // Ok, try to call the function if (is_ok ) { matc_result = mtc_domath(txc.functionName); //xc.argc, txc.argv, txc.startPoint, txc.endPoint, nof_circles, circles); // Error: function call failed if ( matc_result == NULL || matc_result[0] == '\0' ) { strm2 << "***MATC ERROR: no value from circle function call: " << txc.functionName; is_ok = false; } else if ( LibFront::isMatcError(matc_result) ) { LibFront::formatMatcError(matc_result); strm2 << matc_result; is_ok = false; } else { is_ok = getMatcCircleData(matc_result, nof_circles, circles, strm2); } } if ( is_ok && nof_circles == 0 ) { is_ok = false; strm2 << "Nof circles is zero!"; } // Error // if ( !is_ok ) { strm1 << "***ERROR in Matc circle function for edge " << edge_tag << ends; strm2 << ends; gui->showMsg(strm1.str()); gui->showMsg(strm2.str()); return NULL; } GcMulti2D* ptrG = createFunctionCircle(nof_circles, circles, txc, vertex_tags); ptrG->data.funcType = ECIF_MATC; if ( ptrG == NULL ) { strm1 << "***ERROR in Front when processing circle function for edge " << edge_tag << ends; gui->showMsg(strm1.str()); return NULL; } return ptrG; } // ============================ // Create egf function-polyline // ============================ // Matc-version // GcMulti2D* GcMulti2D::createFunctionPolyLineM(int edge_tag, ecif_ElementComponent_X& txc, IdList& vertex_tags) { UserInterface* gui = (UserInterface*)model->getGui(); strstream strm, strm1, strm2; int i,j; char* matc_result = NULL; LibFront::initMatcFrmt(); int nof_polylines = 0; egf_PolyLine* polylines = NULL; bool is_ok = true; // Check that matc function exists (call help("name") // strm << "help(\""; // Copy function name until first left parnethesis for (i = 0; i < strlen(txc.functionName); i++) { char c = txc.functionName[i]; if ( c != '(' ) { strm << c; } else { break; } } strm << "\")" << ends; char* fnm = strm.str(); if ( LibFront::isMatcError(mtc_domath(fnm)) ) { is_ok = false; strm2 << "MATC function: " << txc.functionName << " not defined!"; } // Ok, try to call the polyline function if (is_ok ) { matc_result = mtc_domath(txc.functionName); LibFront::trim(matc_result); //int rc = userFunc(txc.argc, txc.argv, txc.startPoint, txc.endPoint, nof_polylines, polylines); // Error: function call failed if ( matc_result == NULL || matc_result[0] == '\0' ) { strm2 << "***MATC ERROR: no value from polyline function call: " << txc.functionName; is_ok = false; } else if ( LibFront::isMatcError(matc_result) ) { strm2 << matc_result; is_ok = false; } else { is_ok = getMatcPolyLineData(matc_result, nof_polylines, polylines, strm2); } } if ( is_ok && nof_polylines == 0 ) { is_ok = false; strm2 << "Nof polylines is zero!"; } // Error in library or function call, stop // ======================================= if ( !is_ok ) { strm1 << "***ERROR in polyline function for edge " << edge_tag << ends; strm2 << ends; gui->showMsg(strm1.str()); gui->showMsg(strm2.str()); return NULL; } GcMulti2D* ptrG = createFunctionPolyLine(nof_polylines, polylines, txc, vertex_tags); ptrG->data.funcType = ECIF_MATC; if ( ptrG == NULL ) { strm1 << "***ERROR in Front when processing polyline function for edge " << edge_tag << ends; gui->showMsg(strm1.str()); return NULL; } return ptrG; } // Matc circle-function helper // bool GcMulti2D::getMatcCircleData(const char* matc_result, int& nof_circles, egf_Circle*& circles, strstream& msg_strm) { int i,k; nof_circles = 0; circles = NULL; int dim; int radius_given; int center_given; int start_given; int end_given; int vflags_given; strstream strm; strm << matc_result << ends; // These must always be in the matc-result strm >> nof_circles >> dim; strm >> radius_given >> center_given >> start_given >> end_given >> vflags_given; // Not enough common parameter data! // int st = strm.fail(); if ( 0 != strm.fail() ) { msg_strm << "Not enough parameter values for a Matc function circle"; return false; } if ( nof_circles == 0 ) return false; if ( dim < 1 || dim > 3 ) { msg_strm << "Illegal point dimension value for a Matc function circle (" << dim << ")"; return false; } circles = new egf_Circle[nof_circles]; for (i = 0; i < nof_circles; i++) { // Not enough data! // if ( 0 != strm.eof() ) { delete[] circles; circles = NULL; nof_circles = 0; msg_strm << "Not enough data values for a Matc function circle"; return false; } egf_Circle* c = &(circles[i]); if ( 0 != radius_given ) { c->radiusGiven = true; strm >> c->radius; } if ( 0 != center_given ) { c->centerGiven = true; for (k = 0; k < dim; k++) { strm >> c->center[k]; } } if ( 0 != start_given ) { c->startGiven = true; for (k = 0; k < dim; k++) { strm >> c->start[k]; } } if ( 0 != end_given ) { c->endGiven = true; for (k = 0; k < dim; k++) { strm >> c->end[k]; } } if ( 0 != vflags_given ) { strm >> c->vflags[0] >> c->vflags[1]; } // Not enough data! // if ( 0 != strm.fail() ) { delete[] circles; circles = NULL; nof_circles = 0; msg_strm << "Not enough data values for a Matc function circle"; return false; } } return true; } // Matc polyline-function helper // bool GcMulti2D::getMatcPolyLineData(const char* matc_result, int& nof_polylines, egf_PolyLine*& polylines, strstream& msg_strm) { int i,k, nof_points; int dim; int vflags_given; nof_polylines = 0; polylines = NULL; strstream strm; strm << matc_result << ends; // These must always be in the matc-result strm >> nof_polylines >> dim >> vflags_given; // Not enough common parameter data! // if ( 0 != strm.fail() ) { msg_strm << "Not enough parameter values for Matc a function polyline"; return false; } if ( nof_polylines == 0 ) return false; if ( dim < 1 || dim > 3 ) { msg_strm << "Illegal point dimension value for a Matc function polyline (" << dim << ")"; return false; } polylines = new egf_PolyLine[nof_polylines]; // Read all polylines // for (i = 0; i < nof_polylines; i++) { // Not enough data! // if ( strm.eof() ) { delete[] polylines; polylines = NULL; nof_polylines = 0; msg_strm << "Not enough data values for a Matc function polyline"; return false; } egf_PolyLine* c = &(polylines[i]); strm >> nof_points; c->points = new Point3[nof_points]; if ( 0 != vflags_given ) { c->vflags = new int[nof_points]; } // Read all polyline points and possible vertex flags // for (int n = 0; n < nof_points; n++) { for (k = 0; k < dim; k++) { strm >> c->points[n][k]; } if ( 0 != vflags_given ) { strm >> c->vflags[n]; } } if ( 0 != strm.fail() ) { delete[] polylines; polylines = NULL; nof_polylines = 0; msg_strm << "Not enough data values for a Matc function polyline"; return false; } } return true; } // ================================================================ // Common calls // ================================================================ // ============================= // Common create function-circle // ============================= // GcMulti2D* GcMulti2D::createFunctionCircle(int nof_circles, egf_Circle* circles, ecif_ElementComponent_X& txc, IdList& vertex_tags) { // Try to create a new circle element // ---------------------------------- try { ecif_Element_X ntx; init_trx_data(ntx); ntx.tplg_type = ECIF_EDGE; ntx.nof_components = nof_circles; ntx.components = new ecif_ElementComponent_X*[nof_circles]; GcPoint point; int i,k; for (i = 0; i < nof_circles; i++) { // Create new sub-circle ecif_ElementComponent_X* ntxc = new ecif_ElementComponent_X; init_trx_data(*ntxc); ntx.components[i] = ntxc; ntxc->gmtr_type = ECIF_CIRCLE; ntxc->lin_delta_type = txc.lin_delta_type; ntxc->lin_delta[0] = txc.lin_delta[0]; ntxc->lin_delta[1] = txc.lin_delta[1]; ntxc->geometry.edge = new ecif_EdgeGeometry_X; init_trx_data(*(ntxc->geometry.edge)); // Arguments egf_Circle* c = &(circles[i]); ntxc->geometry.edge->radius1 = c->radius; if ( c->centerGiven ) { ntxc->geometry.edge->location = new Point3[1]; for (k = 0; k < 3; k++) { (*ntxc->geometry.edge->location)[k] = c->center[k]; } } if ( c->startGiven ) { ntxc->geometry.edge->start = new Point3[1]; for (k = 0; k < 3; k++) { (*ntxc->geometry.edge->start)[k] = c->start[k]; } } if ( c->endGiven ) { ntxc->geometry.edge->end = new Point3[1]; for (k = 0; k < 3; k++) { (*ntxc->geometry.edge->end)[k] = c->end[k]; } } if ( !c->startGiven || !c->endGiven || isZero(dist3(c->start, c->end)) ) { ntxc->geometry.edge->isClosed = true; } // Store vertex tags if start/end points flagged as vertex ntxc->vertex_tags = new int[2]; ntxc->vertex_tags[0] = NO_INDEX; ntxc->vertex_tags[1] = NO_INDEX; // //-Start point if ( c->startGiven && 0 != c->vflags[0] ) { point.setPos(c->start[0], c->start[1], c->start[2]); BodyElement* v = model->findVertex(&point); //-Create new vertex if needed if ( v == NULL ) { v = new BodyElement1D(&point); model->addBodyElement(v); } ntxc->vertex_tags[0] = v->Tag(); } //-End point if ( c->endGiven && 0 != c->vflags[1] ) { point.setPos(c->end[0], c->end[1], c->end[2]); BodyElement* v = model->findVertex(&point); //-Create new vertex if needed if ( v == NULL ) { v = new BodyElement1D(&point); model->addBodyElement(v); } ntxc->vertex_tags[1] = v->Tag(); } } // all circles // Ok, create new Multi2D geometry from circles GcMulti2D* ptrG = new GcMulti2D(ntx, vertex_tags); if ( !ptrG->geometryIsOk() ) { delete ptrG; return NULL; } ptrG->data.delta = txc.lin_delta[0]; ptrG->data.deltaType = txc.lin_delta_type; ptrG->data.useFixedMeshN = txc.use_fixed_mesh_n; ptrG->data.gmtrType = ECIF_CIRCLE; ptrG->data.functionName = NULL; ptrG->data.libraryName = NULL; update_dyna_string(ptrG->data.functionName, txc.functionName); update_dyna_string(ptrG->data.libraryName, txc.libraryName); ptrG->data.funcArgC = txc.argc; ptrG->data.funcArgV = new double[txc.argc]; for (i = 0; i < txc.argc; i++) { ptrG->data.funcArgV[i] = txc.argv[i]; } copyMatcValueTable(txc.matcTable, ptrG->data.matcTable); reset_trx_data(ntx); return ptrG; } // Error in circle element // ----------------------- catch (...) { return NULL; } } // End createFunctionCircle() // =============================== // Common create function-polyline // =============================== // GcMulti2D* GcMulti2D::createFunctionPolyLine(int nof_polylines, egf_PolyLine* polylines, ecif_ElementComponent_X& txc, IdList& vertex_tags) { int i,j; // Try to create a new polyline element // --------------------------------- try { ecif_Element_X ntx; init_trx_data(ntx); ntx.tplg_type = ECIF_EDGE; ntx.nof_components = nof_polylines; ntx.components = new ecif_ElementComponent_X*[nof_polylines]; GcPoint point; for (i = 0; i < nof_polylines; i++) { // Create new sub-polyline ecif_ElementComponent_X* ntxc = new ecif_ElementComponent_X; init_trx_data(*ntxc); ntx.components[i] = ntxc; egf_PolyLine* c = &(polylines[i]); int nof_points = c->nof_points; ntxc->gmtr_type = ECIF_POLYLINE; ntxc->lin_delta_type = txc.lin_delta_type; ntxc->lin_delta[0] = txc.lin_delta[0]; ntxc->lin_delta[1] = txc.lin_delta[1]; ntxc->geometry.edge = new ecif_EdgeGeometry_X; init_trx_data(*(ntxc->geometry.edge)); if ( isZero(dist3(c->points[0], c->points[nof_points-1])) ) { ntxc->geometry.edge->isClosed = true; } ntxc->geometry.edge->nofDefiningPoints = nof_points; ntxc->geometry.edge->definingPoints = new Point3[nof_points]; ntxc->geometry.edge->pointVertexFlags = new bool[nof_points]; // Count nof vertices int nof_vertices = 0; for (j = 0; j < nof_points; j++) { if ( c->vflags[i] ) nof_vertices++; } ntxc->nof_vertices = nof_vertices; ntxc->vertex_tags = new int[nof_vertices]; // Loop all polyline points // for (j = 0; j < nof_points; j++) { // If point flagged as vertex, store coordinates // also in the point-object (for finding the vertex) for (short k = 0; k < 3; k++) { double p = c->points[j][k]; if ( 1 == c->vflags[i] ) { point.setPosit(k, p); } ntxc->geometry.edge->definingPoints[j][k] = p; } // Store vertex tag if point is flagged as vertex // if ( 1 == c->vflags[j] ) { ntxc->geometry.edge->pointVertexFlags[j] = true; BodyElement* v = model->findVertex(&point); //-Create new vertex if needed if ( v == NULL ) { v = new BodyElement1D(&point); model->addBodyElement(v); } ntxc->vertex_tags[j] = v->Tag(); } else { ntxc->geometry.edge->pointVertexFlags[j] = false; } } // all polyline points } // all polylines // Create new Multi2D elements from polylines GcMulti2D* ptrG = new GcMulti2D(ntx, vertex_tags); ptrG->data.gmtrType = ECIF_POLYLINE; ptrG->data.functionName = NULL; ptrG->data.libraryName = NULL; update_dyna_string(ptrG->data.functionName, txc.functionName); update_dyna_string(ptrG->data.libraryName, txc.libraryName); ptrG->data.funcArgC = txc.argc; ptrG->data.funcArgV = new double[txc.argc]; for (i = 0; i < txc.argc; i++) { ptrG->data.funcArgV[i] = txc.argv[i]; } copyMatcValueTable(txc.matcTable, ptrG->data.matcTable); reset_trx_data(ntx); return ptrG; } // Error in polyline element // ---------------------- catch (...) { return NULL; } } // End createFunctionPolyLine() void GcMulti2D::draw(int gmtr_index, Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id) { if ( gmtr_index < 0 || gmtr_index > data.nofComponents - 1 ) return; Geometry* pg = data.components[gmtr_index]; if ( 1 == pg->getNofComponents() ) { pg->draw(renderer, dmode, dstate, direction, elem_id); } else { pg->draw(gmtr_index, renderer, dmode, dstate, direction, elem_id); } } void GcMulti2D::draw(Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id, bool is_first_loop) { for (int i = 0; i < data.nofComponents; i++) { data.components[i]->draw(renderer, dmode, dstate, direction, elem_id); if ( i < data.nofComponents - 1 ) { renderer->stopDrawingCadBodyElementLoop(); renderer->startDrawingCadBodyElementLoop(is_first_loop); } } } void GcMulti2D::getBoundaryPoints(int& count, BoundaryPoint**& points) { count = getNofBoundaryPoints(); points = new BoundaryPoint*[count]; int index = 0; for (int i = 0; i < data.nofComponents; i++) { int countc; BoundaryPoint** pointsc; data.components[i]->getBoundaryPoints(countc, pointsc); for (int j = 0; j < countc; j++) { points[index++] = pointsc[j]; } delete[] pointsc; pointsc = NULL; } } // NOTE: Argument flags tells if only one of the emf components (ie. components defined // egf- and emf-files) or if the one of the all primitive components should be given // // NOTE: The component can be different is some the emf components are functions which create multiple // primitive components (circles,polylines) // Geometry* GcMulti2D::getComponent(int index, bool only_emf_components) { if ( only_emf_components ) { if ( index < 0 || index > data.nofEmfComponents - 1 ) return NULL; return data.emfComponents[index]; } else { if ( index < 0 || index > data.nofComponents - 1 ) return NULL; return data.components[index]; } } enum linDeltaType GcMulti2D::getDeltaType() { return data.emfComponents[0]->getDeltaType(); } double GcMulti2D::getDeltaU() { return data.emfComponents[0]->getDeltaU(); } void GcMulti2D::getDiscretizationData(int& nof_components, linDeltaType*& types, double*& valuesU, double*& valuesV, bool*& useFixedN) { nof_components = data.nofEmfComponents; types = new linDeltaType[nof_components]; valuesU = new double[nof_components]; useFixedN = new bool[nof_components]; for (int i = 0; i < nof_components; i++) { Geometry* sc = data.emfComponents[i]; types[i] = sc->getDeltaType(); valuesU[i] = sc->getDeltaU(); useFixedN[i] = sc->useFixedMeshN(); } } // NOTE: First simple component defines label's position! // void GcMulti2D::getLabelPoint(Point3& point) { data.components[0]->getLabelPoint(point); } void GcMulti2D::getMifTags(int& nof_tags, int*& tags) { nof_tags = getNofComponents(); tags = new int[nof_tags]; int index = 0; for (int i = 0; i < data.nofComponents; i++) { int nof_tagsc; int* tagsc; data.components[i]->getMifTags(nof_tagsc, tagsc); for (int j = 0; j < nof_tagsc; j++) { tags[index++] = tagsc[j]; } delete[] tagsc; tagsc = NULL; } } int GcMulti2D::getNofBoundaryPoints() { int count = 0; for (int i = 0; i < data.nofComponents; i++) { count += data.components[i]->getNofBoundaryPoints(); } return count; } // NOTE: Argument flags tells if only the nof emf components (ie. components defined // egf- and emf-files) or if the nof all primitive components shouyld be given // // NOTE: This number can be different if some of the emf componets are functions which create multiple // primitive components (circles,polylines) // int GcMulti2D::getNofComponents(bool only_emf_components) { if ( only_emf_components ) { return data.nofEmfComponents; } else { return data.nofComponents; } } ecif_geometryType GcMulti2D::getType() { if ( data.nofComponents < 1 ) { return ECIF_NODIM; } else if ( data.nofComponents > 1 ) { return ECIF_MULTI2D; } else { return data.components[0]->getType(); } } void GcMulti2D::init() { data.nofEmfComponents = 0; data.emfComponents = NULL; data.gmtrType = ECIF_NODIM; data.funcType = ECIF_NOFUNCTION; data.funcArgC = 0; data.funcArgV = NULL; data.funcStartPoint = NULL; data.funcEndPoint = NULL; data.funcStartVertex = NO_INDEX; data.funcEndVertex = NO_INDEX; data.functionName = NULL; data.libraryName = NULL; } bool GcMulti2D::isClosedU() { return data.components[0]->isClosedU(); } // Counts the number of intersections with a line which is parallel to // xy-plane and x-axis and which starts from point *startp* towards right. // Returns a structure where there is the nof intersection and // the minimum x-coordinate for the intersections. RayHit* GcMulti2D::isectionsWithXdir(GcPoint* xdir_startp, bool& negative_on_left) { return data.components[0]->isectionsWithXdir(xdir_startp, negative_on_left); } // Counts the number of intersections with a line which is parallel to // xy-plane and x-axis and which starts from point *startp* towards right. // Returns nof-intersection and the corresponding x-values in the arguments void GcMulti2D::isectionsWithXdir(GcPoint* xdir_startp, int& nof_values , double*& values) { data.components[0]->isectionsWithXdir(xdir_startp, nof_values , values); } // Counts the number of intersections with a line which is parallel to // xy-plane and y-axis and which starts from point *startp* towards right. // Returns nof-intersection and the corresponding y-values in the arguments void GcMulti2D::isectionsWithYdir(GcPoint* ydir_startp, int& nof_values , double*& values) { data.components[0]->isectionsWithYdir(ydir_startp, nof_values , values); } bool GcMulti2D::isOnSameAxis(GcPoint& p1, GcPoint& p2) { if ( data.nofComponents < 1 || data.nofComponents > 1 ) { return false; } else { return data.components[0]->isOnSameAxis(p1, p2); } } ostream& GcMulti2D::output_emf(ostream& out, short indent_size, short indent_level) { for (int i = 0; i < data.nofEmfComponents; i++) { Geometry2D* pg = data.emfComponents[i]; // Simple geometry // if ( !pg->isMultiGeometry() ) { pg->output_emf(out, indent_size, indent_level); // Multi geometry // } else { GcMulti2D* pg = (GcMulti2D*)data.emfComponents[i]; if ( pg->data.functionName != NULL && pg->data.libraryName != NULL ) { pg->output_1_emf(out, indent_size, indent_level); } else { pg->output_n_emf(out, indent_size, indent_level); } } } return out; } ostream& GcMulti2D::output_1_emf(ostream& out, short indent_size, short indent_level) { char* QM = "\""; short is = indent_size; short il = indent_level; const char* def; // Geometry type def = getMatcString(data.matcTable, EMF_GEOMETRY); if ( model->keepMatcDefinitions() && def != NULL ) LibFront::output_matcDef(out, indent_size, indent_level, EMF_GEOMETRY, NULL, def); else if ( data.gmtrType == ECIF_CIRCLE ) LibFront::output_scalar(out, is, il, EMF_GEOMETRY, NULL, "Circle"); else if ( data.gmtrType == ECIF_POLYLINE ) LibFront::output_scalar(out, is, il, EMF_GEOMETRY, NULL, "PolyLine"); // Argument vector if ( data.funcArgC > 0 ) { def = getMatcString(data.matcTable, EMF_ARGUMENTS); if ( model->keepMatcDefinitions() && def != NULL ) LibFront::output_matcDef(out, indent_size, indent_level, EMF_ARGUMENTS, NULL, def); else LibFront::output_vector(out, is, il, EMF_ARGUMENTS, NULL, data.funcArgC, data.funcArgV, false); } // Function definition (Func-name Library-name pair) def = getMatcString(data.matcTable, EMF_FUNCTION); if ( model->keepMatcDefinitions() && def != NULL ) LibFront::output_matcDef(out, indent_size, indent_level, EMF_FUNCTION, NULL, def); else if ( data.functionName != NULL && data.libraryName != NULL ) { LibFront::indent(out, is, il); out << "Function " << QM << data.functionName << QM << " " << QM << data.libraryName << QM << endl; } // Start,end points/vertices if ( data.funcStartPoint != NULL ) { def = getMatcString(data.matcTable, EMF_START_POINT); if ( model->keepMatcDefinitions() && def != NULL ) LibFront::output_matcDef(out, indent_size, indent_level, EMF_START_POINT, NULL, def); else LibFront::output_vector(out, is, il, EMF_START_POINT, NULL, 3, *data.funcStartPoint, false); } if ( data.funcEndPoint != NULL ) { def = getMatcString(data.matcTable, EMF_END_POINT); if ( model->keepMatcDefinitions() && def != NULL ) LibFront::output_matcDef(out, indent_size, indent_level, EMF_END_POINT, NULL, def); else LibFront::output_vector(out, is, il, EMF_END_POINT, NULL, 3, *data.funcEndPoint, false); } if ( data.funcStartVertex != NO_INDEX ) { def = getMatcString(data.matcTable, EMF_START_VERTEX); if ( model->keepMatcDefinitions() && def != NULL ) LibFront::output_matcDef(out, indent_size, indent_level, EMF_START_VERTEX, NULL, def); else LibFront::output_scalar(out, is, il, EMF_START_VERTEX, NULL, data.funcStartVertex); } if ( data.funcEndVertex != NO_INDEX ) { def = getMatcString(data.matcTable, EMF_END_VERTEX); if ( model->keepMatcDefinitions() && def != NULL ) LibFront::output_matcDef(out, indent_size, indent_level, EMF_END_VERTEX, NULL, def); else LibFront::output_scalar(out, is, il, EMF_END_VERTEX, NULL, data.funcEndVertex); } return out; } ostream& GcMulti2D::output_n_emf(ostream& out, short indent_size, short indent_level) { for (int i = 0; i < data.nofComponents; i++) { data.components[i]->output_emf(out, indent_size, indent_level); } return out; } ostream& GcMulti2D::output_mif(ostream& out, const char* header, bool useGmtrMeshN) { for (int i = 0; i < data.nofComponents; i++) { data.components[i]->output_mif(out, header, useGmtrMeshN); } return out; } // Calculate the point corresponding parametric values given as arguments. // NOTE: Argument parameters are in [0,1], but circle's own parametric // representation is between [0, 2PI] void GcMulti2D::param2Point(double u_p, double v_p, Point3& point) { data.components[0]->param2Point(u_p, v_p, point); } // Calculate the point corresponding paramtric values given as arguments. // NOTE: Argument parameters are in [0,1], but circle's own parametric // representation is between [0, 2PI] GcPoint* GcMulti2D::param2Point(double u_p, double v_p) { return data.components[0]->param2Point(u_p, v_p); } // Parameter value for the point (0...1) void GcMulti2D::point2Param(Point3* point, double& u, double& v) { data.components[0]->point2Param(point, u, v); } // Calculates the paramtetric values corresponding the argument-point. ParamPair* GcMulti2D::point2Param(GcPoint* point) { return data.components[0]->point2Param(point); } void GcMulti2D::setDiscretizationData(int nof_components, linDeltaType* types, double* valuesU, double* valuesV, bool* useFixedN) { if ( nof_components != data.nofEmfComponents ) return; for (int i = 0; i < nof_components; i++) { int sub_nof_components = data.emfComponents[i]->getNofComponents(); if ( sub_nof_components > 1 ) { for (int j = 0; j < sub_nof_components; j++) { Geometry* sc = data.emfComponents[i]->getComponent(j); sc->setDiscretizationData(1, &types[i], &valuesU[i], NULL, &useFixedN[i]); } } else { Geometry* sc = data.emfComponents[i]; sc->setDiscretizationData(1, &types[i], &valuesU[i], NULL, &useFixedN[i]); } } } // Copy component's data to a transfer-structure for geoemtry update // // NOTE: By copying the data into a transfer-structure we can use the // same create-circle/polyline functions as for original egf/emf data! // void GcMulti2D::setGeometryUpdateData(ecif_ElementComponent_X& txc, ecif_Multi2D data) { static char func[1024]; const char* def; const char* res; //txc.lin_delta; //txc.lin_delta_type; //txc.nof_vertices; //txc.vertex_tags; //txc.gmtr_type; //txc.geometry; // Function related stuff if ( data.funcType != ECIF_NOFUNCTION ) { txc.isFunction = true; switch (data.funcType) { case ECIF_CPP: txc.isCpp = true; break; case ECIF_F95: txc.isF95 = true; break; case ECIF_MATC: txc.isMatc = true; break; } } def = getMatcString(data.matcTable, EMF_START_POINT); if ( def == NULL ) { txc.startPoint = data.funcStartPoint; } else { res = LibFront::evalMatcString(def); if (!LibFront::isMatcError(res)) { txc.startPoint = create3(res); } } def = getMatcString(data.matcTable, EMF_END_POINT); if ( def == NULL ) { txc.endPoint = data.funcEndPoint; } else { res = LibFront::evalMatcString(def); if (!LibFront::isMatcError(res)) { txc.endPoint = create3(res); } } def = getMatcString(data.matcTable, EMF_START_VERTEX); if ( def == NULL ) { txc.startVertex = data.funcStartVertex; } else { res = LibFront::evalMatcString(def); if (!LibFront::isMatcError(res)) { txc.startVertex = atoi(res); } } def = getMatcString(data.matcTable, EMF_END_VERTEX); if ( def == NULL ) { txc.endVertex = data.funcEndVertex; } else { res = LibFront::evalMatcString(def); if (!LibFront::isMatcError(res)) { txc.endVertex = atoi(res); } } def = getMatcString(data.matcTable, EMF_FUNCTION); if ( def == NULL ) { update_dyna_string(txc.functionName, data.functionName); update_dyna_string(txc.libraryName, data.libraryName); } else { res = LibFront::evalMatcString(def); if (!LibFront::isMatcError(res)) { strstream strm; strm << res << ends; strm >> func; update_dyna_string(txc.functionName, func); if (!strm.eof()) { update_dyna_string(txc.libraryName, strm.str()); } } } def = getMatcString(data.matcTable, EMF_ARGUMENTS); if ( def == NULL ) { txc.argc = data.funcArgC; txc.argv = new double[txc.argc]; for (int i = 0; i < txc.argc; i++) { txc.argv = data.funcArgV; } } else { res = LibFront::evalMatcString(def); if (!LibFront::isMatcError(res)) { strstream strm; strm << LibFront::trim((char*)res) << ends; int count = 0; double value; while (true) { strm >> value; if (0 != strm.fail()) break; count++; } if (count > 0) { txc.argc = count; txc.argv = new double[count]; strstream strm; strm << res << ends; int count = 0; while (true) { strm >> value; if (0 != strm.fail()) break; txc.argv[count++] = value; } txc.argc = count; } } } // Finally copy Matc-expressions copyMatcValueTable(data.matcTable, txc.matcTable); } void GcMulti2D::setMifTag(int& next_tag) { for (int i = 0; i < data.nofComponents; i++) { data.components[i]->setMifTag(next_tag); } } bool GcMulti2D::updateData() { calcBoundaryPoints(); boundbox = calcBoundBox(); return true; } // Update geometry. Relevant when Matc-parameters have been changed! // bool GcMulti2D::updateGeometry(int parent_tag, IdList& vertex_tags) { int i, j; ecif_ElementComponent_X txc; init_trx_data(txc); int final_nof_cmpnts = 0; Geometry2D* newGmtr = NULL; for (i = 0; i < data.nofEmfComponents; i++) { Geometry2D* cmp = data.emfComponents[i]; // Recreate a multi-geometry component (=functions) // ---------------------------------- // if ( cmp->isMultiGeometry() ) { GcMulti2D* oldGmtr = (GcMulti2D*)cmp; reset_trx_data(txc, ECIF_EDGE); //init_trx_data(txc); setGeometryUpdateData(txc, oldGmtr->data); switch ( oldGmtr->data.gmtrType ) { //---Function circle // case ECIF_CIRCLE: if ( oldGmtr->data.funcType == ECIF_CPP ) newGmtr = createFunctionCircleC(parent_tag, txc, vertex_tags); else if ( oldGmtr->data.funcType == ECIF_F95 ) ;//newGmtr = createFunctionCircleF(parent_tag, txc, vertex_tags); else if ( oldGmtr->data.funcType == ECIF_MATC ) newGmtr = createFunctionCircleM(parent_tag, txc, vertex_tags); break; //---Function polyline // case ECIF_POLYLINE: if ( oldGmtr->data.funcType == ECIF_CPP ) newGmtr = createFunctionPolyLineC(parent_tag, txc, vertex_tags); else if ( oldGmtr->data.funcType == ECIF_F95 ) ;//newGmtr = createFunctionPolyLineF(parent_tag, txc, vertex_tags); else if ( oldGmtr->data.funcType == ECIF_MATC ) newGmtr = createFunctionPolyLineM(parent_tag, txc, vertex_tags); break; default: newGmtr = NULL; break; } // Update simple components (and keep it, no copy is made!) // ------------------------ // } else { newGmtr = cmp; newGmtr->updateGeometry(parent_tag, vertex_tags); } // Error in geometry! // if ( newGmtr == NULL || !newGmtr->geometryIsOk() ) { delete newGmtr; geometryOk = false; return false; } data.emfComponents[i] = newGmtr; int ccount = newGmtr->getNofComponents(); final_nof_cmpnts += ccount; } // Each emf-component // Delete old simple geometry // NOTE: old simple emfComponents should not be deleted here, because // they were not copied above!!! // for (i = 0; i < data.nofComponents; i++) { if ( data.isDeletable[i] ) { delete data.components[i]; } } delete[] data.components; delete[] data.isDeletable; data.nofComponents = 0; // Collect all new (simple) components into one array // Geometry2D** tmp = new Geometry2D*[final_nof_cmpnts]; data.isDeletable = new bool[final_nof_cmpnts]; int idx = 0; for (i = 0; i < data.nofEmfComponents; i++) { Geometry2D* pg = data.emfComponents[i]; // If a component is simple, take as it is // if ( !pg->isMultiGeometry() ) { tmp[idx] = pg; data.isDeletable[idx] = false; idx++; // If a component is a Multi2D, copy its subcomponents! // NOTE: Sub components should have been already unpurged // recursively! // } else { for (j = 0; j < pg->getNofComponents(); j++) { tmp[idx] = (Geometry2D*)pg->getComponent(j); data.isDeletable[idx] = true; idx++; } } } // These are components which all are geometry primitves (polylines,circles etc) // data.nofComponents = final_nof_cmpnts; data.components = tmp; return updateData(); } bool GcMulti2D::useFixedMeshN() { // Hack hack hack!!! try { return data.emfComponents[0]->useFixedMeshN(); } catch (...) { return false; } } //******************************* //***** GcNurbsCurve methods ***** //******************************* // Constructor // Emf-style call (In practice, nurbs are not acutally input from emf!) GcNurbsCurve::GcNurbsCurve(ecif_ElementComponent_X& tx, IdList& vertex_tags) { nofVertices = tx.nof_vertices; vertexTags = NULL; if ( nofVertices > 0 ) { vertexTags = new int[nofVertices]; for (int i = 0; i < nofVertices; i++) { BodyElement* v = model->getVertexByTag(tx.vertex_tags[i]); vertex_tags.push_back(v->Tag()); vertexTags[i] = v->Tag(); } } data.deltaType = tx.lin_delta_type; data.delta = tx.lin_delta[0]; data.useFixedMeshN = (bool)tx.use_fixed_mesh_n; create(tx.geometry.edge); copyMatcValueTable(tx.matcTable, data.matcTable); } // Constructor // NOTE: No vertices GcNurbsCurve::GcNurbsCurve(ecif_EdgeGeometry_X* params, bool do_linearize) { nofVertices = 0; vertexTags = NULL; create(params, do_linearize); } // Constructor // Iges/Ideas-style call GcNurbsCurve::GcNurbsCurve(BodyElement* vertex1, BodyElement* vertex2, ecif_EdgeGeometry_X* params, bool do_linearize) { nofVertices = 2; vertexTags = new int[2]; vertexTags[0] = vertex1->Tag(); vertexTags[1] = vertex2->Tag(); create(params, do_linearize); } // Create nurbs curve void GcNurbsCurve::create(ecif_EdgeGeometry_X* params, bool do_linearize) { int i,j; data.degree = params->degree; data.nofKnots = params->nofKnots; data.nofCpoints = params->nofCpoints; data.knots = new double[data.nofKnots]; for (i=0; i < data.nofKnots; i++) data.knots[i] = params->knots[i]; data.cpoints = new Point4[data.nofCpoints]; for (i=0; i < data.nofCpoints; i++) { for(j=0; j < 4; j++) data.cpoints[i][j] = params->cpoints[i][j]; } // Linearization factor deltaU = 1.0 / 36; nofLinearizingPoints = 0; linearizingPoints = NULL; nofBoundaryPoints = 0; boundaryPoints = NULL; if (do_linearize) { linearize(); } boundbox = calcBoundBox(); } // Destructor. GcNurbsCurve::~GcNurbsCurve() { delete[] vertexTags; } // Calculates the bounding box for a nurbs curve. BoundBox* GcNurbsCurve::calcBoundBox() { int i; // We calculate the simple min-max box from control points. // (based on the convex hull proprety of the control polygon for nurbs) RangeVector values; for (i = 0; i < MAX_DIMENSION; i++) { values[2*i] = MAX_RANGE; values[2*i + 1] = MIN_RANGE; } const int DIM2 = 2; // We are in 2D !!!***!!! for (i = 0; i < data.nofCpoints; i++) { for (int k = 0; k < DIM2; k++) { if (data.cpoints[i][k] < values[2*k]) values[2*k] = data.cpoints[i][k]; if (data.cpoints[i][k] > values[2*k + 1]) values[2*k + 1] = data.cpoints[i][k]; } } BoundBox* bbox = new BoundBox(values); return bbox; } // Calculate linearized boundary // Store result in the points-buffer // NOTE: Buffer is allocated here, client should take care of its // deletion!!! // // NOTE: Pure carbage!!! // void GcNurbsCurve::calcLinearizingPoints(int& nof_points, GcPoint**& points, double delta_u) { nof_points = 2; points = new GcPoint*[nof_points]; points[0] = data.start; points[1] = data.end; } void GcNurbsCurve::draw(Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id) { renderer->drawNurbsCrv(dmode, dstate, direction, data, elem_id); } void GcNurbsCurve::getDiscretizationData(int& nof_components, linDeltaType*& types, double*& valuesU, double*& valuesV, bool*& useFixedN) { nof_components = 1; types = new enum linDeltaType[1]; types[0] = data.deltaType; valuesU = new double[1]; valuesU[0] = data.delta; valuesV = NULL; useFixedN = new bool[1]; useFixedN[0] = data.useFixedMeshN; } // Counts the number of intersections with a line which is parallel to // xy-plane and x-axis and which starts from point *startp* towards right. // (For a line-segment (*this*) nof intersections is of course 0 or 1) RayHit* GcNurbsCurve::isectionsWithXdir(GcPoint* xdir_startp, bool& negative_on_left) { // Currently nonsense! !!!***!!! // We create a line from end-points and test with that! GcLine line(data.start->getPoint(), data.end->getPoint()); return line.isectionsWithXdir(xdir_startp, negative_on_left); } void GcNurbsCurve::linearize() { nofLinearizingPoints = 0; delete[] linearizingPoints; linearizingPoints = NULL; calcLinearizingPoints(nofLinearizingPoints, linearizingPoints, deltaU); model->updateMinimumEdgeSize(nofLinearizingPoints, linearizingPoints); } ostream& GcNurbsCurve::output_emf(ostream& out, short indent_size, short indent_level) { return out; } // Calculate the point corresponding paramtric values given as arguments. void GcNurbsCurve::param2Point(double u_p, double v_p, Point3& point) { nurbsCurveValue(&data, u_p, point); } // Calculate the point corresponding paramtric values given as arguments. GcPoint* GcNurbsCurve::param2Point(double u_p, double v_p) { Point3 point; nurbsCurveValue(&data, u_p, point); GcPoint* p = new GcPoint(point); return p; } // Calculates the paramtetric values corresponding the argument-point. void GcNurbsCurve::point2Param(Point3* p, double& u, double& v) { // Currently nearly nonsense! !!!***!!! : // Curve is suppoused to go through first and last control-points! // Only these "end-points" are checked! // Other cases are suppoused to be OFF the curve! Point4& c1 = data.cpoints[0]; Point4& c2 = data.cpoints[data.nofCpoints - 1]; Point3 p1; Point3 p2; for (int i = 0; i < 3; i++) { p1[i] = c1[i]; p2[i] = c2[i]; } //If point doesn't p1 match one of the "end-points" //we return NULL if ( samepoint(*p, p1) ) { u = 0; } else if ( samepoint(*p, p2) ) { u = 1; } else { u = -1.0; } v = 0.0; } // Calculates the paramtetric values corresponding the argument-point. ParamPair* GcNurbsCurve::point2Param(GcPoint* p) { // Currently nearly nonsense! !!!***!!! : // Curve is suppoused to go through first and last control-points! // Only these "end-points" are checked! // Other cases are suppoused to be OFF the curve! double u = 0; Point4& c1 = data.cpoints[0]; Point4& c2 = data.cpoints[data.nofCpoints - 1]; GcPoint p1(c1[0], c1[1], c1[2]); GcPoint p2(c2[0], c2[1], c2[2]); //If point doesn't p1 match one of the "end-points" //we return NULL if (*p == p1) u = 0; else if (*p == p2) u = 1; else return NULL; // Now we can create non-null result-object. ParamPair* par = new ParamPair; par->u = u; par->v = 0; return par; } // Checks if point is on the curve. // Currently nonsense! !!!***!!! ParamPair* GcNurbsCurve::point2Param(GcPoint* p, int direction, double start_u, double start_v) { // Currently nonsense! !!!***!!! ParamPair* par = new ParamPair; par->u = start_u; par->v = start_v; return par; } void GcNurbsCurve::setDiscretizationData(int nof_components, linDeltaType* types, double* valuesU, double* valuesV, bool* useFixedN) { if ( nof_components = 0 ) return; data.deltaType = types[0]; data.delta = valuesU[0]; data.useFixedMeshN = useFixedN[0]; // Update also deltaU which is always in radians // //setDeltaU(data.deltaType, data.delta); } //******************************* //*****GcPolyLine methods ***** //******************************* GcPolyLine::GcPolyLine(ecif_ElementComponent_X& tx, IdList& vertex_tags) { nofVertices = tx.nof_vertices; vertexTags = new int[nofVertices]; int i; for (i = 0; i < nofVertices; i++) { vertexTags[i] = tx.vertex_tags[i]; vertex_tags.push_back(tx.vertex_tags[i]); } GcPoint** points = NULL; int nof_points = tx.geometry.edge->nofDefiningPoints; // Defining points given // --------------------- if ( nof_points > 0 ) { points = new GcPoint*[nof_points]; for (i = 0; i < nof_points; i++) { points[i] = new GcPoint(&tx.geometry.edge->definingPoints[i]); } // Defining vertices given // ----------------------- } else { nof_points = nofVertices; points = new GcPoint*[nof_points]; for (i = 0; i < nofVertices; i++) { BodyElement* v = model->getVertexByTag(tx.vertex_tags[i]); vertexTags[i] = v->Tag(); vertex_tags.push_back(v->Tag()); points[i] = (GcPoint*)v->getGeometry(); } data.hasVertexTies = true; } data.useFixedMeshN = (bool)tx.use_fixed_mesh_n; create(nof_points, points); delete[] points; copyMatcValueTable(tx.matcTable, data.matcTable); } // Constructor. GcPolyLine::GcPolyLine(int nof_points, GcPoint** gc_points) { nofVertices = 0; vertexTags = NULL; create(nof_points, gc_points); } GcPolyLine::GcPolyLine(int nof_vertices, BodyElement** vertices) { nofVertices = nof_vertices; vertexTags = new int[nofVertices]; GcPoint** points = new GcPoint*[nofVertices]; for (int i = 0; i < nofVertices; i++) { BodyElement* v = vertices[i]; vertexTags[i] = v->Tag(); points[i] = (GcPoint*)v->getGeometry(); } data.hasVertexTies = true; create(nofVertices, points); delete[] points; } // Destructor. GcPolyLine::~GcPolyLine() { delete[] vertexTags; } // Create polyline void GcPolyLine::create(int nof_points, GcPoint** points) { data.nofPoints = nof_points; data.points = new GcPoint*[data.nofPoints]; for (int i = 0; i < data.nofPoints; i++) data.points[i] = points[i]; nofBoundaryPoints = 0; boundaryPoints = NULL; updateData(); } // Calculates bounding box for the polyline BoundBox* GcPolyLine::calcBoundBox() { RangeVector range; BoundBox* bbox = new BoundBox(); for (int n = 1; n < data.nofPoints; n++) { // A pair of consequtive points as a line GcPoint* start = data.points[n - 1]; GcPoint* end = data.points[n]; range[0] = start->Pos(X); range[1] = end->Pos(X); range[2] = start->Pos(Y); range[3] = end->Pos(Y); range[4] = start->Pos(Z); range[5] = end->Pos(Z); bbox->extendByRange(range); } return bbox; } void GcPolyLine::calcLinearizingPoints(int& nof_points, GcPoint**& points, double delta_u) { nof_points = data.nofPoints; points = new GcPoint*[data.nofPoints]; for (int i = 0; i < data.nofPoints; i++) { points[i] = data.points[i]; } } void GcPolyLine::draw(Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id) { const Point3* p1; const Point3* p2; // Positive direction: from start to end if ( direction == 1 ) { for (int n = 0; n < data.nofPoints -1; n++) { // A pair of consequtive points as a line p1 = data.points[n]->getPoint(); p2 = data.points[n + 1]->getPoint(); renderer->drawLine(dmode, dstate, 1, p1, p2, elem_id); } // Negative direction: from end to start } else { for (int n = data.nofPoints - 1; n > 0; n--) { // A pair of consequtive points as a line p1 = data.points[n]->getPoint(); p2 = data.points[n - 1]->getPoint(); renderer->drawLine(dmode, dstate, 1, p1, p2, elem_id); } } } void GcPolyLine::getDiscretizationData(int& nof_components, linDeltaType*& types, double*& valuesU, double*& valuesV, bool*& useFixedN) { nof_components = 1; types = NULL; valuesU = NULL; valuesV = NULL; useFixedN = new bool[1]; useFixedN[0] = data.useFixedMeshN; } void GcPolyLine::getLabelPoint(Point3& point) { // Label in the middle of the center segment Point3 p1; Point3 p2; data.points[data.nofPoints/2 - 1]->getPoint(p1); data.points[data.nofPoints/2]->getPoint(p2); point[0] = 0.5 * (p1[0] + p2[0]); point[1] = 0.5 * (p1[1] + p2[1]); point[2] = 0.0; } bool GcPolyLine::getLine(int index, GcLine*& line) { if ( index < 0 || index > getNofLines() - 1) { return false; } Point3* p1 = data.points[index]->getPoint(); Point3* p2 = data.points[index + 1]->getPoint(); line = new GcLine(p1, p2); return true; } bool GcPolyLine::isClosedU() { if ( data.nofPoints > 3 && *data.points[0] == *data.points[data.nofPoints - 1] ) { return true; } else { return false; } } // Counts the number of intersections with a line which is parallel to // xy-plane and x-axis and which starts from point *startp* towards right. // Returns a structure where there is the nof intersection and // the minimum x-coordinate for the intersections. RayHit* GcPolyLine::isectionsWithXdir(GcPoint* xdir_startp, bool& negative_on_left) { RayHit* result = new RayHit; int index = 0; GcLine* line; while (true) { // No more lines! if ( !getLine(index++, line) ) { break; } bool neg_on_left; RayHit* hits = line->isectionsWithXdir(xdir_startp, neg_on_left); if ( hits != NULL ) { result->count++; result->points.push_back(hits->points.front()); if ( hits->min_value < result->min_value ) { result->min_value = hits->min_value; // NOTE: Negative on left indicator is picked // from the "leftmost" hit, this way we can conclude the // possible loop orientation correctly negative_on_left = neg_on_left; } } delete line; delete hits; } if (result->count == 0) { delete result; result = NULL; } return result; } ostream& GcPolyLine::output_emf(ostream& out, short indent_size, short indent_level) { LibFront::output_vector(out, indent_size, indent_level, EMF_VERTICES, NULL, nofVertices, vertexTags, false); if ( data.useFixedMeshN ) { LibFront::output_scalar(out, indent_size, indent_level, EMF_USE_MESH_N, NULL, 1); } return out; } // Calculate the point corresponding the paramtric values given as arguments. // Note param value is n + u_p, where n is line index and u_p is the paramter value // within the line // void GcPolyLine::param2Point(double u_p, double v_p, Point3& point) { point[0] = point[1] = point[2] = 0.0; int index = int(u_p); GcLine* line = NULL; getLine(index, line); if ( line == NULL ) { return; } line->param2Point(u_p - index, v_p, point); delete line; } ParamPair* GcPolyLine::point2Param(GcPoint* p) { GcLine* line = NULL; int index = 0; while (1) { getLine(index++, line); if ( line == NULL ) { break; } ParamPair* pair = line->point2Param(p); if ( pair != NULL ) { return pair; } delete line; } return NULL; } void GcPolyLine::setDiscretizationData(int nof_components, linDeltaType* types, double* valuesU, double* valuesV, bool* useFixedN) { if ( nof_components = 0 ) return; data.useFixedMeshN = useFixedN[0]; } bool GcPolyLine::updateData() { boundbox = calcBoundBox(); return true; } // Update geometry. Relevant when Matc-parameters have been changed! // bool GcPolyLine::updateGeometry(int parent_tag, IdList& vertex_tags) { return updateData(); } //************************************************************************** // Geometry3D methods //************************************************************************** // // NOTE: Badly incomplete (3D Cad geometry not supported!) Geometry3D::Geometry3D() { } Geometry3D::~Geometry3D() { } // Linearize geometry and store points in boundaryPoints array void Geometry3D::calcBoundaryPoints(int boundary_tag) { int i; for (i = 0; i < nofBoundaryPointsU * nofBoundaryPointsV ; i++) { delete boundaryPoints[i]; } delete[] boundaryPoints; nofBoundaryPointsU = 0; nofBoundaryPointsV = 0; boundaryPoints = NULL; int nof_points_u; int nof_points_v; GcPoint** points; double delta_u = getParamDeltaU(); double delta_v = getParamDeltaV(); calcLinearizingPoints(nof_points_u, nof_points_v, points, delta_u, delta_v); int nof_points = 0; nof_points = nof_points_u * nof_points_v; if (nof_points == 0) return; boundaryPoints = new BoundaryPoint*[nof_points]; for (i = 0; i < nof_points; i++) { BoundaryPoint* bp = new BoundaryPoint; boundaryPoints[i] = bp; // Check if bp is an existing vertex! BodyElement* v = model->getVertex(points[i]); if ( v != NULL ) { bp->tag = v->Tag(); bp->vertexTag = v->Tag(); } //bp->boundaryTag = boundary_tag; bp->point = points[i]; } // Handle possibly closed geometry // ------------------------------- int nof_u = nof_points_u; int nof_v = nof_points_v; //-Copy start points to end points if U-closed // if ( isClosedU() ) { for (int i = 1; i <= nof_v; i++) { int pos0 = (i - 1) * nof_u; int pos1 = pos0 + nof_u - 1; BoundaryPoint* tmp = boundaryPoints[pos1]; boundaryPoints[pos1] = boundaryPoints[pos0]; delete tmp; } } //-Copy start points to end points if V-closed // if ( isClosedV() ) { for (int i = 1; i <= nof_u; i++) { int pos0 = (i - 1) * nof_v; int pos1 = pos0 + nof_v - 1; BoundaryPoint* tmp = boundaryPoints[pos1]; boundaryPoints[pos1] = boundaryPoints[pos0]; delete tmp; } } nofBoundaryPointsU = nof_points_u; nofBoundaryPointsV = nof_points_v; // NOTE: Delete only the array,not the points! // delete[] points; } //********************************** //***** GcNurbsSurface methods ***** //********************************** // // NOTE: Badly incomplete (3D Cad geometry not supported!) GcNurbsSurface::GcNurbsSurface(ecif_ElementComponent_X& tx, IdList& vertex_tags) { nofVertices = 0; vertexTags = NULL; copyMatcValueTable(tx.matcTable, data.matcTable); } // Constructor. GcNurbsSurface::GcNurbsSurface(ecif_FaceGeometry_X* params, bool do_linearize) { nofVertices = 0; vertexTags = NULL; create(params, do_linearize); } // Create surface void GcNurbsSurface::create(ecif_FaceGeometry_X* params, bool do_linearize) { int i,j; data.isRational = params->isRational; data.degree_u = params->degree_u; data.nofKnots_u = params->nofKnots_u; data.knots_u = new double[data.nofKnots_u]; for (i=0; i < data.nofKnots_u; i++) data.knots_u[i] = params->knots_u[i]; data.degree_v = params->degree_v; data.nofKnots_v = params->nofKnots_v; data.knots_v = new double[data.nofKnots_v]; for (i=0; i < data.nofKnots_v; i++) data.knots_v[i] = params->knots_v[i]; data.nofCpoints_u = params->nofCpoints_u; data.nofCpoints_v = params->nofCpoints_v; data.nofCpoints = params->nofCpoints; data.cpoints = new Point4[data.nofCpoints]; for (i=0; i < data.nofCpoints; i++) { for(j=0; j < 4; j++) data.cpoints[i][j] = params->cpoints[i][j]; } // Linearization factors deltaU = 1.0 / 36; deltaV = 1.0 / 36; nofLinearizingPointsU = 0; nofLinearizingPointsV = 0; linearizingPoints = NULL; nofBoundaryPointsU = 0; nofBoundaryPointsV = 0; boundaryPoints = NULL; if (do_linearize) { linearize(); } boundbox = calcBoundBox(); } // Destructor. GcNurbsSurface::~GcNurbsSurface() { delete[] vertexTags; } BoundBox* GcNurbsSurface::calcBoundBox() { int i; // We calculate the simple min-max box from control points. // (based on the convex hull proprety of the control polygon for nurbs) RangeVector range; for (i = 0; i < MAX_DIMENSION; i++) { range[2*i] = MAX_RANGE; range[2*i + 1] = MIN_RANGE; } const int DIM3 = 3; // We are in 3D !!!***!!! for (i = 0; i < data.nofCpoints; i++) { for (int k = 0; k < DIM3; k++) { if (data.cpoints[i][k] < range[2*k]) range[2*k] = data.cpoints[i][k]; if (data.cpoints[i][k] > range[2*k + 1]) range[2*k + 1] = data.cpoints[i][k]; } } BoundBox* bbox = new BoundBox(range); return bbox; } // Calculate linearized boundary // Store result in the points-buffer // NOTE: Buffer is allocated here, client should take care of its // deletion!!! // NOTE: Pure carbage!!! void GcNurbsSurface::calcLinearizingPoints(int& nof_points_u, int& nof_points_v, GcPoint**& points, double delta_u, double delta_v) { nof_points_u = 2; nof_points_v = 2; points = new GcPoint*[nof_points_u * nof_points_v]; for (int i = 0; i < nof_points_u * nof_points_v ; i++) { points[i] = data.corners[i]; } } void GcNurbsSurface::draw(Renderer* renderer, objectDrawingMode dmode, objectDrawingState dstate, int direction, int elem_id) { renderer->drawNurbsSrf(dmode, dstate, direction, data, elem_id); } void GcNurbsSurface::linearize() { nofLinearizingPointsU = 0; nofLinearizingPointsV = 0; delete[] linearizingPoints; linearizingPoints = NULL; calcLinearizingPoints(nofLinearizingPointsU, nofLinearizingPointsV, linearizingPoints, deltaU, deltaV); model->updateMinimumEdgeSize(nofLinearizingPointsU * nofLinearizingPointsV, linearizingPoints); } ostream& GcNurbsSurface::output_emf(ostream& out, short indent_size, short indent_level) { return out; } //************************** //*****GcPlane methods ***** //************************** // // NOTE: Badly incomplete (3D Cad geometry not supported!) GcPlane::GcPlane(ecif_ElementComponent_X& tx, IdList& vertex_tags) { nofVertices = 0; vertexTags = NULL; copyMatcValueTable(tx.matcTable, data.matcTable); } // Constructor. GcPlane::GcPlane(int nof_points, GcPoint** points) { nofVertices = 0; vertexTags = NULL; create(nof_points, points); } // Create plane void GcPlane::create(int nof_points, GcPoint** points) { if (nof_points != 4 ) return; for (int i = 0; i < 4; i++ ) { data.corners[i] = points[i]; } boundbox = calcBoundBox(); } // Destructor. GcPlane::~GcPlane() { delete[] vertexTags; } BoundBox* GcPlane::calcBoundBox() { return 0; } ostream& GcPlane::output_emf(ostream& out, short indent_size, short indent_level) { return out; } // ========================================================================== // ========================================================================== // Geometry data structs // ========================================================================== // ========================================================================== // ========================================================================== // 2D classes // ========================================================================== // Struct for circle data // ecif_Circle::ecif_Circle() { init();} ecif_Circle::~ecif_Circle() { if (!hasVertexTies) { delete start; delete end; } purgeMatcValueTable(matcTable); } void ecif_Circle::init() { hasVertexTies = false; center[0] = center[1] = center[2] = 0.0; radius = 0.0; isClosed = true; start = NULL; end = NULL; nofDefiningPoints = 0; definingPoints = NULL; start_u = 0.0; end_u = 0.0; centerGiven = false; radiusGiven = false; delta = 0.0; deltaType = LIN_DELTA_NONE; useFixedMeshN = false; } // Struct for curve data // ecif_Curve::ecif_Curve() { init();} ecif_Curve::~ecif_Curve() { if (!hasVertexTies) { for (int i = 0; i < nofPoints; i++) { delete points[i]; } } delete[] points; delete[] vertex_flags; purgeMatcValueTable(matcTable); } void ecif_Curve::init() { hasVertexTies = false; isClosed = true; nofPoints = 0; points = NULL; vertex_flags = NULL; } // Struct for ellipse data // ecif_Ellipse::ecif_Ellipse() { init();} ecif_Ellipse::~ecif_Ellipse() { if (!hasVertexTies) { delete start; delete end; } purgeMatcValueTable(matcTable); } void ecif_Ellipse::init() { hasVertexTies = false; center[0] = center[1] = center[2] = 0.0; radius1 = 0.0; radius2 = 0.0; isClosed = true; start = NULL; end = NULL; } // Struct for hyperbola data // ecif_Hyperbola::ecif_Hyperbola() { init();} ecif_Hyperbola::~ecif_Hyperbola() { if (!hasVertexTies) { delete start; delete end; } purgeMatcValueTable(matcTable); } void ecif_Hyperbola::init() { hasVertexTies = false; center[0] = center[1] = center[2] = 0.0; direction[0] = direction[1] = direction[2] = 0.0; radius1 = 0.0; radius2 = 0.0; start = NULL; end = NULL; } // Struct for line data // ecif_Line::ecif_Line() { init();} ecif_Line::~ecif_Line() { if (!hasVertexTies) { delete start; delete end; } purgeMatcValueTable(matcTable); } void ecif_Line::init() { hasVertexTies = false; onSymmAxis = 0; normal[0] = normal[1] = normal[2] = 0.0; length = 0.0; start = NULL; end = NULL; dir = NULL; useFixedMeshN = false; } // Struct for multi-geometry data // ecif_Multi2D::ecif_Multi2D() { init();} ecif_Multi2D::~ecif_Multi2D() { delete[] emfComponents; delete[] components; delete[] functionName; delete[] libraryName; purgeMatcValueTable(matcTable); } void ecif_Multi2D::init() { hasVertexTies = false; nofEmfComponents = 0; emfComponents = NULL; nofComponents = 0; isDeletable = NULL; components = NULL; gmtrType = ECIF_NODIM; funcType = ECIF_NOFUNCTION; funcArgC = 0; funcArgV = NULL; funcStartPoint = NULL; funcEndPoint = NULL; funcStartVertex = NO_INDEX; funcEndVertex = NO_INDEX; functionName = NULL; libraryName = NULL; // NOTE: These are valid when there is only one emf component! deltaType = LIN_DELTA_NONE; delta = 0.0; useFixedMeshN = false; } // Struct for nurbs curve data ecif_NurbsCurve::ecif_NurbsCurve() { init();} ecif_NurbsCurve::~ecif_NurbsCurve() { if (!hasVertexTies) { delete start; delete end; } delete[] knots; delete[] cpoints; purgeMatcValueTable(matcTable); } void ecif_NurbsCurve::init() { hasVertexTies = false; isRational = 0; degree = 0; nofKnots = 0; nofCpoints = 0; knots = NULL; cpoints = NULL; start = NULL; end = NULL; useFixedMeshN = false; } // Struct for parabola data // ecif_Parabola::ecif_Parabola() { init();} ecif_Parabola::~ecif_Parabola() { if (!hasVertexTies) { delete start; delete end; } purgeMatcValueTable(matcTable); } void ecif_Parabola::init() { hasVertexTies = false; apex[0] = apex[1] = apex[2] = 0.0; direction[0] = direction[1] = direction[2] = 0.0; focalLength = 0.0; start = NULL; end = NULL; } // Struct for polyline data // ecif_PolyLine::ecif_PolyLine() { init();} ecif_PolyLine::~ecif_PolyLine() { if (!hasVertexTies) { for (int i = 0; i < nofPoints; i++) { delete points[i]; } } delete[] points; purgeMatcValueTable(matcTable); } void ecif_PolyLine::init() { hasVertexTies = false; nofPoints = 0; points = NULL; useFixedMeshN = false; } // Struct for spline curve data // ecif_SplineCurve::ecif_SplineCurve() { init();} ecif_SplineCurve::~ecif_SplineCurve() { if (!hasVertexTies) { delete start; delete end; } delete[] cpoints; purgeMatcValueTable(matcTable); } void ecif_SplineCurve::init() { hasVertexTies = false; degree = 0; nofCpoints = 0; cpoints = NULL; start = NULL; end = NULL; }