| | |
| |
|
| | |
| | |
| | |
| | |
| |
|
| | #include "geometry.h" |
| | using namespace geoff_geometry; |
| |
|
| | #ifdef PEPSPOST |
| | # include "postoutput.h" |
| | #endif |
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | namespace geoff_geometry |
| | { |
| |
|
| | SpanVertex::SpanVertex() |
| | { |
| | for (int i = 0; i < SPANSTORAGE; i++) { |
| | index[i] = NULL; |
| | } |
| | } |
| |
|
| | SpanVertex::~SpanVertex() |
| | { |
| | #ifndef PEPSDLL |
| | |
| | for (int i = 0; i < SPANSTORAGE; i++) { |
| | if (index[i] != NULL) { |
| | delete index[i]; |
| | } |
| | } |
| | #endif |
| | } |
| |
|
| | const SpanVertex& SpanVertex::operator=(const SpanVertex& spv) |
| | { |
| | |
| | if (this == &spv) { |
| | return *this; |
| | } |
| |
|
| | memcpy(x, spv.x, SPANSTORAGE * sizeof(double)); |
| | memcpy(y, spv.y, SPANSTORAGE * sizeof(double)); |
| | memcpy(xc, spv.xc, SPANSTORAGE * sizeof(double)); |
| | memcpy(yc, spv.yc, SPANSTORAGE * sizeof(double)); |
| |
|
| | for (unsigned int i = 0; i < SPANSTORAGE; i++) { |
| | type[i] = spv.type[i]; |
| | spanid[i] = spv.spanid[i]; |
| | index[i] = spv.index[i]; |
| | #ifndef PEPSDLL |
| | if (index[i] != NULL) { |
| | SpanDataObject* obj = new SpanDataObject(index[i]); |
| | index[i] = obj; |
| | } |
| | #endif |
| | } |
| | return *this; |
| | } |
| |
|
| |
|
| | void SpanVertex::Add(int offset, int spantype, const Point& p, const Point& pc, int ID) |
| | { |
| | type[offset] = spantype; |
| | |
| | x[offset] = p.x; |
| | y[offset] = p.y; |
| | xc[offset] = pc.x; |
| | yc[offset] = pc.y; |
| | spanid[offset] = ID; |
| | } |
| | void SpanVertex::AddSpanID(int offset, int ID) |
| | { |
| | spanid[offset] = ID; |
| | } |
| |
|
| | #if PEPSDLL |
| | void SpanVertex::Add(int offset, WireExtraData* Index) |
| | { |
| | index[offset] = Index; |
| | } |
| | WireExtraData* SpanVertex::Get(int offset) |
| | { |
| | return index[offset]; |
| | } |
| | #else |
| | void SpanVertex::Add(int offset, const SpanDataObject* Index) |
| | { |
| | index[offset] = Index; |
| | } |
| |
|
| | const SpanDataObject* SpanVertex::GetIndex(int offset) const |
| | { |
| | return index[offset]; |
| | } |
| | #endif |
| |
|
| | int SpanVertex::Get(int offset, Point& pe, Point& pc) |
| | { |
| | pe = Point(x[offset], y[offset]); |
| | pc = Point(xc[offset], yc[offset]); |
| |
|
| | return type[offset]; |
| | } |
| | int SpanVertex::GetSpanID(int offset) |
| | { |
| | return spanid[offset]; |
| | } |
| |
|
| | Span Span::Offset(double offset) |
| | { |
| | Span Offsp = *this; |
| | if (FNEZ(offset) && !NullSpan) { |
| | if (!dir) { |
| | |
| | Offsp.p0.x -= offset * vs.gety(); |
| | Offsp.p0.y += offset * vs.getx(); |
| |
|
| | Offsp.p1.x -= offset * vs.gety(); |
| | Offsp.p1.y += offset * vs.getx(); |
| | } |
| | else { |
| | |
| | |
| | Offsp.p0.x -= vs.gety() * offset; |
| | Offsp.p0.y += vs.getx() * offset; |
| |
|
| | Offsp.p1.x -= ve.gety() * offset; |
| | Offsp.p1.y += ve.getx() * offset; |
| |
|
| | |
| | } |
| | Offsp.SetProperties(true); |
| | } |
| | return Offsp; |
| | } |
| |
|
| | bool Span::JoinSeparateSpans(Span& sp) |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | Point inters; |
| | int turnLeft = ((this->ve ^ sp.vs) > 0) ? 1 : -1; |
| | if (!this->dir) { |
| | CLine one(*this); |
| | if (!sp.dir) { |
| | |
| | CLine two(sp); |
| | inters = one.Intof(two); |
| | } |
| | else { |
| | |
| | Circle two(sp); |
| | inters = one.Intof(-turnLeft * sp.dir, two); |
| | } |
| | } |
| | else { |
| | Circle one(*this); |
| | if (!sp.dir) { |
| | |
| | CLine two(sp); |
| | inters = two.Intof(turnLeft * this->dir, one); |
| | } |
| | else { |
| | |
| | Circle two(sp); |
| | inters = one.Intof(-turnLeft * this->dir * sp.dir, two); |
| | } |
| | } |
| | if (inters.ok) { |
| | this->p1 = sp.p0 = inters; |
| | this->SetProperties(true); |
| | sp.SetProperties(true); |
| | } |
| | return inters.ok; |
| | } |
| | static int Split(double tolerance, double angle, double radius, int dir); |
| | int Span::Split(double tolerance) |
| | { |
| | |
| | if (!returnSpanProperties) { |
| | this->SetProperties(true); |
| | } |
| | return geoff_geometry::Split(tolerance, angle, radius, dir); |
| | } |
| | #if 0 |
| | int Span3d::Split(double tolerance) { |
| | |
| | if(!returnSpanProperties) |
| | this->SetProperties(true); |
| | return geoff_geometry::Split(tolerance, angle, radius, dir); |
| | } |
| | #endif |
| | static int Split(double tolerance, double angle, double radius, int dir) |
| | { |
| | if (dir == LINEAR) { |
| | return 0; |
| | } |
| | double cosa = 1 - tolerance / radius; |
| | if (cosa > NEARLY_ONE) { |
| | cosa = NEARLY_ONE; |
| | } |
| | cosa = 2 * cosa * cosa - 1; |
| | double sina = sqrt(1 - cosa * cosa) * dir; |
| | double tempang = atan2(sina, cosa); |
| | int num_vectors = (int)(fabs(angle / tempang)) + 1; |
| | return num_vectors; |
| | } |
| |
|
| | void Span::SplitMatrix(int num_vectors, Matrix* matrix) |
| | { |
| | |
| | matrix->Unit(); |
| | if (dir) { |
| | |
| | double incang = angle / (double)num_vectors; |
| |
|
| | matrix->Translate(-pc.x, -pc.y, 0); |
| | matrix->Rotate(incang, 3); |
| | matrix->Translate(pc.x, pc.y, 0); |
| | } |
| | else { |
| | |
| | matrix->Translate(length / num_vectors * vs.getx(), length / num_vectors * vs.gety(), 0); |
| | } |
| | } |
| |
|
| | #if 0 |
| | void Span3d::SplitMatrix(int num_vectors, Matrix* matrix) { |
| | |
| | matrix->Unit(); |
| | if(dir) { |
| | |
| | if(normal.getz() <= NEARLY_ONE) FAILURE(getMessage(L"Unfinished coding - contact the Company", GENERAL_MESSAGES, MES_UNFINISHEDCODING)); |
| | double incang = angle / (double) num_vectors ; |
| |
|
| | matrix->Translate(-pc.x, -pc.y, -pc.z); |
| | matrix->Rotate(incang, 3); |
| | matrix->Translate(pc.x, pc.y, pc.z); |
| | } else { |
| | |
| | double d = length / num_vectors; |
| | matrix->Translate(d * vs.getx(), d * vs.gety(), d * vs.getz()); |
| | } |
| | } |
| | #endif |
| |
|
| | void Span::minmax(Box& box, bool start) |
| | { |
| | minmax(box.min, box.max, start); |
| | } |
| | #if 0 |
| | void Span3d::minmax(Box3d& box, bool start) { |
| | minmax(box.min, box.max, start); |
| | } |
| | #endif |
| | void Span::minmax(Point& min, Point& max, bool start) |
| | { |
| | |
| | if (start) { |
| | MinMax(p0, min, max); |
| | } |
| | MinMax(p1, min, max); |
| |
|
| | if (dir) { |
| | |
| | double dx1 = p1.x - p0.x; |
| | double dy1 = p1.y - p0.y; |
| |
|
| | double dx = pc.x - p0.x; |
| | double dy = pc.y - p0.y; |
| |
|
| | double dx0 = dx + radius; |
| |
|
| | if (dir * (dx0 * dy1 - dx1 * dy) > 0) { |
| | if (pc.x + radius > max.x) { |
| | max.x = pc.x + radius; |
| | } |
| | } |
| | dx0 = dx - radius; |
| | if (dir * (dx0 * dy1 - dx1 * dy) > 0) { |
| | if (pc.x - radius < min.x) { |
| | min.x = pc.x - radius; |
| | } |
| | } |
| | double dy0 = dy + radius; |
| | if (dir * (dx * dy1 - dx1 * dy0) > 0) { |
| | if (pc.y + radius > max.y) { |
| | max.y = pc.y + radius; |
| | } |
| | } |
| |
|
| | dy0 = dy - radius; |
| | if (dir * (dx * dy1 - dx1 * dy0) > 0) { |
| | if (pc.y - radius < min.y) { |
| | min.y = pc.y - radius; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | #if 0 |
| | void Span3d::minmax(Point3d& min, Point3d& max, bool start) { |
| | |
| | if(start) { |
| | MinMax(p0, min, max); |
| | } |
| | MinMax(p1, min, max); |
| |
|
| | if(dir) { |
| | |
| | double dx1 = p1.x - p0.x; |
| | double dy1 = p1.y - p0.y; |
| |
|
| | double dx = pc.x - p0.x; |
| | double dy = pc.y - p0.y; |
| |
|
| | double dx0 = dx + radius; |
| |
|
| | if( dir * (dx0 * dy1 - dx1 * dy) > 0) { |
| | if(pc.x + radius > max.x) max.x = pc.x + radius; |
| | } |
| | dx0 = dx - radius; |
| | if( dir * (dx0 * dy1 - dx1 * dy) > 0) { |
| | if(pc.x - radius < min.x) min.x = pc.x - radius; |
| | } |
| | double dy0 = dy + radius; |
| | if( dir * (dx * dy1 - dx1 * dy0) > 0) { |
| | if(pc.y + radius > max.y) max.y = pc.y + radius; |
| | } |
| |
|
| | dy0 = dy - radius; |
| | if( dir * (dx * dy1 - dx1 * dy0) > 0) { |
| | if(pc.y - radius < min.y) min.y = pc.y - radius; |
| | } |
| | } |
| | } |
| | #endif |
| |
|
| | int Span::Intof(const Span& sp, Point& pInt1, Point& pInt2, double t[4]) const |
| | { |
| | |
| | return geoff_geometry::Intof(*this, sp, pInt1, pInt2, t); |
| | } |
| |
|
| | Point Span::Near(const Point& p) const |
| | { |
| | |
| | if (this->dir == LINEAR) { |
| | double t; |
| | t = (Vector2d(this->p0, p) * this->vs); |
| | return this->vs * t + this->p0; |
| | } |
| | else { |
| | double r = p.Dist(this->pc); |
| | if (r < geoff_geometry::TOLERANCE) { |
| | return (p.Dist(this->p0) < p.Dist(this->p1)) ? this->p0 : this->p1; |
| | } |
| | return (p.Mid(this->pc, (r - this->radius) / r)); |
| | } |
| | } |
| | Point Span::NearOn(const Point& p) const |
| | { |
| | |
| | Point pn; |
| | pn = Near(p); |
| | if (this->OnSpan(pn)) { |
| | return pn; |
| | } |
| |
|
| | |
| | return (pn.Dist(p0) < pn.Dist(p1)) ? p0 : p1; |
| | } |
| |
|
| | void Span::Transform(const Matrix& m, bool setprops) |
| | { |
| | p0 = p0.Transform(m); |
| | p1 = p1.Transform(m); |
| | if (dir != LINEAR) { |
| | pc = pc.Transform(m); |
| | if (m.m_mirrored == -1) { |
| | FAILURE(L"Don't know mirror - use IsMirrored method on object"); |
| | } |
| | if (m.m_mirrored) { |
| | dir = -dir; |
| | } |
| | } |
| | if (setprops) { |
| | SetProperties(true); |
| | } |
| | } |
| |
|
| | #if 0 |
| | void Span3d::Transform(const Matrix& m, bool setprops) { |
| | p0 = p0.Transform(m); |
| | p1 = p1.Transform(m); |
| | if(dir != LINEAR) { |
| | pc = pc.Transform(m); |
| | normal.Transform(m); |
| | if(m.m_mirrored == -1) FAILURE(L"Don't know mirror - use IsMirrored method on object"); |
| | if(m.m_mirrored) dir = -dir; |
| | } |
| | if(setprops) |
| | SetProperties(true); |
| | } |
| | #endif |
| |
|
| | Point Span::Mid() const |
| | { |
| | |
| |
|
| | return geoff_geometry::Mid(*this); |
| | } |
| |
|
| |
|
| | Point Span::MidPerim(double d) const |
| | { |
| | |
| | Point p; |
| | if (this->dir == LINEAR) { |
| | p = this->vs * d + this->p0; |
| | } |
| | else { |
| | Vector2d v(pc, p0); |
| | v.Rotate(d * dir / this->radius); |
| | p = v + pc; |
| | } |
| | return p; |
| | } |
| |
|
| | Point Span::MidParam(double param) const |
| | { |
| | |
| | if (fabs(param) < 0.00000000000001) { |
| | return p0; |
| | } |
| | if (fabs(param - 1.0) < 0.00000000000001) { |
| | return p1; |
| | } |
| | return MidPerim(param * this->length); |
| | } |
| |
|
| | Vector2d Span::GetVector(double fraction) const |
| | { |
| | |
| | if (dir == 0) { |
| | Vector2d v(p0, p1); |
| | v.normalise(); |
| | return v; |
| | } |
| |
|
| | Point p = MidParam(fraction); |
| | Vector2d v(pc, p); |
| | v.normalise(); |
| | if (dir == ACW) { |
| | return Vector2d(-v.gety(), v.getx()); |
| | } |
| | else { |
| | return Vector2d(v.gety(), -v.getx()); |
| | } |
| | } |
| |
|
| | Kurve::Kurve(const Kurve& k) |
| | : Matrix() |
| | { |
| | |
| | this->m_nVertices = k.m_nVertices; |
| | memcpy(this->e, k.e, 16 * sizeof(double)); |
| | this->m_unit = k.m_unit; |
| | this->m_mirrored = k.m_mirrored; |
| | this->m_isReversed = k.m_isReversed; |
| | this->m_started = k.m_started; |
| | for (unsigned int i = 0; i < k.m_spans.size(); i++) { |
| | SpanVertex* spv = new SpanVertex; |
| | *spv = *k.m_spans[i]; |
| | this->m_spans.push_back(spv); |
| | } |
| | } |
| |
|
| | const Kurve& Kurve::operator=(const Kurve& k) |
| | { |
| | if (this == &k) { |
| | return *this; |
| | } |
| |
|
| | memcpy(e, k.e, 16 * sizeof(double)); |
| | m_unit = k.m_unit; |
| | m_mirrored = k.m_mirrored; |
| | m_isReversed = k.m_isReversed; |
| |
|
| | this->Clear(); |
| |
|
| | if (k.m_nVertices) { |
| | m_started = true; |
| | } |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | for (unsigned int i = 0; i < k.m_spans.size(); i++) { |
| | SpanVertex* spv = new SpanVertex; |
| | *spv = *k.m_spans[i]; |
| | this->m_spans.push_back(spv); |
| | } |
| | m_nVertices = k.m_nVertices; |
| | return *this; |
| | } |
| |
|
| | #if 0 |
| |
|
| | Kurve::Kurve(Kurve& k) :Matrix(){ |
| | *this = k; |
| | return; |
| | *this = Matrix(k); |
| |
|
| | Point p, pc; |
| | m_nVertices = 0; |
| |
|
| | for(int i = 0; i < k.m_nVertices; i++) { |
| | int spantype = k.Get(i, p, pc); |
| | int spanid = k.GetSpanID(i); |
| | if(Add(spantype, p, pc)) this->AddSpanID(spanid); |
| | } |
| | if(k.m_nVertices) m_started = true; |
| | } |
| |
|
| | const Kurve& Kurve::operator=( Kurve &k) |
| | { |
| | *this = Matrix(k); |
| |
|
| | Point p, pc; |
| | this->Clear(); |
| | m_isReversed = k.m_isReversed; |
| |
|
| | for(int i = 0; i < k.m_nVertices; i++) { |
| | int spantype = k.Get(i, p, pc); |
| | int spanid = k.GetSpanID(i); |
| | if(Add(spantype, p, pc)) this->AddSpanID(spanid); |
| | } |
| | if(k.m_nVertices) m_started = true; |
| | return *this; |
| | } |
| | #endif |
| |
|
| | const Kurve& Kurve::operator=(const Matrix& m) |
| | { |
| | |
| | |
| |
|
| | for (int i = 0; i < 16; i++) { |
| | e[i] = m.e[i]; |
| | } |
| | m_unit = m.m_unit; |
| | m_mirrored = m.m_mirrored; |
| | return *this; |
| | } |
| |
|
| | Kurve::~Kurve() |
| | { |
| | this->Clear(); |
| | } |
| |
|
| |
|
| | bool Kurve::Closed() const |
| | { |
| | |
| | if (m_nVertices > 1) { |
| | Point ps, pe, pc; |
| | Get(0, ps, pc); |
| | Get(m_nVertices - 1, pe, pc); |
| | return (ps == pe); |
| | } |
| | else { |
| | return false; |
| | } |
| | } |
| |
|
| | void Kurve::FullCircle(int dir, const Point& c, double radius) |
| | { |
| | |
| | |
| | this->Clear(); |
| | Point ps = c; |
| | ps.x = c.x + radius; |
| | this->Start(ps); |
| | this->AddSpanID(FULL_CIRCLE_KURVE); |
| | ps.x = c.x - radius; |
| | this->Add(dir, ps, c, true); |
| | ps.x = c.x + radius; |
| | this->Add(dir, ps, c, true); |
| | } |
| |
|
| | void Kurve::Start() |
| | { |
| | if (m_started) { |
| | this->Clear(); |
| | } |
| | m_started = true; |
| | } |
| |
|
| |
|
| | void Kurve::Start(const Point& p) |
| | { |
| | Start(); |
| | Add(0, p, Point(0, 0)); |
| | } |
| |
|
| | bool Kurve::Add(const Span& sp, bool AddNullSpans) |
| | { |
| | |
| | if (!this->m_started) { |
| | this->Start(sp.p0); |
| | } |
| | if (this->Add(sp.dir, sp.p1, sp.pc, AddNullSpans)) { |
| | this->AddSpanID(sp.ID); |
| | return true; |
| | } |
| | return false; |
| | } |
| |
|
| | bool Kurve::Add(const spVertex& spv, bool AddNullSpans) |
| | { |
| | if (Add(spv.type, spv.p, spv.pc, AddNullSpans)) { |
| | AddSpanID(spv.spanid); |
| | return true; |
| | } |
| | return false; |
| | } |
| |
|
| | bool Kurve::Add(int span_type, const Point& p0, const Point& pc, bool AddNullSpans) |
| | { |
| | |
| | #ifdef _DEBUG |
| | |
| | #endif |
| |
|
| | if (!m_started) { |
| | Start(p0); |
| | return true; |
| | } |
| |
|
| | if (m_nVertices) { |
| | |
| | |
| | Point pv, pcc; |
| | Get(m_nVertices - 1, pv, pcc); |
| | if (pv.Dist(p0) < geoff_geometry::TOLERANCE) { |
| | if (!AddNullSpans) { |
| | return false; |
| | } |
| | span_type = LINEAR; |
| | } |
| | } |
| |
|
| | SpanVertex* p; |
| | if (m_nVertices % SPANSTORAGE == 0) { |
| | p = new SpanVertex; |
| | m_spans.push_back(p); |
| | } |
| | else { |
| | p = (SpanVertex*)m_spans[m_nVertices / SPANSTORAGE]; |
| | } |
| |
|
| | p->Add(m_nVertices % SPANSTORAGE, span_type, p0, pc); |
| | m_nVertices++; |
| | return true; |
| | } |
| | void Kurve::AddSpanID(int ID) |
| | { |
| | |
| | int vertex = this->m_nVertices - 1; |
| | SpanVertex* p = (SpanVertex*)m_spans[vertex / SPANSTORAGE]; |
| | p->AddSpanID(vertex % SPANSTORAGE, ID); |
| | } |
| |
|
| | void Kurve::Add() |
| | { |
| | |
| | if (m_nVertices == 0) { |
| | FAILURE(L"Invalid attempt to add null span - no start"); |
| | } |
| | Point p, pc; |
| | Get(m_nVertices - 1, p, pc); |
| | Add(p, true); |
| | } |
| |
|
| | bool Kurve::Add(const Point& p0, bool AddNullSpans) |
| | { |
| | return Add(0, p0, Point(0, 0), AddNullSpans); |
| | } |
| |
|
| |
|
| | void Kurve::Add(const Kurve* k, bool AddNullSpans) |
| | { |
| | Span sp; |
| | Matrix m; |
| | if (!this->m_unit) { |
| | m = *k; |
| | Matrix im = this->Inverse(); |
| | m.Multiply(im); |
| | m.IsUnit(); |
| | } |
| | for (int i = 1; i <= k->nSpans(); i++) { |
| | k->Get(i, sp, false, this->m_unit); |
| | #ifndef PEPSDLL |
| | const SpanDataObject* obj = k->GetIndex(i - 1); |
| | #endif |
| | if (!this->m_unit) { |
| | sp.Transform(m); |
| | } |
| |
|
| | if (i == 1) { |
| | |
| | bool AddFirstVertex = true; |
| | if (nSpans()) { |
| | Span spLast; |
| | Get(nSpans(), spLast, false, false); |
| | if (spLast.p1.Dist(sp.p0) <= geoff_geometry::TOLERANCE) { |
| | AddFirstVertex = false; |
| | } |
| | } |
| | if (AddFirstVertex) { |
| | Add(sp.p0, AddNullSpans); |
| | #ifndef PEPSDLL |
| | if (obj != NULL) { |
| | SpanDataObject* objnew = new SpanDataObject(obj); |
| | AddIndex(nSpans() - 1, objnew); |
| | } |
| | #endif |
| | } |
| | } |
| |
|
| | Add(sp.dir, sp.p1, sp.pc, AddNullSpans); |
| | #ifndef PEPSDLL |
| | if (obj != NULL) { |
| | SpanDataObject* objnew = new SpanDataObject(obj); |
| | AddIndex(nSpans() - 1, objnew); |
| | } |
| | #endif |
| | } |
| | } |
| |
|
| | void Kurve::Replace(int vertexnumber, const spVertex& spv) |
| | { |
| | |
| | Replace(vertexnumber, spv.type, spv.p, spv.pc, spv.spanid); |
| | } |
| |
|
| |
|
| | void Kurve::Replace(int vertexnumber, int type, const Point& p0, const Point& pc, int ID) |
| | { |
| | |
| | #ifdef _DEBUG |
| | if (vertexnumber > m_nVertices) { |
| | FAILURE(getMessage(L"Kurve::Replace - vertexNumber out of range")); |
| | } |
| | #endif |
| | SpanVertex* p = (SpanVertex*)m_spans[vertexnumber / SPANSTORAGE]; |
| | p->Add(vertexnumber % SPANSTORAGE, type, p0, pc, ID); |
| | } |
| |
|
| | #ifdef PEPSDLL |
| | void Kurve::ModifyIndex(int vertexnumber, WireExtraData* i) |
| | { |
| | |
| | # ifdef _DEBUG |
| | if (vertexnumber > m_nVertices) { |
| | FAILURE(getMessage(L"Kurve::ModifyIndex - vertexNumber out of range")); |
| | } |
| | # endif |
| | SpanVertex* p = (SpanVertex*)m_spans[vertexnumber / SPANSTORAGE]; |
| | p->Add(vertexnumber % SPANSTORAGE, i); |
| | } |
| | #else |
| | void Kurve::AddIndex(int vertexNumber, const SpanDataObject* data) |
| | { |
| | if (vertexNumber > m_nVertices - 1) { |
| | FAILURE(L"Kurve::AddIndex - vertexNumber out of range"); |
| | } |
| | SpanVertex* p = (SpanVertex*)m_spans[vertexNumber / SPANSTORAGE]; |
| | p->Add(vertexNumber % SPANSTORAGE, data); |
| | } |
| |
|
| | const SpanDataObject* Kurve::GetIndex(int vertexNumber) const |
| | { |
| | if (vertexNumber > m_nVertices - 1) { |
| | FAILURE(L"Kurve::GetIndex - vertexNumber out of range"); |
| | } |
| | SpanVertex* p = (SpanVertex*)m_spans[vertexNumber / SPANSTORAGE]; |
| | return p->GetIndex(vertexNumber % SPANSTORAGE); |
| | } |
| |
|
| |
|
| | #endif |
| | void Kurve::Get(std::vector<Span>* all, bool igNoreNullSpans) const |
| | { |
| | |
| | for (int i = 1; i <= nSpans(); i++) { |
| | Span sp; |
| | Get(i, sp, true); |
| | if (igNoreNullSpans && sp.NullSpan) { |
| | continue; |
| | } |
| | all->push_back(sp); |
| | } |
| | } |
| |
|
| | void Kurve::Get(int vertexnumber, spVertex& spv) const |
| | { |
| | spv.type = Get(vertexnumber, spv.p, spv.pc); |
| | spv.spanid = GetSpanID(vertexnumber); |
| | } |
| |
|
| | int Kurve::Get(int vertexnumber, Point& pe, Point& pc) const |
| | { |
| | |
| | if (vertexnumber < 0 || vertexnumber >= m_nVertices) { |
| | FAILURE(getMessage(L"Kurve::Get - vertexNumber out of range")); |
| | } |
| | if (m_isReversed) { |
| | int revVertexnumber = m_nVertices - 1 - vertexnumber; |
| | SpanVertex* p = (SpanVertex*)m_spans[revVertexnumber / SPANSTORAGE]; |
| | int offset = revVertexnumber % SPANSTORAGE; |
| | pe = Point(p->x[offset], p->y[offset]); |
| | if (vertexnumber > 0) { |
| | revVertexnumber++; |
| | offset = revVertexnumber % SPANSTORAGE; |
| | p = (SpanVertex*)m_spans[revVertexnumber / SPANSTORAGE]; |
| | pc = Point(p->xc[offset], p->yc[offset]); |
| | return -p->type[offset]; |
| | } |
| | else { |
| | return LINEAR; |
| | } |
| | } |
| | else { |
| | SpanVertex* p = (SpanVertex*)m_spans[vertexnumber / SPANSTORAGE]; |
| | return p->Get(vertexnumber % SPANSTORAGE, pe, pc); |
| | } |
| | } |
| | int Kurve::GetSpanID(int vertexnumber) const |
| | { |
| | |
| | if (vertexnumber < 0 || vertexnumber >= m_nVertices) { |
| | FAILURE(getMessage(L"Kurve::Get - vertexNumber out of range")); |
| | } |
| | if (m_isReversed) { |
| | vertexnumber = m_nVertices - 1 - vertexnumber; |
| | } |
| | SpanVertex* p = (SpanVertex*)m_spans[vertexnumber / SPANSTORAGE]; |
| | return p->GetSpanID(vertexnumber % SPANSTORAGE); |
| | } |
| | int Kurve::Get(int spannumber, Span& sp, bool returnSpanProperties, bool transform) const |
| | { |
| | |
| | if (spannumber < 1 || spannumber > m_nVertices) { |
| | FAILURE(getMessage(L"Kurve::Get - vertexNumber out of range")); |
| | } |
| | if (m_nVertices < 2) { |
| | return -99; |
| | } |
| |
|
| | int spanVertexNumber = spannumber - 1; |
| | if (m_isReversed) { |
| | spanVertexNumber = m_nVertices - 1 - spanVertexNumber; |
| | } |
| | SpanVertex* p = (SpanVertex*)m_spans[spanVertexNumber / SPANSTORAGE]; |
| | sp.p0.x = p->x[spanVertexNumber % SPANSTORAGE]; |
| | sp.p0.y = p->y[spanVertexNumber % SPANSTORAGE]; |
| | sp.p0.ok = 1; |
| |
|
| | sp.dir = Get(spannumber, sp.p1, sp.pc); |
| | sp.ID = GetSpanID(spannumber); |
| |
|
| | if (transform && !m_unit) { |
| | const Matrix* m = this; |
| | sp.Transform(*m, false); |
| | } |
| |
|
| | sp.SetProperties(returnSpanProperties); |
| |
|
| | return sp.dir; |
| | } |
| |
|
| | #if 0 |
| | int Kurve::Get(int spannumber, Span3d& sp, bool returnSpanProperties, bool transform) const { |
| | |
| | if(spannumber < 1 || spannumber > m_nVertices) FAILURE(getMessage(L"Kurve::Get - vertexNumber out of range")); |
| | if(m_nVertices < 2) |
| | return -99; |
| |
|
| | int spanVertexNumber = spannumber - 1; |
| | SpanVertex* p = (SpanVertex*)m_spans[spanVertexNumber / SPANSTORAGE]; |
| | sp.p0.x = p->x[spanVertexNumber % SPANSTORAGE]; |
| | sp.p0.y = p->y[spanVertexNumber % SPANSTORAGE]; |
| | sp.p0.z = 0; |
| | |
| |
|
| | sp.dir = Get(spannumber, sp.p1, sp.pc); |
| |
|
| | if(transform && !m_unit) { |
| | const Matrix *m = this; |
| | sp.Transform(*m, false); |
| | } |
| |
|
| | sp.SetProperties(returnSpanProperties); |
| |
|
| | return sp.dir; |
| | } |
| | #endif |
| |
|
| | void Kurve::Get(Point& ps, Point& pe) const |
| | { |
| | |
| | Span sp; |
| | Get(1, sp, true, true); |
| | ps = sp.p0; |
| | Get(m_nVertices - 1, sp, true, true); |
| | pe = sp.p1; |
| | } |
| |
|
| | void Span::SetProperties(bool returnProperties) |
| | { |
| | returnSpanProperties = returnProperties; |
| | if (returnSpanProperties) { |
| | |
| | if (dir) { |
| | |
| | vs = ~Vector2d(pc, p0); |
| | ve = ~Vector2d(pc, p1); |
| | if (dir == CW) { |
| | vs = -vs; |
| | ve = -ve; |
| | } |
| |
|
| | radius = vs.normalise(); |
| | double radCheck = ve.normalise(); |
| | |
| | if (FNE(radius, radCheck, geoff_geometry::TOLERANCE)) { |
| | FAILURE(getMessage(L"Invalid Geometry - Radii mismatch - SetProperties")); |
| | } |
| |
|
| | length = 0.0; |
| | angle = 0.0; |
| | if (radius > geoff_geometry::TOLERANCE) { |
| | if ((NullSpan = (p0.Dist(p1)) <= geoff_geometry::TOLERANCE)) { |
| | dir = LINEAR; |
| | } |
| | else { |
| | |
| | length = fabs(angle = IncludedAngle(vs, ve, dir)) * radius; |
| | } |
| | } |
| | else { |
| | NullSpan = true; |
| | } |
| | } |
| | else { |
| | |
| | vs = Vector2d(p0, p1); |
| |
|
| | length = vs.normalise(); |
| | NullSpan = (length <= geoff_geometry::TOLERANCE); |
| | ve = vs; |
| | } |
| | minmax(box, true); |
| | } |
| | } |
| |
|
| | #if 0 |
| | void Span3d::SetProperties(bool returnProperties) { |
| | if(returnSpanProperties = returnProperties) { |
| | |
| | if(dir) { |
| | |
| | vs = normal ^ Vector3d(pc, p0); |
| | ve = normal ^ Vector3d(pc, p1); |
| | if(dir == CW) { |
| | vs = -vs; |
| | ve = -ve; |
| | } |
| |
|
| | radius = vs.normalise(); |
| | double radCheck = ve.normalise(); |
| | if(FNE(radius, radCheck, geoff_geometry::TOLERANCE * 0.5)) FAILURE(getMessage(L"Invalid Geometry - Radii mismatch - SetProperties", GEOMETRY_ERROR_MESSAGES, MES_INVALIDARC)); |
| | if(radius > geoff_geometry::TOLERANCE) { |
| | if(NullSpan = (p0.Dist(p1) <= geoff_geometry::TOLERANCE)) { |
| | length = 0.0; |
| | angle = 0.0; |
| | dir = LINEAR; |
| | } |
| | else { |
| | |
| | length = fabs(angle = IncludedAngle(vs, ve, normal, dir)) * radius; |
| | } |
| | } |
| | else |
| | NullSpan = true; |
| | } |
| | else { |
| | |
| | vs = Vector3d(p0, p1); |
| |
|
| | length = vs.normalise(); |
| | NullSpan = (length <= geoff_geometry::TOLERANCE); |
| | ve = vs; |
| | } |
| | minmax(box, true); |
| | } |
| | } |
| | #endif |
| |
|
| |
|
| | Point Mid(const Span& span) |
| | { |
| | |
| | if (span.dir) { |
| | CLine chord(span.p0, span.p1); |
| | if (chord.ok) { |
| | CLine bisector(Mid(span.p0, span.p1), ~chord.v, false); |
| | return Intof((span.dir == CW) ? FARINT : NEARINT, bisector, Circle(span)); |
| | } |
| | else { |
| | return span.p0; |
| | } |
| | } |
| | else { |
| | return Mid(span.p0, span.p1); |
| | } |
| | } |
| |
|
| | Point Kurve::Near(const Point& p, int& nearSpanNumber) const |
| | { |
| | |
| | double minDist = 1.0e100; |
| | Point pNear, pn; |
| |
|
| | nearSpanNumber = 0; |
| | for (int i = 1; i <= nSpans(); i++) { |
| | Span sp; |
| | Get(i, sp, true, true); |
| | pNear = sp.NearOn(p); |
| | double d = pNear.Dist(p); |
| | if (minDist > d) { |
| | nearSpanNumber = i; |
| | pn = pNear; |
| | minDist = d; |
| | if (minDist < geoff_geometry::TOLERANCE) { |
| | break; |
| | } |
| | } |
| | } |
| | return pn; |
| | } |
| |
|
| |
|
| | Point Kurve::NearToVertex(const Point& p, int& nearSpanNumber) const |
| | { |
| | |
| | double minDistSquared = 1.0e100; |
| | Point pn; |
| |
|
| | Matrix inv_mat = *this; |
| | inv_mat.Inverse(); |
| |
|
| | Point tp = p; |
| | if (!m_unit) { |
| | tp = tp.Transform(inv_mat); |
| | } |
| |
|
| | nearSpanNumber = 0; |
| |
|
| | for (int i = 0; i < m_nVertices; i++) { |
| | Point ps, pc; |
| | Get(i, ps, pc); |
| | double DistSquared = Vector2d(ps, tp).magnitudesqd(); |
| | if (DistSquared < minDistSquared) { |
| | minDistSquared = DistSquared; |
| | nearSpanNumber = i; |
| | pn = ps; |
| | } |
| | } |
| | return pn.Transform(*this); |
| | } |
| |
|
| | void Kurve::ChangeStart(const Point* pNewStart, int startSpanno) |
| | { |
| | |
| | if (startSpanno == 1) { |
| | Span spFirst; |
| | this->Get(1, spFirst, false, true); |
| | if (spFirst.p0 == *pNewStart) { |
| | return; |
| | } |
| | } |
| | else if (startSpanno == this->nSpans()) { |
| | Span spLast; |
| | this->Get(this->nSpans(), spLast, false, true); |
| | if (spLast.p1 == *pNewStart) { |
| | return; |
| | } |
| | } |
| | Kurve temp; |
| |
|
| | bool wrapped = false; |
| | int spanno = startSpanno; |
| | Span sp; |
| | for (int nSpans = 0; nSpans <= this->nSpans(); nSpans++) { |
| | this->Get(spanno, sp, false, true); |
| | if (spanno == startSpanno && !wrapped) { |
| | temp.Start(*pNewStart); |
| | temp.Add(sp.dir, sp.p1, sp.pc, true); |
| | } |
| | else { |
| | if (nSpans == this->nSpans() && this->Closed()) { |
| | sp.p1 = *pNewStart; |
| | } |
| | temp.Add(sp, true); |
| | } |
| |
|
| | spanno++; |
| |
|
| | if (spanno > this->nSpans()) { |
| | if (!this->Closed()) { |
| | break; |
| | } |
| | spanno = 1; |
| | wrapped = true; |
| | } |
| | } |
| |
|
| | *this = temp; |
| | } |
| |
|
| |
|
| | void Kurve::ChangeEnd(const Point* pNewEnd, int endSpanno) |
| | { |
| | |
| | if (endSpanno == 1) { |
| | Span spFirst; |
| | this->Get(1, spFirst, false, true); |
| | if (spFirst.p0 == *pNewEnd) { |
| | return; |
| | } |
| | } |
| | else if (endSpanno == this->nSpans()) { |
| | Span spLast; |
| | this->Get(this->nSpans(), spLast, false, true); |
| | if (spLast.p1 == *pNewEnd) { |
| | return; |
| | } |
| | } |
| | Kurve temp; |
| |
|
| | Span sp; |
| |
|
| | for (int spanno = 1; spanno != (endSpanno + 1); spanno++) { |
| | this->Get(spanno, sp, false, true); |
| | if (spanno == 1) { |
| | temp.Start(sp.p0); |
| | } |
| |
|
| | if (spanno == endSpanno) { |
| | sp.p1 = *pNewEnd; |
| | } |
| |
|
| | temp.Add(sp.dir, sp.p1, sp.pc, true); |
| | if (spanno == endSpanno) { |
| | break; |
| | } |
| |
|
| | |
| | } |
| |
|
| | *this = temp; |
| | } |
| |
|
| | void Kurve::minmax(Point& min, Point& max) |
| | { |
| | |
| | double xscale = 1.0; |
| | min = Point(1.0e61, 1.0e61); |
| | max = Point(-1.0e61, -1.0e61); |
| |
|
| | if (!GetScale(xscale)) { |
| | FAILURE(getMessage(L"Differential Scale not allowed for this method")); |
| | } |
| | Span sp; |
| | for (int i = 1; i < m_nVertices; i++) { |
| | Get(i, sp, true, true); |
| | if (i == 1) { |
| | MinMax(sp.p0, min, max); |
| | } |
| | sp.minmax(min, max, false); |
| | } |
| | } |
| |
|
| | void Kurve::minmax(Box& b) |
| | { |
| | minmax(b.min, b.max); |
| | } |
| |
|
| | void Kurve::StoreAllSpans(std::vector<Span>& kSpans) const |
| | { |
| | Span span; |
| | for (int i = 1; i <= this->nSpans(); i++) { |
| | this->Get(i, span, true, false); |
| | kSpans.push_back(span); |
| | } |
| | } |
| |
|
| | void Kurve::Clear() |
| | { |
| | for (vector<SpanVertex*>::iterator It = m_spans.begin(); It != m_spans.end(); It++) { |
| | SpanVertex* spv = *It; |
| | delete spv; |
| | } |
| | m_spans.clear(); |
| | m_started = false; |
| | m_nVertices = 0; |
| | m_isReversed = false; |
| | } |
| |
|
| | bool Kurve::operator==(const Kurve& k) const |
| | { |
| | |
| | if (nSpans() != k.nSpans()) { |
| | return false; |
| | } |
| | spVertex thisvertex, vertex; |
| | for (int i = 0; i <= nSpans(); i++) { |
| | this->Get(i, thisvertex); |
| | k.Get(i, vertex); |
| | if (thisvertex != vertex) { |
| | return false; |
| | } |
| | } |
| | return true; |
| | } |
| |
|
| | double Kurve::Perim() const |
| | { |
| | |
| | double perim = 0; |
| | Span sp; |
| | double xscale = 1.0; |
| | if (!GetScale(xscale)) { |
| | FAILURE(getMessage(L"Differential Scale not allowed for this method")); |
| | } |
| |
|
| | if (m_nVertices > 1) { |
| | for (int i = 1; i < m_nVertices; i++) { |
| | perim += (Get(i, sp, true)) ? fabs(sp.angle) * sp.radius : sp.length; |
| | } |
| | } |
| | return perim * xscale; |
| | } |
| | double Kurve::Area() const |
| | { |
| | |
| | double xscale = 1.0; |
| | double area = 0; |
| | Span sp; |
| |
|
| | if (Closed()) { |
| | if (!GetScale(xscale)) { |
| | FAILURE(getMessage(L"Differential Scale not allowed for this method")); |
| | |
| | } |
| | for (int i = 1; i < m_nVertices; i++) { |
| | if (Get(i, sp, true)) { |
| | area |
| | += (0.5 |
| | * ((sp.pc.x - sp.p0.x) * (sp.pc.y + sp.p0.y) |
| | - (sp.pc.x - sp.p1.x) * (sp.pc.y + sp.p1.y) |
| | - sp.angle * sp.radius * sp.radius)); |
| | } |
| | else { |
| | area += 0.5 * (sp.p1.x - sp.p0.x) * (sp.p0.y + sp.p1.y); |
| | } |
| | } |
| | } |
| | return area * xscale * xscale; |
| | } |
| |
|
| | static void bubblesort(vector<Point>& p, vector<double>& d); |
| |
|
| | int Kurve::Intof(const Span& spin, vector<Point>& p) const |
| | { |
| | |
| | int totalPoints = 0; |
| | for (int i = 1; i <= nSpans(); i++) { |
| | Span sp; |
| | Get(i, sp, true, true); |
| |
|
| | Point pInt1, pInt2; |
| | double t[4]; |
| | int numint = sp.Intof(spin, pInt1, pInt2, t); |
| | if (numint) { |
| | p.push_back(pInt1); |
| | } |
| | if (numint == 2) { |
| | p.push_back(pInt2); |
| | } |
| | totalPoints += numint; |
| | } |
| | if (totalPoints) { |
| | |
| | vector<double> d; |
| | Span temp(spin); |
| |
|
| | for (int i = 0; i < (int)p.size(); i++) { |
| | temp.p1 = p[i]; |
| | temp.SetProperties(true); |
| |
|
| | d.push_back(temp.length); |
| | } |
| | bubblesort(p, d); |
| | } |
| | return totalPoints; |
| | } |
| |
|
| | static void bubblesort(vector<Point>& p, vector<double>& d) |
| | { |
| |
|
| | for (int pass = 1; pass < (int)p.size(); pass++) { |
| | for (int j = 0; j < (int)p.size() - 1; j++) { |
| | if (d[j] > d[j + 1]) { |
| | |
| | Point temp = p[j]; |
| | p[j] = p[j + 1]; |
| | p[j + 1] = temp; |
| | double dtemp = d[j]; |
| | d[j] = d[j + 1]; |
| | d[j + 1] = dtemp; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | int Kurve::Intof(const Kurve& k, vector<Point>& p) const |
| | { |
| | vector<Point> all; |
| |
|
| | int totalPoints = 0; |
| | for (int i = 1; i <= nSpans(); i++) { |
| | Span sp; |
| | Get(i, sp, true, true); |
| | vector<Point> p0; |
| | totalPoints += k.Intof(sp, p0); |
| |
|
| | for (int j = 0; j < (int)p0.size(); j++) { |
| | all.push_back(p0[j]); |
| | } |
| | } |
| | (void)totalPoints; |
| | |
| | |
| | |
| |
|
| |
|
| | for (int i = 0; i < (int)all.size(); i++) { |
| | if (i == 0) { |
| | p.push_back(all[0]); |
| | } |
| | else if (all[i - 1].Dist(all[i]) > geoff_geometry::TOLERANCE) { |
| | p.push_back(all[i]); |
| | } |
| | } |
| |
|
| | |
| | return (int)p.size(); |
| | } |
| |
|
| | bool Kurve::Split(double MaximumRadius, double resolution) |
| | { |
| |
|
| | Span sp; |
| | bool changed = false; |
| | Kurve ko; |
| |
|
| | Get(0, sp.p0, sp.pc); |
| | ko.Start(sp.p0); |
| |
|
| | for (int i = 1; i < m_nVertices; i++) { |
| | sp.dir = Get(i, sp.p1, sp.pc); |
| | if (sp.dir) { |
| | sp.SetProperties(true); |
| | if (sp.radius >= MaximumRadius) { |
| | |
| | int nSplits = sp.Split(resolution); |
| | if (nSplits > 1) { |
| | Matrix m; |
| | sp.SplitMatrix(nSplits, &m); |
| | for (int j = 1; j < nSplits; j++) { |
| | sp.p0 = sp.p0.Transform(m); |
| | ko.Add(sp.p0); |
| | } |
| |
|
| | sp.dir = LINEAR; |
| | changed = true; |
| | } |
| | } |
| | } |
| |
|
| | ko.Add(sp.dir, sp.p1, sp.pc); |
| |
|
| | sp.p0 = sp.p1; |
| | } |
| | |
| | if (changed) { |
| | *this = ko; |
| | } |
| | return changed; |
| | } |
| |
|
| | void Kurve::Reverse() |
| | { |
| | |
| | int nSwaps = (m_nVertices - 1) / 2; |
| | if (nSwaps == 0) { |
| | return; |
| | } |
| | Point p0, pc0; |
| | Point pend, pcend; |
| |
|
| | int i = 0, j = m_nVertices - 1; |
| | int dir0 = Get(i, p0, pc0); |
| | int spanID0 = GetSpanID(i); |
| | int dirend = Get(j, pend, pcend); |
| | int spanIDend = GetSpanID(j); |
| |
|
| | while (i <= nSwaps) { |
| | Point p1, pc1; |
| | int dir1 = Get(i + 1, p1, pc1); |
| | int spanID1 = GetSpanID(i + 1); |
| | Point pendp, pcendp; |
| | int direndp = Get(j - 1, pendp, pcendp); |
| | int spanIDendp = GetSpanID(j - 1); |
| | |
| | Replace(i, dir0, pend, pc0, spanID0); |
| | Replace(j, dirend, p0, pcend, spanIDend); |
| |
|
| | dir0 = dir1; |
| | p0 = p1; |
| | pc0 = pc1; |
| | dirend = direndp; |
| | pend = pendp; |
| | pcend = pcendp; |
| | spanID0 = spanID1; |
| | spanIDend = spanIDendp; |
| |
|
| | i++; |
| | j--; |
| | } |
| |
|
| | |
| | |
| | i = 0; |
| | j = m_nVertices - 1; |
| | dir0 = Get(i, p0, pc0); |
| | dirend = Get(j, pend, pcend); |
| |
|
| | while (i < nSwaps) { |
| | Point p1, pc1; |
| | Point pendp, pcendp; |
| |
|
| | int dir1 = Get(i + 1, p1, pc1); |
| | int direndp = Get(j - 1, pendp, pcendp); |
| |
|
| | Replace(i + 1, -dirend, p1, pcend); |
| | Replace(j, -dir1, pend, pc1); |
| | dir0 = dir1; |
| | p0 = p1; |
| | pc0 = pc1; |
| | dirend = direndp; |
| | pend = pendp; |
| | pcend = pcendp; |
| | i++; |
| | j--; |
| | } |
| | } |
| |
|
| | int Kurve::Reduce(double tolerance) |
| | { |
| | |
| | |
| | if (nSpans() <= 2) { |
| | return 0; |
| | } |
| | Kurve kReduced; |
| | kReduced = Matrix(*this); |
| |
|
| | #if 0 |
| | for(int i = 1; i <= this->nSpans(); i++) { |
| | Span sp; |
| | this->Get(i, sp, true); |
| |
|
| | for(int j = i+1; j <= this->nSpans(); j++) { |
| | Span spnext; |
| | this->Get(j, spnext, true); |
| |
|
| | } |
| | } |
| | return m_nVertices - kReduced.m_nVertices; |
| |
|
| | #else |
| | int dir1, dir2 = 0; |
| | Point p0, p1, p2, pc0, pc1, pc2; |
| | int vertex = 0; |
| | int dir0 = Get(vertex++, p0, pc0); |
| | kReduced.Start(p0); |
| | int lvertex = vertex++; |
| |
|
| | while (vertex < m_nVertices) { |
| | while (vertex < m_nVertices) { |
| | int savelvertex = lvertex; |
| | int addvertex = vertex - 1; |
| | dir2 = Get(vertex++, p2, pc2); |
| | CLine cl(p0, p2); |
| | if (cl.ok) { |
| | bool outoftol = false; |
| | while (lvertex < vertex - 1) { |
| | dir1 = Get(lvertex++, p1, pc1); |
| |
|
| | if (dir1 || fabs(cl.Dist(p1)) > tolerance) { |
| | outoftol = true; |
| | break; |
| | } |
| | } |
| | if (outoftol) { |
| | dir0 = Get(addvertex, p0, pc0); |
| | kReduced.Add(dir0, p0, pc0); |
| | lvertex = addvertex + 1; |
| | } |
| | else { |
| | lvertex = savelvertex; |
| | } |
| | } |
| | } |
| | } |
| | kReduced.Add(dir2, p2, pc2); |
| |
|
| | if (m_nVertices != kReduced.m_nVertices) { |
| | *this = kReduced; |
| | } |
| | return m_nVertices - kReduced.m_nVertices; |
| | #endif |
| | } |
| |
|
| | void Kurve::Part(int startVertex, int EndVertex, Kurve* part) |
| | { |
| | |
| | spVertex spv; |
| | for (int i = startVertex; i <= EndVertex; i++) { |
| | Get(i, spv); |
| | part->Add(spv, true); |
| | } |
| | return; |
| | } |
| |
|
| |
|
| | Kurve Kurve::Part(int fromSpanno, const Point& fromPt, int toSpanno, const Point& toPt) |
| | { |
| | |
| | |
| | Kurve kPart; |
| | Span span; |
| | Point ps, pe; |
| | int iStartSpanNr, iEndSpanNr, i; |
| |
|
| | |
| | if (fromSpanno == 0) { |
| | ps = Near(fromPt, iStartSpanNr); |
| | } |
| | else { |
| | Get(fromSpanno, span, true, true); |
| | ps = span.p0; |
| | iStartSpanNr = fromSpanno; |
| | } |
| | |
| | if (toSpanno == 0) { |
| | pe = Near(toPt, iEndSpanNr); |
| | } |
| | else { |
| | Get(toSpanno, span, true, true); |
| | pe = span.p1; |
| | iEndSpanNr = toSpanno; |
| | } |
| |
|
| | kPart.Start(ps); |
| | Get(iStartSpanNr, span, true, true); |
| |
|
| | if (iStartSpanNr == iEndSpanNr) { |
| | kPart.Add(span.dir, pe, span.pc); |
| | return kPart; |
| | } |
| |
|
| | if (iStartSpanNr < iEndSpanNr) { |
| | for (i = iStartSpanNr; i < iEndSpanNr; i++) { |
| | Get(i, span, true, true); |
| | kPart.Add(span.dir, span.p1, span.pc); |
| | } |
| | Get(iEndSpanNr, span, true, true); |
| | kPart.Add(span.dir, pe, span.pc); |
| | } |
| | if (iStartSpanNr > iEndSpanNr) { |
| | for (i = iStartSpanNr; i <= nSpans(); i++) { |
| | Get(i, span, true, true); |
| | kPart.Add(span.dir, span.p1, span.pc); |
| | } |
| | if (!Closed()) { |
| | Get(1, span, true, true); |
| | kPart.Add(0, span.p0, Point(0.0, 0.0)); |
| | } |
| | for (i = 1; i < iEndSpanNr; i++) { |
| | Get(i, span, true, true); |
| | kPart.Add(span.dir, span.p1, span.pc); |
| | } |
| | Get(iEndSpanNr, span, true, true); |
| | kPart.Add(span.dir, pe, span.pc); |
| | } |
| | return kPart; |
| | } |
| |
|
| | Kurve Kurve::Part(double fromParam, double toParam) |
| | { |
| | |
| | |
| | Kurve k; |
| |
|
| | double perimTotal = this->Perim(); |
| | double fromPerim = fromParam * perimTotal; |
| | double toPerim = toParam * perimTotal; |
| | double perim = 0.; |
| | double perimLast = 0.; |
| | for (int i = 1; i <= this->nSpans(); i++) { |
| | Span sp; |
| | this->Get(i, sp, true, true); |
| | perim += sp.length; |
| | if (fromPerim <= perim && !k.m_started) { |
| | |
| | if (FEQ(fromPerim, perim)) { |
| | k.Start(sp.p0); |
| | } |
| | else { |
| | double d = fromPerim - perimLast; |
| | k.Start(sp.MidPerim(d)); |
| | } |
| | } |
| |
|
| | if (perim >= toPerim) { |
| | |
| | if (FEQ(toPerim, perim)) { |
| | k.Add(sp); |
| | } |
| | else { |
| | double d = toPerim - perimLast; |
| | sp.p1 = sp.MidPerim(d); |
| | k.Add(sp); |
| | } |
| | break; |
| | } |
| | if (k.m_started) { |
| | k.Add(sp); |
| | } |
| | perimLast = perim; |
| | } |
| | return k; |
| | } |
| |
|
| | void tangential_arc(const Point& p0, const Point& p1, const Vector2d& v0, Point& c, int& dir) |
| | { |
| | |
| | dir = 0; |
| |
|
| | if (p0.Dist(p1) > 0.0000000001 && v0.magnitude() > 0.0000000001) { |
| | Vector2d v1(p0, p1); |
| | Point halfway(p0 + Point(v1 * 0.5)); |
| | Plane pl1(halfway, v1); |
| | Plane pl2(p0, v0); |
| | Line plane_line; |
| | if (pl1.Intof(pl2, plane_line)) { |
| | Line l1(halfway, v1); |
| | double t1, t2; |
| | Line lshort; |
| | plane_line.Shortest(l1, lshort, t1, t2); |
| | c = lshort.p0; |
| | Vector3d cross = Vector3d(v0) ^ Vector3d(v1); |
| | dir = (cross.getz() > 0) ? 1 : -1; |
| | } |
| | } |
| | } |
| |
|
| | } |
| |
|