QList<QSharedPointer<RShape> > RDimAlignedData::getShapes(const RBox& queryBox, bool ignoreComplex) const { Q_UNUSED(queryBox) Q_UNUSED(ignoreComplex) QSharedPointer<RBlockReferenceEntity> dimBlockReference = getDimensionBlockReference(); if (!dimBlockReference.isNull()) { return dimBlockReference->getShapes(queryBox, ignoreComplex); } QList<QSharedPointer<RShape> > ret; double dimexo = getDimexo(); double dimexe = getDimexe(); RLine extensionLine(extensionPoint1, extensionPoint2); // angle from extension endpoints towards dimension line double extAngle = extensionPoint1.getAngleTo(extensionPoint2); RS::Side side = extensionLine.getSideOfPoint(definitionPoint); if (side==RS::RightHand) { extAngle -= M_PI/2.0; } else { extAngle += M_PI/2.0; } // extension lines length double extLength = extensionLine.getDistanceTo(definitionPoint, false); RVector v1, v2, e1; RLine line; // from entity to inner point of extension line: v1.setPolar(dimexo, extAngle); // from entity to outer point of extension line: v2.setPolar(dimexe, extAngle); e1.setPolar(1.0, extAngle); refDefinitionPoint1 = extensionPoint1 + e1*extLength; refDefinitionPoint2 = extensionPoint2 + e1*extLength; definitionPoint = refDefinitionPoint1; // extension line 1: line = RLine(extensionPoint1 + v1, extensionPoint1 + e1*extLength + v2); ret.append(QSharedPointer<RLine>(new RLine(line))); // extension line 2: line = RLine(extensionPoint2 + v1, extensionPoint2 + e1*extLength + v2); ret.append(QSharedPointer<RLine>(new RLine(line))); // dimension line: ret.append(getDimensionLineShapes( extensionPoint1 + e1*extLength, extensionPoint2 + e1*extLength, true, true)); return ret; }
int EBuffer::InsertString(const char *aStr, int aCount) { int P; int C, L; int Y = VToR(CP.Row); if (BFI(this, BFI_InsertKillBlock) == 1) if (CheckBlock() == 1) if (BlockKill() == 0) return 0; if (BFI(this, BFI_Insert) == 0) if (CP.Col < LineLen()) if (KillChar() == 0) return 0; if (InsText(Y, CP.Col, aCount, aStr) == 0) return 0; C = CP.Col; L = VToR(CP.Row); P = CharOffset(RLine(L), C); P += aCount; C = ScreenPos(RLine(L), P); if (SetPos(C, CP.Row) == 0) return 0; if (BFI(this, BFI_Trim) && *aStr != '\t') if (TrimLine(L) == 0) return 0; if (BFI(this, BFI_WordWrap) == 2) { if (DoWrap(0) == 0) return 0; } else if (BFI(this, BFI_WordWrap) == 1) { int P, C = CP.Col; PELine LP; int L; if (C > BFI(this, BFI_RightMargin)) { L = CP.Row; C = BFI(this, BFI_RightMargin); P = CharOffset(LP = RLine(L), C); while ((C > BFI(this, BFI_LeftMargin)) && ((LP->Chars[P] != ' ') && (LP->Chars[P] != 9))) C = ScreenPos(LP, --P); if (P <= BFI(this, BFI_LeftMargin)) { C = BFI(this, BFI_RightMargin); } else C = ScreenPos(LP, P); if (SplitLine(L, C) == 0) return 0; IndentLine(L + 1, BFI(this, BFI_LeftMargin)); if (SetPos(CP.Col - C - 1 + BFI(this, BFI_LeftMargin), CP.Row + 1) == 0) return 0; } } return 1; }
int EBuffer::InsPrevLineChar() { int L = VToR(CP.Row); int C = CP.Col, P; if (L > 0) { L--; if (C < LineLen(L)) { P = CharOffset(RLine(L), C); return InsertChar(RLine(L)->Chars[P]); } } return 0; }
int EBuffer::InsPrevLineToEol() { int L = VToR(CP.Row); int C = CP.Col, P; int Len; if (L > 0) { L--; P = CharOffset(RLine(L), C); Len = RLine(L)->Count - P; if (Len > 0) return InsertString(RLine(L)->Chars + P, Len); } return 0; }
int EBuffer::FoldCreateByRegexp(const char *Regexp) { /*FOLD00*/ RxNode *R; int err = 1; if (Modify() == 0) return 0; R = RxCompile(Regexp); if (R != NULL) { PELine X; int first = -1; int L; for (L = 0; L < RCount; L++) { RxMatchRes RM; X = RLine(L); if (RxExec(R, X->Chars, X->Count, X->Chars, &RM) == 1) { if (first >= 0) { int i; for (i = L; i > 0; i--) { PELine Y; Y = RLine(i); if ((Y->Count == 0) || strrchr(Y->Chars, '}')) { if ((L - i) > 2) { while ((i > 0) && (RLine(i - 1)->Count == 0)) i--; if ((first >= 0) && i && (FoldCreate(i) == 0)) err = 0; } break; } } } else first = L; if (FoldCreate(L) == 0) { err = 0; break; } } } RxFree(R); } return err; }
void EBuffer::Rehilit(int ToRow) { hlState State; int HilitX; PELine L; int ECol; if (StartHilit == -1) // all ok return; if (BFI(this, BFI_MultiLineHilit) == 0) // everything handled in redisplay return; if (ToRow <= StartHilit) // will be handled in redisplay return; if (ToRow >= RCount) ToRow = RCount; HilitX = 1; while ((StartHilit < RCount) && ((StartHilit < ToRow) || HilitX)) { L = RLine(StartHilit); HilitX = 0; if (StartHilit > 0) State = RLine(StartHilit - 1)->StateE; else State = 0; if ((BFI(this, BFI_HilitOn) == 1) && (HilitProc != 0)) { HilitProc(this, StartHilit, 0, 0, 0, L, State, 0, &ECol); } else { Hilit_Plain(this, StartHilit, 0, 0, 0, L, State, 0, &ECol); } if (L->StateE != State) { HilitX = 1; L->StateE = State; } Draw(StartHilit, StartHilit); // ? if (StartHilit > EndHilit) EndHilit = StartHilit; if (HilitX == 0) // jump over (can we always do this ?) if (StartHilit < EndHilit) { StartHilit = EndHilit; } StartHilit++; } }
// FindFunction -- search for line matching 'RoutineRegexp' // starting from current line + 'delta'. 'way' should be +1 or -1. int EBuffer::FindFunction(int delta, int way) { RxNode *regx; int line; PELine L; RxMatchRes res; if (BFS(this, BFS_RoutineRegexp) == 0) { View->MView->Win->Choice(GPC_ERROR, "Error", 1, "O&K", "No routine regexp."); return -1; } regx = RxCompile(BFS(this, BFS_RoutineRegexp)); if (regx == 0) { View->MView->Win->Choice(GPC_ERROR, "Error", 1, "O&K", "Failed to compile regexp '%s'", BFS(this, BFS_RoutineRegexp)); return -1; } //** Scan backwards from the current cursor position, Msg(S_BUSY, "Matching %s", BFS(this, BFS_RoutineRegexp)); line = VToR(CP.Row) + delta; while (line >= 0 && line < RCount) { L = RLine(line); if (RxExec(regx, L->Chars, L->Count, L->Chars, &res) == 1) break; line += way; } if (line < 0) line = 0; if (line >= RCount) line = RCount - 1; RxFree(regx); return line; }
int EBuffer::BlockUnTab() { EPoint B, E; ELine *L; int O, C; AutoExtend = 0; if (CheckBlock() == 0) return 0; if (RCount <= 0) return 0; B = BB; E = BE; Draw(B.Row, E.Row); for (int i = B.Row; i < E.Row; i++) { L = RLine(i); O = 0; C = 0; while (O < L->Count) { if (L->Chars[O] == '\t') { C = NextTab(C, BFI(this, BFI_TabSize)); if (DelChars(i, O, 1) != 1) return 0; if (InsChars(i, O, C - O, 0) != 1) return 0; O = C; } else { O++; C++; } } } return 1; }
QList<RVector> RShape::getIntersectionPointsAT(const RArc& arc1, const RTriangle& triangle2, bool limited) { Q_UNUSED(limited) RTriangle plane(arc1.getCenter(), arc1.getStartPoint(), arc1.getEndPoint()); QList<RVector> r = plane.getIntersectionPoints(RLine(triangle2.getCorner(0), triangle2.getCorner(1))); r.append(plane.getIntersectionPoints(RLine(triangle2.getCorner(1), triangle2.getCorner(2)))); r.append(plane.getIntersectionPoints(RLine(triangle2.getCorner(2), triangle2.getCorner(0)))); if (r.size()<2) { return QList<RVector>(); } RLine l(r[0], r[1]); return l.getIntersectionPoints(arc1); }
int EBuffer::LineIndented(int Row, const char *indentchars) { ELine *l; if (Row < 0) return 0; if (Row >= RCount) return 0; l = RLine(Row); return ScreenPos(l, LineIndentedCharCount(l, indentchars)); }
bool RArc::scale(const RVector& scaleFactors, const RVector& c) { // negative scaling: mirroring and scaling if (scaleFactors.x < 0.0) { mirror(RLine(center, center + RVector(0.0, 1.0))); } if (scaleFactors.y < 0.0) { mirror(RLine(center, center + RVector(1.0, 0.0))); } center.scale(scaleFactors, c); radius *= scaleFactors.x; if (radius < 0.0) { radius *= -1.0; } return true; }
int EBuffer::MoveNextEqualIndent() { int L = VToR(CP.Row); int I = LineIndented(L); while (L++ < RCount - 1) if ((RLine(L)->Count > 0) && (LineIndented(L) == I)) return SetPosR(I, L); return 0; }
int EBuffer::IsLineBlank(int Row) const { PELine X = RLine(Row); int P; for (P = 0; P < X->Count; P++) if (X->Chars[P] != ' ' && X->Chars[P] != 9) return 0; return 1; }
bool REntityData::flipVertical() { // if this entity is based on a shape (point,line,arc,...), // transform using shape API: RShape* s = castToShape(); if (s==NULL) { return mirror(RLine(RVector(0,0), RVector(1,0))); } return s->flipVertical(); }
int EBuffer::BlockSort(int Reverse) { int rq; ELine *oldL; if (CheckBlock() == 0) return 0; if (RCount == 0) return 0; SortMinRow = BB.Row; SortMaxRow = BE.Row; if (BlockMode != bmStream || BE.Col == 0) SortMaxRow--; if (SortMinRow >= SortMaxRow) return 1; SortBuffer = this; SortReverse = Reverse; switch (BlockMode) { case bmLine: case bmStream: SortMinCol = -1; SortMaxCol = -1; break; case bmColumn: SortMinCol = BB.Col; SortMaxCol = BE.Col; break; } SortRows = (int *)malloc((SortMaxRow - SortMinRow + 1) * sizeof(int)); if (SortRows == 0) { free(SortRows); return 0; } for (rq = 0; rq <= SortMaxRow - SortMinRow; rq++) SortRows[rq] = rq + SortMinRow; qsort(SortRows, SortMaxRow - SortMinRow + 1, sizeof(int), SortProc); // now change the order of lines according to new order in Rows array. for (rq = 0; rq <= SortMaxRow - SortMinRow; rq++) { oldL = RLine(SortRows[rq]); if (InsLine(1 + rq + SortMaxRow, 0) == 0) return 0; if (InsChars(1 + rq + SortMaxRow, 0, oldL->Count, oldL->Chars) == 0) return 0; } for (rq = 0; rq <= SortMaxRow - SortMinRow; rq++) if (DelLine(SortMinRow) == 0) return 0; free(SortRows); return 1; }
int EBuffer::MovePrevEqualIndent() { int L = VToR(CP.Row); int I = LineIndented(L); while (--L >= 0) if ((RLine(L)->Count > 0) && (LineIndented(L) == I)) return SetPosR(I, L); return 0; }
void ROrthoGrid::paintCursor(const RVector& pos) { // crosshair size: double s = 0; if (!RSettings::getShowLargeCrosshair()) { s = view.mapDistanceFromView(25); } RBox b = view.getBox(); if (isometric) { double dxp, dyp, dxn, dyn; if (RSettings::getShowLargeCrosshair()) { dxp = b.c2.x - pos.x; dyp = tan(M_PI/6) * dxp; dxn = pos.x - b.c1.x; dyn = tan(M_PI/6) * dxn; } else { dxp = dxn = cos(M_PI/6) * s; dyp = dyn = sin(M_PI/6) * s; } // .-´ if (projection==RS::IsoTop || projection==RS::IsoRight) { view.paintGridLine(RLine(pos + RVector(dxp,dyp), pos - RVector(dxn,dyn))); } // `-. if (projection==RS::IsoTop || projection==RS::IsoLeft) { view.paintGridLine(RLine(pos + RVector(dxp,-dyp), pos - RVector(dxn,-dyn))); } // | if (projection==RS::IsoRight || projection==RS::IsoLeft) { if (RSettings::getShowLargeCrosshair()) { view.paintGridLine(RLine(RVector(pos.x, b.c1.y), RVector(pos.x, b.c2.y))); } else { view.paintGridLine(RLine(RVector(pos.x, pos.y - s), RVector(pos.x, pos.y + s))); } } } else { if (RSettings::getShowLargeCrosshair()) { view.paintGridLine(RLine(RVector(b.c1.x, pos.y), RVector(b.c2.x, pos.y))); view.paintGridLine(RLine(RVector(pos.x, b.c1.y), RVector(pos.x, b.c2.y))); } else { double s = view.mapDistanceFromView(25); RVector sx(s, 0); RVector sy(0, s); view.paintGridLine(RLine(pos-sx, pos+sx)); view.paintGridLine(RLine(pos-sy, pos+sy)); } } }
int EBuffer::GetMap(int Row, int *StateLen, hsState **StateMap) { hlState State = 0; Rehilit(Row); *StateLen = LineChars(Row); if (Row > 0) State = RLine(Row - 1)->StateE; if (*StateLen > 0) { PELine L = RLine(Row); int ECol; *StateMap = (hsState *)malloc(*StateLen); if (*StateMap == 0) return 0; if ((BFI(this, BFI_HilitOn) == 1) && (HilitProc != 0)) HilitProc(this, Row, 0, 0, *StateLen, L, State, *StateMap, &ECol); else Hilit_Plain(this, Row, 0, 0, *StateLen, L, State, *StateMap, &ECol); // if (L->StateE != State) { // L->StateE = State; // } } else { *StateLen = 1; *StateMap = (hsState *)malloc(1); if (*StateMap == 0) return 0; (*StateMap)[0] = (hsState)(State & 0xFF); } return 1; }
int EBuffer::Delete() { int Y = VToR(CP.Row); if (CheckBlock() == 1 && BFI(this, BFI_DeleteKillBlock)) { if (BlockKill() == 0) return 0; } else if (CP.Col < LineLen()) { if (BFI(this, BFI_DeleteKillTab)) { int P; int C = CP.Col, C1; P = CharOffset(RLine(Y), C); C1 = ScreenPos(RLine(Y), P + 1); if (DelText(Y, C, C1 - C) == 0) return 0; } else { ELine *L = RLine(Y); int C = CharOffset(L, CP.Col); if (L->Count > 0 && L->Chars[C] == '\t') { /* We're on top of tab character. Skip over all spaces and tabs so that only the last space/tab gets deleted. */ while (C < L->Count && (L->Chars[C+1] == '\t' || L->Chars[C+1] == ' ')) C++; } if (DelText(Y, ScreenPos(L, C), 1) == 0) return 0; } } else if (LineJoin() == 0) return 0; if (BFI(this, BFI_WordWrap) == 2) { if (DoWrap(0) == 0) return 0; if (CP.Col >= LineLen(Y)) if (CP.Row < VCount - 1) { if (SetPos(BFI(this, BFI_LeftMargin), CP.Row + 1) == 0) return 0; } } if (BFI(this, BFI_Trim)) if (TrimLine(VToR(CP.Row)) == 0) return 0; return 1; }
int EBuffer::TrimLine(int Row) { PELine L = RLine(Row); int P, X, E; if (L->Count == 0) return 1; P = L->Count; while ((P > 0) && ((L->Chars[P - 1] == ' ') || (L->Chars[P - 1] == 9))) P--; X = ScreenPos(L, P); E = ScreenPos(L, L->Count); if (E - X > 0) if (DelText(Row, X, E - X, 1) == 0) return 0; return 1; }
bool REllipse::scale(const RVector& scaleFactors, const RVector& c) { if (fabs(fabs(scaleFactors.x) - fabs(scaleFactors.y)) > RS::PointTolerance) { qWarning("REllipse::scale: scaling with different factors in X/Y not supported for ellipses at this point"); return false; } //RVector oldMinorPoint = getMinorPoint(); // negative scaling: mirroring and scaling if (scaleFactors.x < 0.0) { mirror(RLine(center, center + RVector(0.0, 1.0))); } if (scaleFactors.y < 0.0) { mirror(RLine(center, center + RVector(1.0, 0.0))); } center.scale(scaleFactors, c); //oldMinorPoint.scale(scaleFactors); RVector f = RVector(fabs(scaleFactors.x), fabs(scaleFactors.y), fabs(scaleFactors.z)); majorPoint.scale(f); // if (fabs(majorPoint.getMagnitude()) > 1.0e-4) { // ratio = oldMinorPoint.getMagnitude() / majorPoint.getMagnitude(); // } return true; // QList<RVector> box = getBoxCorners(); // RVector::scaleList(box, scaleFactors, c); // // TODO: // REllipse e = REllipse::createInscribed(box); // //*this = e; // return true; }
QList<RLine> RPatternLine::getLines() const { QList<RLine> ret; RVector cursor(0,0); // continuous: if (dashes.length()==0) { RVector newCursor = cursor + RVector::createPolar(10.0, angle); ret.append(RLine(cursor, newCursor)); cursor = newCursor; } else { for (int i=0; i<dashes.length(); i++) { double dash = dashes[i]; RVector newCursor = cursor + RVector::createPolar(qAbs(dash), angle); if (dash>0) { ret.append(RLine(cursor, newCursor)); } cursor = newCursor; } } return ret; }
void ROrthoGrid::paintGridLines(const RVector& space, const RBox& box, bool meta) { if (!space.isValid()) { return; } // updates cache if necessary: getProjection(); isIsometric(); RVector min = box.getCorner1(); RVector max = box.getCorner2(); double deltaX = max.x - min.x; double deltaY = max.y - min.y; if (deltaX / space.x > 1e3 || deltaY / space.y > 1e3) { return; } double dx = deltaY / tan(M_PI/6); if (isometric) { min.x -= dx; max.x += dx; } int c; double x; for (x=min.x, c=0; x<max.x; x+=space.x, c++) { //int x2 = RMath::mround(x/space.x); //if (!isometric || c%2==0) { if (isometric) { if (projection==RS::IsoTop || projection==RS::IsoRight) { view.paintGridLine(RLine(RVector(x, min.y), RVector(x+dx, max.y))); } if (projection==RS::IsoTop || projection==RS::IsoLeft) { view.paintGridLine(RLine(RVector(x, min.y), RVector(x-dx, max.y))); } // vertical grid lines: if (projection==RS::IsoRight || projection==RS::IsoLeft) { view.paintGridLine(RLine(RVector(x, min.y), RVector(x, max.y))); view.paintGridLine(RLine(RVector(x-space.x/2, min.y), RVector(x-space.x/2, max.y))); } } else { view.paintGridLine(RLine(RVector(x, min.y), RVector(x, max.y))); } //} } // horizontal lines: if (!isometric) { for (double y=min.y; y<max.y; y+=space.y) { view.paintGridLine(RLine(RVector(min.x, y), RVector(max.x, y))); } } }
bool RDimRotatedData::moveReferencePoint(const RVector& referencePoint, const RVector& targetPoint) { // if definition point and extension points are on one line, // move the extension points together with the definition point: bool moveExtensionPoints = false; if (referencePoint.equalsFuzzy(definitionPoint)) { if (RLine(extensionPoint1, extensionPoint2).isOnShape(definitionPoint, false)) { moveExtensionPoints = true; } } bool ret = RDimLinearData::moveReferencePoint(referencePoint, targetPoint); if (moveExtensionPoints) { // move extension points with definition point: RVector dir = RVector::createPolar(1.0, rotation); RLine dimLine = RLine(targetPoint, targetPoint + dir); extensionPoint1 = dimLine.getClosestPointOnShape(extensionPoint1, false); extensionPoint2 = dimLine.getClosestPointOnShape(extensionPoint2, false); definitionPoint = RVector::getAverage(extensionPoint1, extensionPoint2); //recomputeDefinitionPoint(referencePoint, targetPoint); } return ret; }
int EBuffer::KillWord() { int Y = VToR(CP.Row); if (CP.Col >= LineLen()) { if (KillChar() == 0) return 0; } else { PELine L = RLine(Y); int P = CharOffset(L, CP.Col); int C; int Class = ChClassK(L->Chars[P]); while ((P < L->Count) && (ChClassK(L->Chars[P]) == Class)) P++; C = ScreenPos(L, P); if (DelText(Y, CP.Col, C - CP.Col) == 0) return 0; } return 1; }
int EBuffer::KillWordPrev() { int Y = VToR(CP.Row); if (CP.Col == 0) { if (KillCharPrev() == 0) return 0; } else if (CP.Col > LineLen()) { if (SetPos(LineLen(), CP.Row) == 0) return 0; } else { PELine L = RLine(Y); int P = CharOffset(L, CP.Col); int C; int Class = ChClassK(L->Chars[P - 1]); while ((P > 0) && (ChClassK(L->Chars[P - 1]) == Class)) P--; C = ScreenPos(L, P); if (DelText(Y, C, CP.Col - C) == 0) return 0; if (SetPos(C, CP.Row) == 0) return 0; } return 1; }
int EBuffer::BlockSelectWord() { int Y = VToR(CP.Row); PELine L = RLine(Y); int P; int C; if (BlockUnmark() == 0) return 0; BlockMode = bmStream; P = CharOffset(L, CP.Col); if (P >= L->Count) return 0; C = ChClassK(L->Chars[P]); while ((P > 0) && (C == ChClassK(L->Chars[P - 1]))) P--; if (SetBB(EPoint(Y, ScreenPos(L, P))) == 0) return 0; while ((P < L->Count) && (C == ChClassK(L->Chars[P]))) P++; if (SetBE(EPoint(Y, ScreenPos(L, P))) == 0) return 0; return 1; }
int EBuffer::ScanForRoutines() { RxNode *regx; int line; PELine L; RxMatchRes res; if (BFS(this, BFS_RoutineRegexp) == 0) { View->MView->Win->Choice(GPC_ERROR, "Error", 1, "O&K", "No routine regexp."); return 0; } regx = RxCompile(BFS(this, BFS_RoutineRegexp)); if (regx == 0) { View->MView->Win->Choice(GPC_ERROR, "Error", 1, "O&K", "Failed to compile regexp '%s'", BFS(this, BFS_RoutineRegexp)); return 0; } if (rlst.Lines) { free(rlst.Lines); rlst.Lines = 0; } rlst.Lines = 0; rlst.Count = 0; Msg(S_BUSY, "Matching %s", BFS(this, BFS_RoutineRegexp)); for (line = 0; line < RCount; line++) { L = RLine(line); if (RxExec(regx, L->Chars, L->Count, L->Chars, &res) == 1) { rlst.Count++; rlst.Lines = (int *) realloc((void *) rlst.Lines, sizeof(int) * (rlst.Count | 0x1F)); rlst.Lines[rlst.Count - 1] = line; Msg(S_BUSY, "Routines: %d", rlst.Count); } } RxFree(regx); return 1; }
void RExporter::exportArcSegment(const RArc& arc) { double segmentLength; if (pixelSizeHint>0.0) { // approximate arc with segments with the length of 2 pixels: segmentLength = pixelSizeHint * 2; } else { segmentLength = arc.getRadius() / 40.0; } // avoid a segment length of 0: if (segmentLength<1.0e-4) { segmentLength = 1.0e-4; } double a1 = arc.getStartAngle(); double a2 = arc.getEndAngle(); RVector center = arc.getCenter(); double radius = arc.getRadius(); // avoid huge radius and slow down to almost stand-still: if (radius>1.0e6) { return; } double aStep; if (radius<1.0e-3) { aStep = 0.1; } else { aStep = segmentLength / radius; if (aStep>1.0) { aStep = 1.0; } double minAStep = 2*M_PI/360.0; if (!draftMode) { minAStep /= 4; } if (aStep<minAStep) { aStep = minAStep; } } RVector prev = arc.getStartPoint(); RVector ci; double a; if(!arc.isReversed()) { // Arc Counterclockwise: if(a1>a2-RS::AngleTolerance) { a2+=2*M_PI; } for(a=a1+aStep; a<=a2; a+=aStep) { ci.x = center.x + cos(a) * radius; ci.y = center.y + sin(a) * radius; //path.lineTo(RVector(ci.x, ci.y)); this->exportLineSegment(RLine(prev, ci)); prev = ci; } } else { // Arc Clockwise: if(a1<a2+RS::AngleTolerance) { a2-=2*M_PI; } for(a=a1-aStep; a>=a2; a-=aStep) { ci.x = center.x + cos(a) * radius; ci.y = center.y + sin(a) * radius; this->exportLineSegment(RLine(prev, ci)); //path.lineTo(RVector(cix, ciy)); prev = ci; } } this->exportLineSegment(RLine(prev, arc.getEndPoint())); //path.lineTo(arc.getEndPoint()); }
void RExporter::exportLine(const RLine& line, double offset) { if (!line.isValid()) { return; } double length = line.getLength(); if (length>1e100 || length<RS::PointTolerance) { return; } RLinetypePattern p = getLinetypePattern(); // continuous line or // we are in draft mode or // QCAD is configured to show screen based line patterns if (!p.isValid() || p.getNumDashes() == 1 || draftMode || screenBasedLinetypes) { exportLineSegment(line); return; } p.scale(getPatternFactor()); double patternLength = p.getPatternLength(); // avoid huge number of small segments due to very fine // pattern or long lines: if (patternLength<RS::PointTolerance || length / patternLength > 5000) { exportLineSegment(line); return; } double angle = line.getAngle(); RVector* vp = NULL; vp = new RVector[p.getNumDashes()]; for (int i = 0; i < p.getNumDashes(); ++i) { vp[i] = RVector(cos(angle) * fabs(p.getDashLengthAt(i)), sin(angle) * fabs(p.getDashLengthAt(i))); } bool optimizeEnds = false; if (RMath::isNaN(offset)) { offset = getPatternOffset(length, p); optimizeEnds = true; } else { double num = ceil(offset / patternLength); offset -= num * patternLength; } bool done = false; int i = 0; RVector cursor(line.getStartPoint() + RVector::createPolar(offset, angle)); double total = offset; bool dashFound = false; bool gapFound = false; RVector p1 = line.getStartPoint(); RVector p2 = p1; do { if (dashFound && !gapFound) { // don't shoot over end of line: if (total + fabs(p.getDashLengthAt(i)) >= length - 1.0e-6) { if (optimizeEnds) { exportLineSegment(RLine(p1, line.endPoint)); } else { exportLineSegment(RLine(p1, p2)); } break; } exportLineSegment(RLine(p1, p2)); } // dash, no gap. note that a dash can have a length of 0.0 (point): if (p.getDashLengthAt(i) > -RS::PointTolerance) { // check if we're on the line already: if (total + p.getDashLengthAt(i) > 0) { p1 = cursor; // no gap at the beginning of the line: if (total < 0 || (!dashFound && optimizeEnds)) { p1 = line.startPoint; } p2 = cursor + vp[i]; if (!p2.equalsFuzzy(line.startPoint, 1.0e-6)) { dashFound = true; } } gapFound = false; } // gap: else { gapFound = true; } cursor += vp[i]; total += fabs(p.getDashLengthAt(i)); done = total > length; ++i; if (i >= p.getNumDashes()) { i = 0; } } while (!done); if (!gapFound || !dashFound) { if (total + fabs(p.getDashLengthAt(i)) >= length - 1.0e-6) { if (optimizeEnds || (total>length && !gapFound)) { exportLineSegment(RLine(p1, line.endPoint)); } else { exportLineSegment(RLine(p1, p2)); } } else { exportLineSegment(RLine(p1, p2)); } } delete[] vp; }