[vtkusers] Manually positioning a cylinder between two points - How to?

Wagner Sales wsales at gmail.com
Mon Jun 14 17:22:58 EDT 2010


Hi all,

I need to manually position a cylinder between two points in 3D space.
In fact, aren't exactly a cylinder, but a polydata that's have same
properties a cylinder haves.
Because aren't a simple cylinder, I can't use the vtkLineSource, for
example, to do this job. Searching in google, I've found a mail from
Marc Cotran in 2007 that's appears to solve my problem.
But the code present in the mail aren't complete and I failed to get
this working.  The complete text and code of the mail are above, and
basically I can't do the job the class Coord does ( norm and normalize
).
Original mail link:

http://www.vtk.org/pipermail/vtkusers/2007-March/090334.html

Original mail text:

Hi Mark,

I have a 'hard' way of doing what you are asking. The easiest way is
what Amy proposes, but if you definitely want a cylinder that can update
quickly with changes to the endpoints...

- useablePt1 and 2 are classes (Coord) with 3 variables (x, y, z) for
coordinates. Although we implemented some convenience methods in Coord,
you could do it all with vtkMath.

- this->transform corresponds to that of the actor made from the
cylinderSource

//////////////////////////////

    this->cylinderSource = vtkCylinderSource::New();
    this->cylinderSource->SetCapping(1);
    this->cylinderSource->SetResolution(5);

    // find out halfway point
    Coord halfwayPt(
        (useablePt1.x() + useablePt2.x()) / 2,
        (useablePt1.y() + useablePt2.y()) / 2,
        (useablePt1.z() + useablePt2.z()) / 2);

    double pos[4];
    double res[4];

    pos[0] = halfwayPt.x();
    pos[1] = halfwayPt.y();
    pos[2] = halfwayPt.z();
    pos[3] = 1;

    this->transform.getTransform()->MultiplyPoint(pos, res);

    // we found the center point

    Coord diff(this->pt2 - this->pt1);
    Coord normalized(diff.normalize());

    double norm = diff.norm();

    this->cachedActor->SetScale(this->radius, norm, this->radius);

    // get cross product
    double cross[3];
    double input[3];
    double output[3];

    input[0] = 0;
    input[1] = 1;
    input[2] = 0;

    output[0] = normalized.x();
    output[1] = normalized.y();
    output[2] = normalized.z();

    vtkMath::Cross(input, output, cross);

    // get the angle
    double angle = HelperClass::getAngle(Coord(0,1,0), Coord(), normalized);

    // start with no rotation so they don't accumulate
    this->cachedActor->SetOrientation(0,0,0);

    this->cachedActor->RotateWXYZ(angle, cross[0], cross[1], cross[2]);

    this->cachedActor->SetPosition(
        res[0] / res[3],
        res[1] / res[3],
        res[2] / res[3]);

//////////////////////////////

It is quite possible that the code can be optimized (or at least made
shorter). The only advantage to this method is that you don't have to
remap the actor when you change one or both of the endpoints. If you
don't care about updates, I strongly recommend the lineSource/TubeFilter
method (it's much simpler!!!)

Marc


Regards,

Wagner Sales



More information about the vtkusers mailing list