X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Arc.cpp;h=0eb84450c4e5dbbbf75634280721b4d011754fde;hb=06e7f5859095193fc7f498bd89a7d28009794f53;hp=9ebf16eb34205e343f114a511be0a5eb0e9ba60f;hpb=0055749835b1aca56e3dc0ec14718c775f438b5c;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Arc.cpp b/src/SketchPlugin/SketchPlugin_Arc.cpp index 9ebf16eb3..0eb84450c 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.cpp +++ b/src/SketchPlugin/SketchPlugin_Arc.cpp @@ -1,8 +1,21 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: SketchPlugin_Arc.cpp -// Created: 26 Apr 2014 -// Author: Artem ZHIDKOV +// Copyright (C) 2014-2023 CEA, EDF +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// #include "SketchPlugin_Arc.h" #include "SketchPlugin_Sketch.h" @@ -37,11 +50,11 @@ #include #include // for sqrt on Linux -#include +#include -const double tolerance = 1e-7; -const double paramTolerance = 1.e-4; -const double PI = 3.141592653589793238463; +static const double tolerance = 1e-7; +static const double paramTolerance = 1.e-4; +static const double PI = 3.141592653589793238463; SketchPlugin_Arc::SketchPlugin_Arc() @@ -99,44 +112,47 @@ void SketchPlugin_Arc::execute() aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); std::shared_ptr aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z())); - GeomShapePtr anArcShape = boolean(REVERSED_ID())->value() ? - GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal) - : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal); - - std::shared_ptr aResult = document()->createConstruction(data(), 1); - aResult->setShape(anArcShape); - aResult->setIsInHistory(false); - setResult(aResult, 1); -} - -void SketchPlugin_Arc::move(double theDeltaX, double theDeltaY) -{ - std::shared_ptr aData = data(); - if(!aData->isValid()) { - return; + if (myParamBefore == 0) { // parameter has not been calculate yet + std::shared_ptr aCircleForArc( + new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); + aCircleForArc->parameter(anEndAttr->pnt(), paramTolerance, myParamBefore); } - bool aWasBlocked = aData->blockSendAttributeUpdated(true); - - std::shared_ptr aCenter = std::dynamic_pointer_cast( - attribute(CENTER_ID())); - if(aCenter->isInitialized()) { - aCenter->move(theDeltaX, theDeltaY); - } + bool isReversed = boolean(REVERSED_ID())->value(); - std::shared_ptr aStart = std::dynamic_pointer_cast( - attribute(START_ID())); - if(aStart->isInitialized()) { - aStart->move(theDeltaX, theDeltaY); + GeomEdgePtr anArcShape; + if (fabs(myParamBefore - 2.0 * PI) < paramTolerance) { + anArcShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aStart->distance(aCenter)); + myParamBefore = 0; + } else { + anArcShape = isReversed ? + GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal) + : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal); } - std::shared_ptr anEnd = std::dynamic_pointer_cast( - attribute(END_ID())); - if(anEnd->isInitialized()) { - anEnd->move(theDeltaX, theDeltaY); + // calculate tolerances for start and end points of the arc and set them to the result shape + // (this is done to fix gaps which appear because of inaccurate computation of arcs in PlaneGCS, + // which leads to difference in SketchPlugin_Arc attributes and boundary points of result shape) + if (anArcShape) { + for (int ind = 0; ind < 2; ++ind) { + bool isFirst = ind == 0; + GeomPointPtr anArcBndPoint = isFirst == isReversed ? anEnd : aStart; + GeomPointPtr aShapePoint = isFirst ? anArcShape->firstPoint() : anArcShape->lastPoint(); + double aDistance = anArcBndPoint->distance(aShapePoint); + // avoid setting too high tolerance because it may be caused by incomplete update of an arc + if (aDistance > tolerance && aDistance < 100. * tolerance) { + if (isFirst) + anArcShape->setFirstPointTolerance(aDistance); + else + anArcShape->setLastPointTolerance(aDistance); + } + } } - aData->blockSendAttributeUpdated(aWasBlocked); + std::shared_ptr aResult = document()->createConstruction(data(), 1); + aResult->setShape(anArcShape); + aResult->setIsInHistory(false); + setResult(aResult, 1); } bool SketchPlugin_Arc::isFixed() @@ -190,8 +206,17 @@ void SketchPlugin_Arc::attributeChanged(const std::string& theID) aCirc->parameter(anEdge->firstPoint(), paramTolerance, aStartParam); aCirc->parameter(aMinPnt, paramTolerance, aMidParam); aCirc->parameter(anEdge->lastPoint(), paramTolerance, anEndParam); + + // adjust period + anEndParam -= aStartParam; + aMidParam -= aStartParam; + if (anEndParam < 0.0) + anEndParam += 2.0 * PI; + if (aMidParam < 0.0) + aMidParam += 2.0 * PI; + aWasBlocked = data()->blockSendAttributeUpdated(true); - if(aStartParam < aMidParam && aMidParam < anEndParam) { + if(aMidParam < anEndParam) { setReversed(false); } else { setReversed(true); @@ -213,31 +238,28 @@ void SketchPlugin_Arc::attributeChanged(const std::string& theID) return; std::shared_ptr aCircleForArc(new GeomAPI_Circ2d(aCenter, aStart)); - bool aWasBlocked = data()->blockSendAttributeUpdated(true); - // The Arc end point is projected - // on the circle formed by center and start points + // Do not recalculate REVERSED flag if the arc is not consistent std::shared_ptr aProjection = aCircleForArc->project(anEnd); - if (aProjection && anEnd->distance(aProjection) > tolerance) { - anEndAttr->setValue(aProjection); - anEnd = aProjection; - } - data()->blockSendAttributeUpdated(aWasBlocked, false); - - double aParameterNew = 0.0; - if(aCircleForArc->parameter(anEnd, paramTolerance, aParameterNew)) { - bool aWasBlocked = data()->blockSendAttributeUpdated(true); - if(myParamBefore <= PI / 2.0 && aParameterNew >= PI * 1.5) { - if(!boolean(REVERSED_ID())->value()) { - boolean(REVERSED_ID())->setValue(true); - } - } else if(myParamBefore >= PI * 1.5 && aParameterNew <= PI / 2.0) { - if(boolean(REVERSED_ID())->value()) { - boolean(REVERSED_ID())->setValue(false); + if (aProjection && anEnd->distance(aProjection) <= tolerance) { + double aParameterNew = 0.0; + if(aCircleForArc->parameter(anEnd, paramTolerance, aParameterNew)) { + bool aWasBlocked = data()->blockSendAttributeUpdated(true); + if(myParamBefore <= PI / 2.0 && aParameterNew >= PI * 1.5) { + if(!boolean(REVERSED_ID())->value()) { + boolean(REVERSED_ID())->setValue(true); + } + } else if(myParamBefore >= PI * 1.5 && aParameterNew <= PI / 2.0) { + if(boolean(REVERSED_ID())->value()) { + boolean(REVERSED_ID())->setValue(false); + } } + data()->blockSendAttributeUpdated(aWasBlocked, false); } - data()->blockSendAttributeUpdated(aWasBlocked, false); + if (fabs(aParameterNew) < paramTolerance || + fabs(aParameterNew - 2.0 * PI) < paramTolerance) + aParameterNew = 2.0 * PI; + myParamBefore = aParameterNew; } - myParamBefore = aParameterNew; } double aRadius = 0;