|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
// TnzTools includes
|
|
|
850a0b |
#include <tools replicator.h=""></tools>
|
|
|
850a0b |
#include <tools modifierclone.h="" modifiers=""></tools>
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
// TnzCore includes
|
|
|
850a0b |
#include <tgl.h></tgl.h>
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
//*****************************************************************************************
|
|
|
850a0b |
// TReplicatorGrid implementation
|
|
|
850a0b |
//*****************************************************************************************
|
|
|
850a0b |
|
|
|
850a0b |
class TReplicatorGrid final : public TReplicator {
|
|
|
850a0b |
Q_DECLARE_TR_FUNCTIONS(TReplicatorAffine)
|
|
|
850a0b |
public:
|
|
|
850a0b |
const TStringId m_idFixAngle;
|
|
|
850a0b |
const TStringId m_idFixSkew;
|
|
|
850a0b |
const TStringId m_idMirrorA;
|
|
|
850a0b |
const TStringId m_idMirrorB;
|
|
|
850a0b |
const TStringId m_idCountA;
|
|
|
850a0b |
const TStringId m_idCountAInv;
|
|
|
850a0b |
const TStringId m_idCountB;
|
|
|
850a0b |
const TStringId m_idCountBInv;
|
|
|
850a0b |
|
|
|
850a0b |
protected:
|
|
|
850a0b |
TAssistantPoint &m_center;
|
|
|
850a0b |
TAssistantPoint &m_a;
|
|
|
850a0b |
TAssistantPoint &m_b;
|
|
|
850a0b |
|
|
|
850a0b |
public:
|
|
|
850a0b |
TReplicatorGrid(TMetaObject &object):
|
|
|
850a0b |
TReplicator(object),
|
|
|
850a0b |
m_idFixAngle("fixAngle"),
|
|
|
850a0b |
m_idFixSkew("fixSkew"),
|
|
|
850a0b |
m_idMirrorA("mirrorA"),
|
|
|
850a0b |
m_idMirrorB("mirrorB"),
|
|
|
850a0b |
m_idCountA("countA"),
|
|
|
850a0b |
m_idCountAInv("countAInv"),
|
|
|
850a0b |
m_idCountB("countB"),
|
|
|
850a0b |
m_idCountBInv("countBInv"),
|
|
|
850a0b |
m_center( addPoint("center", TAssistantPoint::CircleCross) ),
|
|
|
850a0b |
m_a ( addPoint("a", TAssistantPoint::CircleFill, TPointD(80, 0)) ),
|
|
|
850a0b |
m_b ( addPoint("b", TAssistantPoint::Circle, TPointD( 0, -80)) )
|
|
|
850a0b |
{
|
|
|
850a0b |
addProperty( new TBoolProperty(m_idFixAngle.str(), getFixAngle()) );
|
|
|
850a0b |
addProperty( new TBoolProperty(m_idFixSkew.str(), getFixSkew()) );
|
|
|
850a0b |
addProperty( new TBoolProperty(m_idMirrorA.str(), getMirrorA()) );
|
|
|
850a0b |
addProperty( new TBoolProperty(m_idMirrorB.str(), getMirrorB()) );
|
|
|
850a0b |
addProperty( createCountProperty(m_idCountA, getCountA(), 1) );
|
|
|
850a0b |
addProperty( createCountProperty(m_idCountAInv, getCountAInv(), 0) );
|
|
|
850a0b |
addProperty( createCountProperty(m_idCountB, getCountB(), 1) );
|
|
|
850a0b |
addProperty( createCountProperty(m_idCountBInv, getCountBInv(), 0) );
|
|
|
850a0b |
}
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
static QString getLocalName()
|
|
|
850a0b |
{ return tr("Replicator Grid"); }
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
void updateTranslation() const override {
|
|
|
850a0b |
TReplicator::updateTranslation();
|
|
|
850a0b |
setTranslation(m_idFixAngle, tr("Fix Angle"));
|
|
|
850a0b |
setTranslation(m_idFixSkew, tr("Fix Skew"));
|
|
|
850a0b |
setTranslation(m_idMirrorA, tr("Mirror A"));
|
|
|
850a0b |
setTranslation(m_idMirrorB, tr("Mirror B"));
|
|
|
850a0b |
setTranslation(m_idCountA, tr("Count A"));
|
|
|
850a0b |
setTranslation(m_idCountAInv, tr("Inv. Count A"));
|
|
|
850a0b |
setTranslation(m_idCountB, tr("Count B"));
|
|
|
850a0b |
setTranslation(m_idCountBInv, tr("Inv. Count B"));
|
|
|
850a0b |
}
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
inline bool getFixAngle() const
|
|
|
850a0b |
{ return data()[m_idFixAngle].getBool(); }
|
|
|
850a0b |
inline bool getFixSkew() const
|
|
|
850a0b |
{ return data()[m_idFixSkew].getBool(); }
|
|
|
850a0b |
inline bool getMirrorA() const
|
|
|
850a0b |
{ return data()[m_idMirrorA].getBool(); }
|
|
|
850a0b |
inline bool getMirrorB() const
|
|
|
850a0b |
{ return data()[m_idMirrorB].getBool(); }
|
|
|
850a0b |
inline int getCountA() const
|
|
|
850a0b |
{ return (int)data()[m_idCountA].getDouble(); }
|
|
|
850a0b |
inline int getCountAInv() const
|
|
|
850a0b |
{ return (int)data()[m_idCountAInv].getDouble(); }
|
|
|
850a0b |
inline int getCountB() const
|
|
|
850a0b |
{ return (int)data()[m_idCountB].getDouble(); }
|
|
|
850a0b |
inline int getCountBInv() const
|
|
|
850a0b |
{ return (int)data()[m_idCountBInv].getDouble(); }
|
|
|
850a0b |
|
|
|
850a0b |
protected:
|
|
|
850a0b |
inline void setCountA(int x)
|
|
|
850a0b |
{ if (getCountA() != (double)x) data()[m_idCountA].setDouble((double)x); }
|
|
|
850a0b |
inline void setCountAInv(int x)
|
|
|
850a0b |
{ if (getCountAInv() != (double)x) data()[m_idCountAInv].setDouble((double)x); }
|
|
|
850a0b |
inline void setCountB(int x)
|
|
|
850a0b |
{ if (getCountB() != (double)x) data()[m_idCountB].setDouble((double)x); }
|
|
|
850a0b |
inline void setCountBInv(int x)
|
|
|
850a0b |
{ if (getCountBInv() != (double)x) data()[m_idCountBInv].setDouble((double)x); }
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
void onSetDefaults() override {
|
|
|
850a0b |
setCountA(4);
|
|
|
850a0b |
setCountB(4);
|
|
|
850a0b |
TReplicator::onSetDefaults();
|
|
|
850a0b |
}
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
void onFixData() override {
|
|
|
850a0b |
TReplicator::onFixData();
|
|
|
850a0b |
setCountA( std::max(1, std::min(multiplierSoftLimit, getCountA())) );
|
|
|
850a0b |
setCountAInv( std::max(0, std::min(multiplierSoftLimit, getCountAInv())) );
|
|
|
850a0b |
setCountB( std::max(1, std::min(multiplierSoftLimit, getCountB())) );
|
|
|
850a0b |
setCountBInv( std::max(0, std::min(multiplierSoftLimit, getCountBInv())) );
|
|
|
850a0b |
}
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
void onFixPoints() override {
|
|
|
850a0b |
TPointD &c = m_center.position;
|
|
|
850a0b |
TPointD &a = m_a.position;
|
|
|
850a0b |
TPointD &b = m_b.position;
|
|
|
850a0b |
|
|
|
850a0b |
if (getFixAngle()) {
|
|
|
850a0b |
double la = tdistance(a, c);
|
|
|
850a0b |
double lb = tdistance(b, c);
|
|
|
850a0b |
a = TPointD(a.x < c.x ? -la : la, 0) + c;
|
|
|
850a0b |
b = TPointD(0, b.y < c.y ? -lb : lb) + c;
|
|
|
850a0b |
} else
|
|
|
850a0b |
if (getFixSkew()) {
|
|
|
850a0b |
TPointD da = a - c;
|
|
|
850a0b |
double la = norm2(da);
|
|
|
850a0b |
if (la > TConsts::epsilon*TConsts::epsilon) {
|
|
|
850a0b |
TPointD db = b - c;
|
|
|
850a0b |
TPointD pa(-da.y, da.x);
|
|
|
850a0b |
double l = pa*db/la;
|
|
|
850a0b |
b = pa*l + c;
|
|
|
850a0b |
}
|
|
|
850a0b |
}
|
|
|
850a0b |
}
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
void onMovePoint(TAssistantPoint &point, const TPointD &position) override {
|
|
|
850a0b |
TPointD pc = m_center.position;
|
|
|
850a0b |
point.position = position;
|
|
|
850a0b |
if (&point == &m_center) {
|
|
|
850a0b |
TPointD d = m_center.position - pc;
|
|
|
850a0b |
m_a.position += d;
|
|
|
850a0b |
m_b.position += d;
|
|
|
850a0b |
} else {
|
|
|
850a0b |
onFixPoints();
|
|
|
850a0b |
}
|
|
|
850a0b |
}
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
void onDataFieldChanged(const TStringId &name, const TVariant &value) override {
|
|
|
850a0b |
TReplicator::onDataFieldChanged(name, value);
|
|
|
850a0b |
if ( name == m_idFixAngle
|
|
|
850a0b |
|| name == m_idFixSkew )
|
|
|
850a0b |
fixPoints();
|
|
|
850a0b |
}
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
static bool makeMirror(TAffine &mirror, const TPointD &c, const TPointD &x) {
|
|
|
850a0b |
if (!(norm2(x) > TConsts::epsilon*TConsts::epsilon))
|
|
|
850a0b |
return false;
|
|
|
850a0b |
TPointD y(-x.y, x.x);
|
|
|
850a0b |
TAffine t0( x.x, y.x, c.x,
|
|
|
850a0b |
x.y, y.y, c.y );
|
|
|
850a0b |
TAffine t1( x.x, -y.x, c.x,
|
|
|
850a0b |
x.y, -y.y, c.y );
|
|
|
850a0b |
mirror = t1*t0.inv();
|
|
|
850a0b |
return true;
|
|
|
850a0b |
}
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
public:
|
|
|
850a0b |
int getMultipler() const override {
|
|
|
850a0b |
return (getCountA() + getCountAInv())
|
|
|
850a0b |
* (getCountB() + getCountBInv())
|
|
|
850a0b |
* (getMirrorA() ? 2 : 1)
|
|
|
850a0b |
* (getMirrorB() ? 2 : 1);
|
|
|
850a0b |
}
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
void getModifiers(
|
|
|
850a0b |
const TAffine &toTool,
|
|
|
850a0b |
TInputModifier::List &outModifiers ) const override
|
|
|
850a0b |
{
|
|
|
850a0b |
TPointD c = toTool*m_center.position;
|
|
|
850a0b |
TPointD da = toTool*m_a.position - c;
|
|
|
850a0b |
TPointD db = toTool*m_b.position - c;
|
|
|
850a0b |
|
|
|
850a0b |
TAffine ma, mb;
|
|
|
850a0b |
|
|
|
850a0b |
bool mirrorA = getMirrorA() && makeMirror(ma, c, da);
|
|
|
850a0b |
bool mirrorB = getMirrorB() && makeMirror(ma, c, db);
|
|
|
850a0b |
|
|
|
850a0b |
int a1 = getCountA();
|
|
|
850a0b |
int b1 = getCountB();
|
|
|
850a0b |
int a0 = -getCountAInv();
|
|
|
850a0b |
int b0 = -getCountBInv();
|
|
|
850a0b |
|
|
|
850a0b |
TModifierClone *modifier = new TModifierClone();
|
|
|
850a0b |
for(int ib = b0; ib < b1; ++ib)
|
|
|
850a0b |
for(int ia = a0; ia < a1; ++ia) {
|
|
|
850a0b |
TPointD o = da*ia + db*ib;
|
|
|
850a0b |
if (ia || ib)
|
|
|
850a0b |
modifier->transforms.push_back(TTrackTransform(
|
|
|
850a0b |
TAffine( 1, 0, o.x,
|
|
|
850a0b |
0, 1, o.y ) ));
|
|
|
850a0b |
if (mirrorA)
|
|
|
850a0b |
modifier->transforms.push_back(TTrackTransform(
|
|
|
850a0b |
TAffine( ma.a11, ma.a12, ma.a13 + o.x,
|
|
|
850a0b |
ma.a21, ma.a22, ma.a23 + o.y ) ));
|
|
|
850a0b |
if (mirrorB)
|
|
|
850a0b |
modifier->transforms.push_back(TTrackTransform(
|
|
|
850a0b |
TAffine( mb.a11, mb.a12, mb.a13 + o.x,
|
|
|
850a0b |
mb.a21, mb.a22, mb.a23 + o.y ) ));
|
|
|
850a0b |
}
|
|
|
850a0b |
outModifiers.push_back(modifier);
|
|
|
850a0b |
}
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
void draw(TToolViewer*, bool enabled) const override {
|
|
|
850a0b |
double alpha = getDrawingAlpha(enabled);
|
|
|
850a0b |
double pixelSize = sqrt(tglGetPixelSize2());
|
|
|
850a0b |
|
|
|
850a0b |
TPointD c = m_center.position;
|
|
|
850a0b |
TPointD a = m_a.position;
|
|
|
850a0b |
TPointD b = m_b.position;
|
|
|
850a0b |
TPointD da = a - c;
|
|
|
850a0b |
TPointD db = b - c;
|
|
|
850a0b |
|
|
|
850a0b |
int a1 = getCountA();
|
|
|
850a0b |
int b1 = getCountB();
|
|
|
850a0b |
int a0 = -getCountAInv();
|
|
|
850a0b |
int b0 = -getCountBInv();
|
|
|
850a0b |
|
|
|
850a0b |
bool mirrorA = getMirrorA();
|
|
|
850a0b |
bool mirrorB = getMirrorB();
|
|
|
850a0b |
|
|
|
850a0b |
// draw base
|
|
|
850a0b |
drawSegment(c, a, pixelSize, alpha);
|
|
|
850a0b |
drawSegment(c, b, pixelSize, alpha);
|
|
|
850a0b |
|
|
|
850a0b |
// draw clones
|
|
|
850a0b |
for(int ib = b0; ib < b1; ++ib)
|
|
|
850a0b |
for(int ia = a0; ia < a1; ++ia) {
|
|
|
850a0b |
TPointD o = c + da*ia + db*ib;
|
|
|
850a0b |
if (ia || ib) {
|
|
|
850a0b |
drawSegment(o, o + da*0.2, pixelSize, alpha);
|
|
|
850a0b |
drawSegment(o, o + db*0.2, pixelSize, alpha);
|
|
|
850a0b |
}
|
|
|
850a0b |
if (mirrorA) drawSegment(o, o - da*0.2, pixelSize, alpha);
|
|
|
850a0b |
if (mirrorB) drawSegment(o, o - db*0.2, pixelSize, alpha);
|
|
|
850a0b |
}
|
|
|
850a0b |
}
|
|
|
850a0b |
};
|
|
|
850a0b |
|
|
|
850a0b |
|
|
|
850a0b |
//*****************************************************************************************
|
|
|
850a0b |
// Registration
|
|
|
850a0b |
//*****************************************************************************************
|
|
|
850a0b |
|
|
|
850a0b |
static TAssistantTypeT<treplicatorgrid> replicatorGrid("replicatorGrid");</treplicatorgrid>
|