File size: 4,727 Bytes
a5ffdcd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | /*
* ********************************************************************************
* This file is part of the LibreCAD project, a 2D CAD program
*
* Copyright (C) 2025 LibreCAD.org
* Copyright (C) 2025 sand1024
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* ********************************************************************************
*/
#include "lc_dimarrowblockpoly.h"
#include <boost/next_prior.hpp>
LC_DimArrowPoly::LC_DimArrowPoly(RS_EntityContainer* parent, const RS_Vector &pos, double angle, double size)
: LC_DimArrow(parent,pos,angle,size) {
}
RS_Vector LC_DimArrowPoly::getNearestEndpoint(const RS_Vector& coord, double* dist /*= nullptr*/) const {
double minDist{RS_MAXDOUBLE};
double curDist{0.0};
RS_Vector ret;
for (const auto vertex : m_vertices) {
curDist = vertex.distanceTo(coord);
if (curDist < minDist) {
ret = vertex;
minDist = curDist;
}
}
auto pos = getPosition();
curDist = pos.distanceTo(coord);
if (curDist < minDist) {
ret = pos;
minDist = curDist;
}
setDistPtr(dist, minDist);
return ret;
}
RS_Vector LC_DimArrowPoly::getNearestPointOnEntity(const RS_Vector& coord, bool onEntity, double* dist,
[[maybe_unused]]RS_Entity** entity) const {
//
// this is not exact and quite generic implementation.
// it skips specifics of the geometry and relies on vertexes only.
// however, for most cases for arrows it should be fine.
// Actually, the major reason for bothering with nearest points -
// is just to ensure that the entire dimension entity may be caught by
// catchEntity(..) if the mouse hovers over the arrow entity.
// All arrows are not full-fledge persistent entities, they are just
// used for drawing as part of dimension ...
RS_Vector ret(false);
double currDist {RS_MAXDOUBLE};
int next;
size_t lastIndex = m_vertices.size() - 2;
for (size_t i = 0; i <= lastIndex; i++) {
next = i + 1;
auto current = m_vertices[i];
RS_Vector direction {m_vertices[next] - current};
RS_Vector vpc {coord-current};
double a {direction.squared()};
if( a < RS_TOLERANCE2) {
//line too short
vpc = current;
}
else{
//find projection on line
vpc = current + direction * RS_Vector::dotP( vpc, direction) / a;
}
double tmpDist = vpc.distanceTo( coord);
if (tmpDist < currDist) {
currDist = tmpDist;
ret = vpc;
}
}
if (onEntity && !ret.isInWindowOrdered( minV, maxV)) {
// projection point not within range, find the nearest endpoint
ret = getNearestEndpoint( coord, dist);
currDist = ret.distanceTo( coord);
}
setDistPtr( dist, currDist);
return ret;
}
void LC_DimArrowPoly::positionFromZero() {
RS_Vector angleVector(getAngle());
positionDimLinePointFromZero(angleVector);
auto position = getPosition();
for (auto& vertex : m_vertices) {
vertex.move(position);
vertex.rotate(position, angleVector);
}
calculateBorders();
}
void LC_DimArrowPoly::doCalculateBorders() {
for (const auto vertex : m_vertices) {
minV = RS_Vector::minimum(minV, vertex);
maxV = RS_Vector::maximum(maxV, vertex);
}
}
void LC_DimArrowPoly::doMove(const RS_Vector& offset) {
for (auto& vertex : m_vertices) {
vertex.move(offset);
}
}
void LC_DimArrowPoly::doRotate(const RS_Vector& center, const RS_Vector& angleVector) {
for (auto& vertex : m_vertices) {
vertex.rotate(center, angleVector);
}
}
void LC_DimArrowPoly::doScale(const RS_Vector& center, const RS_Vector& factor) {
for (auto& vertex : m_vertices) {
vertex.scale(center, factor);
}
}
void LC_DimArrowPoly::doMirror(const RS_Vector& axisPoint1, const RS_Vector& axisPoint2) {
for (auto& vertex : m_vertices) {
vertex.mirror(axisPoint1, axisPoint2);
}
}
|