Allow DXF import of 3D arcs and circles
Extrusion direction (normal) of arcs and circles were not taken into account when importing. - Add method for calculating a quaternion from extrusion direction according to DXF arbitrary axis algorithm - Add required workplanes for arcs not on XY origin plane - Adjust addDimRadial and addDimDiametric to include normal when creating associated circle request
This commit is contained in:
parent
6b7f114697
commit
3ce8c29982
@ -1 +1 @@
|
|||||||
Subproject commit 03fa5f30f1a1db7231a25653c9dd38044fe06640
|
Subproject commit 0b7b7b709d9299565db603f878214656ef5e9ddf
|
@ -9,6 +9,21 @@ static std::string ToUpper(std::string str) {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Quaternion NormalFromExtPoint(Vector extPoint) {
|
||||||
|
// DXF arbitrary axis algorithm for transforming a Z-vector into a rotated
|
||||||
|
// coordinate system
|
||||||
|
Vector ax, ay;
|
||||||
|
Vector az = extPoint.WithMagnitude(1.0);
|
||||||
|
|
||||||
|
if ((fabs(az.x) < 1/64.) && (fabs(az.y) < 1/64.)) {
|
||||||
|
ax = Vector::From(0, 1, 0).Cross(az).WithMagnitude(1.0);
|
||||||
|
} else {
|
||||||
|
ax = Vector::From(0, 0, 1).Cross(az).WithMagnitude(1.0);
|
||||||
|
}
|
||||||
|
ay = az.Cross(ax).WithMagnitude(1.0);
|
||||||
|
return Quaternion::From(ax, ay);
|
||||||
|
}
|
||||||
|
|
||||||
class DxfImport : public DRW_Interface {
|
class DxfImport : public DRW_Interface {
|
||||||
public:
|
public:
|
||||||
Vector blockX;
|
Vector blockX;
|
||||||
@ -516,12 +531,41 @@ public:
|
|||||||
return hr.entity(0);
|
return hr.entity(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
hEntity createCircle(const Vector &c, double r, hStyle style) {
|
hEntity createWorkplane(const Vector &p, const Quaternion &q) {
|
||||||
|
hRequest hr = SS.GW.AddRequest(Request::Type::WORKPLANE, /*rememberForUndo=*/false);
|
||||||
|
SK.GetEntity(hr.entity(1))->PointForceTo(p);
|
||||||
|
processPoint(hr.entity(1));
|
||||||
|
SK.GetEntity(hr.entity(32))->NormalForceTo(q);
|
||||||
|
return hr.entity(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
hEntity findOrCreateWorkplane(const Vector &p, const Quaternion &q) {
|
||||||
|
Vector z = q.RotationN();
|
||||||
|
for(auto &r : SK.request) {
|
||||||
|
if((r.type == Request::Type::WORKPLANE) && (r.group == SS.GW.activeGroup)) {
|
||||||
|
Vector wp = SK.GetEntity(r.h.entity(1))->PointGetNum();
|
||||||
|
Vector wz = SK.GetEntity(r.h.entity(32))->NormalN();
|
||||||
|
|
||||||
|
if ((p.DistanceToPlane(wz, wp) < LENGTH_EPS) && z.Equals(wz)) {
|
||||||
|
return r.h.entity(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return createWorkplane(p, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void activateWorkplane(hEntity he) {
|
||||||
|
Group *g = SK.GetGroup(SS.GW.activeGroup);
|
||||||
|
g->activeWorkplane = he;
|
||||||
|
}
|
||||||
|
|
||||||
|
hEntity createCircle(const Vector &c, const Quaternion &q, double r, hStyle style) {
|
||||||
hRequest hr = SS.GW.AddRequest(Request::Type::CIRCLE, /*rememberForUndo=*/false);
|
hRequest hr = SS.GW.AddRequest(Request::Type::CIRCLE, /*rememberForUndo=*/false);
|
||||||
SK.GetEntity(hr.entity(1))->PointForceTo(c);
|
SK.GetEntity(hr.entity(1))->PointForceTo(c);
|
||||||
processPoint(hr.entity(1));
|
processPoint(hr.entity(1));
|
||||||
|
SK.GetEntity(hr.entity(32))->NormalForceTo(q);
|
||||||
SK.GetEntity(hr.entity(64))->DistanceForceTo(r);
|
SK.GetEntity(hr.entity(64))->DistanceForceTo(r);
|
||||||
|
|
||||||
configureRequest(hr, style);
|
configureRequest(hr, style);
|
||||||
return hr.entity(0);
|
return hr.entity(0);
|
||||||
}
|
}
|
||||||
@ -560,13 +604,25 @@ public:
|
|||||||
if(data.space != DRW::ModelSpace) return;
|
if(data.space != DRW::ModelSpace) return;
|
||||||
if(addPendingBlockEntity<DRW_Arc>(data)) return;
|
if(addPendingBlockEntity<DRW_Arc>(data)) return;
|
||||||
|
|
||||||
hRequest hr = SS.GW.AddRequest(Request::Type::ARC_OF_CIRCLE, /*rememberForUndo=*/false);
|
|
||||||
double r = data.radious;
|
double r = data.radious;
|
||||||
double sa = data.staangle;
|
double sa = data.staangle;
|
||||||
double ea = data.endangle;
|
double ea = data.endangle;
|
||||||
Vector c = Vector::From(data.basePoint.x, data.basePoint.y, data.basePoint.z);
|
Vector c = toVector(data.basePoint);
|
||||||
Vector rvs = Vector::From(r * cos(sa), r * sin(sa), data.basePoint.z).Plus(c);
|
Vector nz = toVector(data.extPoint);
|
||||||
Vector rve = Vector::From(r * cos(ea), r * sin(ea), data.basePoint.z).Plus(c);
|
Quaternion q = NormalFromExtPoint(nz);
|
||||||
|
|
||||||
|
bool planar = q.RotationN().Equals(Vector::From(0, 0, 1));
|
||||||
|
bool onPlane = c.z < LENGTH_EPS;
|
||||||
|
|
||||||
|
hEntity oldWorkplane = SS.GW.ActiveWorkplane();
|
||||||
|
if (!planar || !onPlane) {
|
||||||
|
activateWorkplane(findOrCreateWorkplane(c, q));
|
||||||
|
}
|
||||||
|
|
||||||
|
hRequest hr = SS.GW.AddRequest(Request::Type::ARC_OF_CIRCLE, /*rememberForUndo=*/false);
|
||||||
|
Vector u = q.RotationU(), v = q.RotationV();
|
||||||
|
Vector rvs = c.Plus(u.ScaledBy(r * cos(sa))).Plus(v.ScaledBy(r * sin(sa)));
|
||||||
|
Vector rve = c.Plus(u.ScaledBy(r * cos(ea))).Plus(v.ScaledBy(r * sin(ea)));
|
||||||
|
|
||||||
if(data.extPoint.z == -1.0) {
|
if(data.extPoint.z == -1.0) {
|
||||||
c.x = -c.x;
|
c.x = -c.x;
|
||||||
@ -584,13 +640,16 @@ public:
|
|||||||
processPoint(hr.entity(2));
|
processPoint(hr.entity(2));
|
||||||
processPoint(hr.entity(3));
|
processPoint(hr.entity(3));
|
||||||
configureRequest(hr, styleFor(&data));
|
configureRequest(hr, styleFor(&data));
|
||||||
|
activateWorkplane(oldWorkplane);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addCircle(const DRW_Circle &data) override {
|
void addCircle(const DRW_Circle &data) override {
|
||||||
if(data.space != DRW::ModelSpace) return;
|
if(data.space != DRW::ModelSpace) return;
|
||||||
if(addPendingBlockEntity<DRW_Circle>(data)) return;
|
if(addPendingBlockEntity<DRW_Circle>(data)) return;
|
||||||
|
|
||||||
createCircle(toVector(data.basePoint), data.radious, styleFor(&data));
|
Vector nz = toVector(data.extPoint);
|
||||||
|
Quaternion normal = NormalFromExtPoint(nz);
|
||||||
|
createCircle(toVector(data.basePoint), normal, data.radious, styleFor(&data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addLWPolyline(const DRW_LWPolyline &data) override {
|
void addLWPolyline(const DRW_LWPolyline &data) override {
|
||||||
@ -835,9 +894,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hConstraint createDiametric(Vector cp, double r, Vector tp, double actual,
|
hConstraint createDiametric(Vector cp, Quaternion q, double r, Vector tp,
|
||||||
bool asRadius = false) {
|
double actual, bool asRadius = false) {
|
||||||
hEntity he = createCircle(cp, r, invisibleStyle());
|
hEntity he = createCircle(cp, q, r, invisibleStyle());
|
||||||
|
|
||||||
hConstraint hc = Constraint::Constrain(
|
hConstraint hc = Constraint::Constrain(
|
||||||
Constraint::Type::DIAMETER,
|
Constraint::Type::DIAMETER,
|
||||||
@ -869,7 +928,9 @@ public:
|
|||||||
actual = data->getActualMeasurement();
|
actual = data->getActualMeasurement();
|
||||||
}
|
}
|
||||||
|
|
||||||
createDiametric(cp, cp.Minus(dp).Magnitude(), tp, actual, /*asRadius=*/true);
|
Vector nz = toVector(data->getExtrusion());
|
||||||
|
Quaternion q = NormalFromExtPoint(nz);
|
||||||
|
createDiametric(cp, q, cp.Minus(dp).Magnitude(), tp, actual, /*asRadius=*/true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addDimDiametric(const DRW_DimDiametric *data) override {
|
void addDimDiametric(const DRW_DimDiametric *data) override {
|
||||||
@ -886,7 +947,9 @@ public:
|
|||||||
actual = data->getActualMeasurement();
|
actual = data->getActualMeasurement();
|
||||||
}
|
}
|
||||||
|
|
||||||
createDiametric(cp, cp.Minus(dp1).Magnitude(), tp, actual, /*asRadius=*/false);
|
Vector nz = toVector(data->getExtrusion());
|
||||||
|
Quaternion q = NormalFromExtPoint(nz);
|
||||||
|
createDiametric(cp, q, cp.Minus(dp1).Magnitude(), tp, actual, /*asRadius=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addDimAngular3P(const DRW_DimAngular3p *data) override {
|
void addDimAngular3P(const DRW_DimAngular3p *data) override {
|
||||||
@ -972,11 +1035,13 @@ public:
|
|||||||
void addArc(const DRW_Arc &data) override {
|
void addArc(const DRW_Arc &data) override {
|
||||||
if(data.space != DRW::ModelSpace) return;
|
if(data.space != DRW::ModelSpace) return;
|
||||||
checkCoord(data.basePoint);
|
checkCoord(data.basePoint);
|
||||||
|
checkExt(data.extPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addCircle(const DRW_Circle &data) override {
|
void addCircle(const DRW_Circle &data) override {
|
||||||
if(data.space != DRW::ModelSpace) return;
|
if(data.space != DRW::ModelSpace) return;
|
||||||
checkCoord(data.basePoint);
|
checkCoord(data.basePoint);
|
||||||
|
checkExt(data.extPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPolyline(const DRW_Polyline &data) override {
|
void addPolyline(const DRW_Polyline &data) override {
|
||||||
@ -1041,6 +1106,7 @@ public:
|
|||||||
checkCoord(data->getCenterPoint());
|
checkCoord(data->getCenterPoint());
|
||||||
checkCoord(data->getDiameterPoint());
|
checkCoord(data->getDiameterPoint());
|
||||||
checkCoord(data->getTextPoint());
|
checkCoord(data->getTextPoint());
|
||||||
|
checkExt(data->getExtrusion());
|
||||||
}
|
}
|
||||||
|
|
||||||
void addDimDiametric(const DRW_DimDiametric *data) override {
|
void addDimDiametric(const DRW_DimDiametric *data) override {
|
||||||
@ -1048,6 +1114,7 @@ public:
|
|||||||
checkCoord(data->getDiameter1Point());
|
checkCoord(data->getDiameter1Point());
|
||||||
checkCoord(data->getDiameter2Point());
|
checkCoord(data->getDiameter2Point());
|
||||||
checkCoord(data->getTextPoint());
|
checkCoord(data->getTextPoint());
|
||||||
|
checkExt(data->getExtrusion());
|
||||||
}
|
}
|
||||||
|
|
||||||
void addDimAngular3P(const DRW_DimAngular3p *data) override {
|
void addDimAngular3P(const DRW_DimAngular3p *data) override {
|
||||||
@ -1066,6 +1133,12 @@ public:
|
|||||||
is3d = true;
|
is3d = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void checkExt(const DRW_Coord &coord) {
|
||||||
|
if ((fabs(coord.x) > 1/64.) || (fabs(coord.y) > 1/64.)) {
|
||||||
|
is3d = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1112,14 +1185,14 @@ ImportDwgDxf(const Platform::Path &filename,
|
|||||||
void ImportDxf(const Platform::Path &filename) {
|
void ImportDxf(const Platform::Path &filename) {
|
||||||
ImportDwgDxf(filename, [](const std::string &data, DRW_Interface *intf) {
|
ImportDwgDxf(filename, [](const std::string &data, DRW_Interface *intf) {
|
||||||
std::stringstream stream(data);
|
std::stringstream stream(data);
|
||||||
return dxfRW().read(stream, intf, /*ext=*/false);
|
return dxfRW().read(stream, intf, /*ext=*/true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImportDwg(const Platform::Path &filename) {
|
void ImportDwg(const Platform::Path &filename) {
|
||||||
ImportDwgDxf(filename, [](const std::string &data, DRW_Interface *intf) {
|
ImportDwgDxf(filename, [](const std::string &data, DRW_Interface *intf) {
|
||||||
std::stringstream stream(data);
|
std::stringstream stream(data);
|
||||||
return dwgR().read(stream, intf, /*ext=*/false);
|
return dwgR().read(stream, intf, /*ext=*/true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user