Commit 9ac02dce authored by Hans-Christian Ebke's avatar Hans-Christian Ebke

Plugin-PolyLine: Load/save support for bezier and circles. Improved circle and bezier handling.


git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@17644 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 586636ad
This diff is collapsed.
......@@ -183,6 +183,8 @@ private slots:
void slot_setCirclePointNum(int i);
void slot_setSplinePointNum(int i);
virtual void slotObjectUpdated( int _identifier );
private :
EditMode mode();
......@@ -302,11 +304,13 @@ private:
int createCircle_CurrSelIndex_;
/// Use this one to mark the last index to update the number of points
int createCircle_LastSelIndex_;
/// Data for creating a circle, center and it's normal
ACG::Vec3d createCircle_Point_;
ACG::Vec3d createCircle_Normal_;
/// The handle which is being dragged.
ACG::SceneGraph::GlutPrimitiveNode* moveCircle_SelNode_;
///The last valid hit on the mesh
ACG::Vec3d moveCircle_LastHitPos_;
ACG::Vec3d moveCircle_LastHitNor_;
bool moveCircle_IsLocked;
bool moveCircle_IsFloating;
/**
* \brief Calculates a point on the mesh.
......@@ -353,6 +357,18 @@ private:
*/
ACG::Vec3d createCircle_getHit(PolyLineCircleData* _circleData, ACG::Vec3d _hit_point);
public slots:
/* \brief Creates the UI elements for the poly line(asserting it has circle data)
*
*/
void createCircle_createUI(int _polyLineObjectID);
/* \brief Creates the UI elements for the poly line(asserting it has spline data)
*
*/
void createSpline_createUI(int _polyLineObjectID);
private:
/** \brief Generates points for the ellipse.
*
* @param _lineObject The object to generate points for.
......
......@@ -56,7 +56,7 @@ PolyLinePlugin::
getPointOnMesh(PolyLineBezierSplineData* _SplineData, ACG::Vec3d _point, ACG::Vec3d* _nor)
{
TriMeshObject* mesh;
if(!PluginFunctions::getObject(_SplineData->meshIndex(), mesh))
if(!PluginFunctions::getObject(_SplineData->meshIndex_, mesh))
return _point;
OpenMeshTriangleBSPT<TriMesh>* bsp = mesh->requestTriangleBsp();
OpenMeshTriangleBSPT<TriMesh>::NearestNeighbor neigh = bsp->nearest(_point);
......@@ -97,14 +97,17 @@ PolyLinePlugin::
updatePolyBezierSpline(PolyLineObject* _lineObject, unsigned int _pointCount)
{
PolyLineBezierSplineData* splineData = dynamic_cast<PolyLineBezierSplineData*>(_lineObject->objectData(BEZSPLINE_DATA));
if(!splineData)
return;
TriMeshObject* mesh;
if(!splineData || !PluginFunctions::getObject(splineData->meshIndex_, mesh))
return;//no mesh -> do nothing
_lineObject->line()->clear();
int segCount = (splineData->points_.size() + splineData->handles_.size() - 1) / 3, segment = 0;
for(int s = 0; s < segCount; s++) {
unsigned int segCount = (splineData->points_.size() + splineData->handles_.size() - 1) / 3;
for(unsigned int s = 0; s < segCount; s++) {
const ACG::Vec3d a = splineData->points_[s].position, d = splineData->points_[s + 1].position,
b = splineData->handles_[s * 2], c = splineData->handles_[s * 2 + 1];
for(unsigned int i = 0; i < _pointCount; i++) {
//the last segment will get one more point to close the spline
unsigned int n = (s != segCount - 1) ? _pointCount : (_pointCount + 1);
for(unsigned int i = 0; i < n; i++) {
float alpha = float(i) / float(_pointCount);
const ACG::Vec3d e = a + (b - a) * alpha, f = c + (d - c) * alpha;
ACG::Vec3d g = e + (f - e) * alpha;
......
......@@ -30,7 +30,7 @@
* License along with OpenFlipper. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
\*===========================================================================*/
/*===========================================================================*\
* *
......@@ -38,7 +38,7 @@
* $Author$ *
* $Date$ *
* *
\*===========================================================================*/
\*===========================================================================*/
//=============================================================================
//
......@@ -46,16 +46,14 @@
//
//=============================================================================
//== INCLUDES =================================================================
#include "PolyLinePlugin.hh"
namespace {
struct Onb {
ACG::Vec3d x,y,z;
ACG::Vec3d x, y, z;
Onb(PolyLineCircleData* _circleData) {
x = _circleData->circleMainAxis_;
......@@ -63,7 +61,8 @@ struct Onb {
y = _circleData->circleNormal_;
}
ACG::Vec3d toWorld(ACG::Vec3d v) const {
return ACG::Vec3d(x[0] * v[0] + y[0] * v[1] + z[0] * v[2],
return ACG::Vec3d(
x[0] * v[0] + y[0] * v[1] + z[0] * v[2],
x[1] * v[0] + y[1] * v[1] + z[1] * v[2],
x[2] * v[0] + y[2] * v[1] + z[2] * v[2]);
}
......@@ -73,27 +72,25 @@ struct Onb {
//-----------------------------------------------------------------------------
bool
PolyLinePlugin::
createCircle_getPointOnMesh(TriMeshObject* _triMeshObject, ACG::Vec3d _center, ACG::Vec3d _pOnPlane, ACG::Vec3d _n, ACG::Vec3d* _pOut)
{
bool PolyLinePlugin::createCircle_getPointOnMesh(TriMeshObject* _triMeshObject, ACG::Vec3d _center,
ACG::Vec3d _pOnPlane, ACG::Vec3d _n, ACG::Vec3d* _pOut) {
OpenMeshTriangleBSPT<TriMesh>* bsp = _triMeshObject->requestTriangleBsp();
OpenMeshTriangleBSPT<TriMesh>::RayCollision rayInt = bsp->raycollision(_pOnPlane, _n);
if(rayInt.empty())
if (rayInt.empty())
return false;
ACG::Vec3d eye = PluginFunctions::viewerProperties(0).glState().eye();
int i = -1;
double smDist = 10e10;
for(unsigned int j = 0; j < rayInt.size(); j++) {
for (unsigned int j = 0; j < rayInt.size(); j++) {
ACG::Vec3d norAtInt = _triMeshObject->mesh()->normal(rayInt[j].first);
ACG::Vec3d p = _pOnPlane + _n * rayInt[j].second, dir = _center - p;
const double dist = dir.norm();
if(dist < smDist) {
if (dist < smDist) {
smDist = dist;
if(_pOut)
*_pOut = p;//+ norAtInt * 0.002;//that would fix lines below the surface, but what is the correct scale?
if (_pOut)
*_pOut = p; //+ norAtInt * 0.002;//that would fix lines below the surface, but what is the correct scale?
i = j;
}
}
......@@ -103,44 +100,42 @@ createCircle_getPointOnMesh(TriMeshObject* _triMeshObject, ACG::Vec3d _center, A
//-----------------------------------------------------------------------------
bool
PolyLinePlugin::
createCircle_getHitInfo(PolyLineCircleData* _circleData, ACG::Vec3d _hit_Point, ACG::Vec3d* _pOut, double* r, ACG::Vec3d* _onPlaneO)
{
bool PolyLinePlugin::createCircle_getHitInfo(PolyLineCircleData* _circleData, ACG::Vec3d _hit_Point, ACG::Vec3d* _pOut,
double* r, ACG::Vec3d* _onPlaneO) {
ACG::Vec3d n = _circleData->circleNormal_, x0 = _circleData->circleCenter_;
double t = ((n | x0) - (n | _hit_Point)) / n.sqrnorm();
ACG::Vec3d onPlane = _hit_Point + t * n, d = onPlane - x0;
if(r)
if (r)
*r = d.norm();
if(_onPlaneO)
if (_onPlaneO)
*_onPlaneO = onPlane;
TriMeshObject* mesh;
if(PluginFunctions::getObject(_circleData->circleMeshIndex_, mesh))
if (PluginFunctions::getObject(_circleData->circleMeshIndex_, mesh))
return createCircle_getPointOnMesh(mesh, x0, onPlane, n, _pOut);
else return false;
else
return false;
}
//-----------------------------------------------------------------------------
ACG::Vec3d
PolyLinePlugin::
createCircle_getHit(PolyLineCircleData* _circleData, ACG::Vec3d _hit_point)
{
ACG::Vec3d PolyLinePlugin::createCircle_getHit(PolyLineCircleData* _circleData, ACG::Vec3d _hit_point) {
ACG::Vec3d pOnMesh, pOnPlane;
double r;
if(!createCircle_getHitInfo(_circleData, _hit_point, &pOnMesh, &r, &pOnPlane))
return pOnPlane;//no point on the mesh was found...
else return pOnMesh;
if (!createCircle_getHitInfo(_circleData, _hit_point, &pOnMesh, &r, &pOnPlane))
return pOnPlane; //no point on the mesh was found...
else
return pOnMesh;
}
//-----------------------------------------------------------------------------
void
PolyLinePlugin::
updatePolyEllipse(PolyLineObject* _lineObject, unsigned int _pointCount)
{
void PolyLinePlugin::updatePolyEllipse(PolyLineObject* _lineObject, unsigned int _pointCount) {
PolyLineCircleData* lineData = dynamic_cast<PolyLineCircleData*>(_lineObject->objectData(CIRCLE_DATA));
TriMeshObject* mesh;
if(!PluginFunctions::getObject(lineData->circleMeshIndex_, mesh))
return;//if there is no mesh available do not try to recreate the circle
const double theta = 2.0 * M_PI / double(_pointCount);
_pointCount += tool_->rb_CloseCircle->isChecked() ? 0 : -1;
const double r2 = lineData->circleMainRadius_, r1 = lineData->circleSideRadius_;
......@@ -148,15 +143,17 @@ updatePolyEllipse(PolyLineObject* _lineObject, unsigned int _pointCount)
_lineObject->line()->clear();
for(unsigned int i = 0; i <= _pointCount; i++) {
for (unsigned int i = 0; i <= _pointCount; i++) {
const double tanTheta_i = tan(theta * i);
double x = (r1 * r2) / sqrt(r2 * r2 + r1 * r1 * tanTheta_i * tanTheta_i);
x = ((theta * i) <= M_PI_2 || (theta * i) > (3.0 * M_PI_2)) ? x : -x;
const double y = tanTheta_i * x;
ACG::Vec3d pOnMesh;
const ACG::Vec3d pOnPlane(y,0,x),//this is in the local coord system!
const ACG::Vec3d pOnPlane(y, 0, x), //this is in the local coord system!
pInWorld = basis.toWorld(pOnPlane) + lineData->circleCenter_;
if(createCircle_getHitInfo(lineData, pInWorld, &pOnMesh))
if(moveCircle_IsFloating)
_lineObject->line()->add_point(pInWorld);
else if(createCircle_getHitInfo(lineData, pInWorld, &pOnMesh))
_lineObject->line()->add_point(pOnMesh);
}
emit updatedObject(_lineObject->id(), UPDATE_GEOMETRY | UPDATE_TOPOLOGY);
......@@ -164,5 +161,3 @@ updatePolyEllipse(PolyLineObject* _lineObject, unsigned int _pointCount)
//-----------------------------------------------------------------------------
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment