|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
// TnzTools includes
|
|
|
aa51ee |
#include <tools replicator.h=""></tools>
|
|
|
aa51ee |
#include <tools modifierclone.h="" modifiers=""></tools>
|
|
|
aa51ee |
#include <tools assistants="" guidelineline.h=""></tools>
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
// TnzCore includes
|
|
|
aa51ee |
#include <tgl.h></tgl.h>
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
//*****************************************************************************************
|
|
|
aa51ee |
// TReplicatorStar implementation
|
|
|
aa51ee |
//*****************************************************************************************
|
|
|
aa51ee |
|
|
|
aa51ee |
class TReplicatorStar final : public TReplicator {
|
|
|
aa51ee |
Q_DECLARE_TR_FUNCTIONS(TReplicatorStar)
|
|
|
aa51ee |
public:
|
|
|
aa51ee |
const TStringId m_idDiscreteAngle;
|
|
|
aa51ee |
const TStringId m_idMirror;
|
|
|
aa51ee |
const TStringId m_idCount;
|
|
|
aa51ee |
|
|
|
aa51ee |
protected:
|
|
|
aa51ee |
TAssistantPoint &m_center;
|
|
|
aa51ee |
TAssistantPoint &m_a;
|
|
|
aa51ee |
|
|
|
aa51ee |
public:
|
|
|
aa51ee |
TReplicatorStar(TMetaObject &object):
|
|
|
aa51ee |
TReplicator(object),
|
|
|
aa51ee |
m_idDiscreteAngle("discreteAngle"),
|
|
|
aa51ee |
m_idMirror("mirror"),
|
|
|
aa51ee |
m_idCount("count"),
|
|
|
aa51ee |
m_center( addPoint("center", TAssistantPoint::CircleCross) ),
|
|
|
aa51ee |
m_a ( addPoint("a", TAssistantPoint::Circle, TPointD(80, 0)) )
|
|
|
aa51ee |
{
|
|
|
aa51ee |
addProperty( new TBoolProperty(m_idDiscreteAngle.str(), getDiscreteAngle()) );
|
|
|
aa51ee |
addProperty( new TBoolProperty(m_idMirror.str(), getMirror()) );
|
|
|
aa51ee |
addProperty( createCountProperty(m_idCount, getCount(), 2) );
|
|
|
aa51ee |
}
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
static QString getLocalName()
|
|
|
aa51ee |
{ return tr("Replicator Star"); }
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
void updateTranslation() const override {
|
|
|
aa51ee |
TReplicator::updateTranslation();
|
|
|
aa51ee |
setTranslation(m_idDiscreteAngle, tr("Discrete Angle"));
|
|
|
aa51ee |
setTranslation(m_idMirror, tr("Mirror"));
|
|
|
aa51ee |
setTranslation(m_idCount, tr("Count"));
|
|
|
aa51ee |
}
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
inline bool getDiscreteAngle() const
|
|
|
aa51ee |
{ return data()[m_idDiscreteAngle].getBool(); }
|
|
|
aa51ee |
inline bool getMirror() const
|
|
|
aa51ee |
{ return data()[m_idMirror].getBool(); }
|
|
|
aa51ee |
inline int getCount() const
|
|
|
aa51ee |
{ return (int)data()[m_idCount].getDouble(); }
|
|
|
aa51ee |
|
|
|
aa51ee |
protected:
|
|
|
aa51ee |
inline void setCount(int x)
|
|
|
aa51ee |
{ if (getCount() != (double)x) data()[m_idCount].setDouble((double)x); }
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
void onSetDefaults() override {
|
|
|
aa51ee |
setCount(6);
|
|
|
aa51ee |
TReplicator::onSetDefaults();
|
|
|
aa51ee |
}
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
void onFixData() override {
|
|
|
aa51ee |
TReplicator::onFixData();
|
|
|
aa51ee |
setCount( std::max(1, std::min(multiplierSoftLimit - 1, getCount())) );
|
|
|
aa51ee |
}
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
TPointD fixA() const {
|
|
|
aa51ee |
TPointD a = m_a.position;
|
|
|
aa51ee |
|
|
|
aa51ee |
if (getDiscreteAngle()) {
|
|
|
aa51ee |
TPointD d = a - m_center.position;
|
|
|
aa51ee |
double l = norm2(d);
|
|
|
aa51ee |
if (l > TConsts::epsilon*TConsts::epsilon) {
|
|
|
aa51ee |
l = sqrt(l);
|
|
|
aa51ee |
int count = getCount();
|
|
|
aa51ee |
if (count > 0) {
|
|
|
aa51ee |
double angle = atan2(d.y, d.x);
|
|
|
aa51ee |
angle = round(angle*2*count/M_PI)*M_PI/(2*count);
|
|
|
aa51ee |
a.x = cos(angle)*l + m_center.position.x;
|
|
|
aa51ee |
a.y = sin(angle)*l + m_center.position.y;
|
|
|
aa51ee |
}
|
|
|
aa51ee |
}
|
|
|
aa51ee |
}
|
|
|
aa51ee |
|
|
|
aa51ee |
if (areAlmostEqual(a, m_center.position))
|
|
|
aa51ee |
a = m_center.position + TPointD(1, 0);
|
|
|
aa51ee |
|
|
|
aa51ee |
return a;
|
|
|
aa51ee |
}
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
void onMovePoint(TAssistantPoint &point, const TPointD &position) override {
|
|
|
aa51ee |
if (&point == &m_center)
|
|
|
aa51ee |
m_a.position += position - m_center.position;
|
|
|
aa51ee |
point.position = position;
|
|
|
aa51ee |
}
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
public:
|
|
|
aa51ee |
int getMultipler() const override
|
|
|
aa51ee |
{ return getCount() + 1; }
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
void getModifiers(
|
|
|
aa51ee |
const TAffine &toTool,
|
|
|
aa51ee |
TInputModifier::List &outModifiers ) const override
|
|
|
aa51ee |
{
|
|
|
aa51ee |
int count = getCount();
|
|
|
aa51ee |
bool mirror = getMirror();
|
|
|
aa51ee |
|
|
|
aa51ee |
TPointD c = toTool*m_center.position;
|
|
|
aa51ee |
TPointD x = toTool*fixA() - c;
|
|
|
aa51ee |
TPointD y(-x.y, x.x);
|
|
|
aa51ee |
|
|
|
aa51ee |
TAffine t1( x.x, y.x, c.x,
|
|
|
aa51ee |
x.y, y.y, c.y );
|
|
|
aa51ee |
TAffine t2( x.x, -y.x, c.x,
|
|
|
aa51ee |
x.y, -y.y, c.y );
|
|
|
aa51ee |
|
|
|
aa51ee |
TAffine t0 = t1.inv();
|
|
|
aa51ee |
TRotation r(360.0/getCount());
|
|
|
aa51ee |
|
|
|
aa51ee |
TModifierClone *modifier = new TModifierClone();
|
|
|
aa51ee |
for(int i = 0; i < count; ++i) {
|
|
|
aa51ee |
if (i)
|
|
|
aa51ee |
modifier->transforms.push_back(TTrackTransform(t1*t0));
|
|
|
aa51ee |
if (mirror) {
|
|
|
aa51ee |
modifier->transforms.push_back(TTrackTransform(t2*t0));
|
|
|
aa51ee |
t2 *= r;
|
|
|
aa51ee |
}
|
|
|
aa51ee |
t1 *= r;
|
|
|
aa51ee |
}
|
|
|
aa51ee |
|
|
|
aa51ee |
outModifiers.push_back(modifier);
|
|
|
aa51ee |
}
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
void draw(TToolViewer*, bool enabled) const override {
|
|
|
aa51ee |
double alpha = getDrawingAlpha(enabled);
|
|
|
aa51ee |
double gridAlpha = getDrawingGridAlpha();
|
|
|
aa51ee |
double pixelSize = sqrt(tglGetPixelSize2());
|
|
|
aa51ee |
|
|
|
aa51ee |
int count = getCount();
|
|
|
aa51ee |
bool mirror = getMirror();
|
|
|
aa51ee |
|
|
|
aa51ee |
TPointD c = m_center.position;
|
|
|
aa51ee |
TPointD a = fixA();
|
|
|
aa51ee |
TPointD d = normalize(a - c);
|
|
|
aa51ee |
|
|
|
aa51ee |
double spacing = 10*pixelSize;
|
|
|
aa51ee |
double l = spacing*count/M_2PI;
|
|
|
aa51ee |
|
|
|
aa51ee |
TPointD p0 = c + d*l;
|
|
|
aa51ee |
TPointD p1 = p0 + d;
|
|
|
aa51ee |
TRotation r(360.0/count);
|
|
|
aa51ee |
|
|
|
aa51ee |
TAffine4 modelview, projection;
|
|
|
aa51ee |
glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a);
|
|
|
aa51ee |
glGetDoublev(GL_PROJECTION_MATRIX, projection.a);
|
|
|
aa51ee |
|
|
|
aa51ee |
TAffine matrix = (projection*modelview).get2d();
|
|
|
aa51ee |
TAffine matrixInv = matrix.inv();
|
|
|
aa51ee |
const TRectD oneBox(-1.0, -1.0, 1.0, 1.0);
|
|
|
aa51ee |
|
|
|
aa51ee |
for(int i = 0; i < count; ++i) {
|
|
|
aa51ee |
TPointD pp0 = matrix*p0;
|
|
|
aa51ee |
TPointD pp1 = matrix*p1;
|
|
|
aa51ee |
if (TGuidelineLine::truncateRay(oneBox, pp0, pp1))
|
|
|
aa51ee |
drawSegment(matrixInv*pp0, matrixInv*pp1, pixelSize, i ? gridAlpha : alpha);
|
|
|
aa51ee |
p0 = r*(p0 - c) + c;
|
|
|
aa51ee |
p1 = r*(p1 - c) + c;
|
|
|
aa51ee |
}
|
|
|
aa51ee |
|
|
|
aa51ee |
TPointD p = TPointD(-d.y, d.x);
|
|
|
aa51ee |
drawSegment( (mirror ? a+p*15 : a), a-p*15, pixelSize, alpha );
|
|
|
aa51ee |
|
|
|
aa51ee |
drawSegment(c - d*10, c + d*10, pixelSize, alpha);
|
|
|
aa51ee |
drawSegment(c - p*10, c + p*10, pixelSize, alpha);
|
|
|
aa51ee |
}
|
|
|
aa51ee |
};
|
|
|
aa51ee |
|
|
|
aa51ee |
|
|
|
aa51ee |
//*****************************************************************************************
|
|
|
aa51ee |
// Registration
|
|
|
aa51ee |
//*****************************************************************************************
|
|
|
aa51ee |
|
|
|
aa51ee |
static TAssistantTypeT<treplicatorstar> replicatorStar("replicatorStar");</treplicatorstar>
|