[vtk-developers] Class design for spline visualizations

Lin M majcjc at gmail.com
Thu Jun 18 23:44:51 EDT 2015


Do we store the auxiliary variables like PatchDegree PatchDimension and
PatchParameterRange for all patches in the adaptor class and keep the
variables for certain patch in the vtkMappedDataArray subclass when we want
to retrieve that patch?

On Thu, Jun 18, 2015 at 9:17 PM, Lin M <majcjc at gmail.com> wrote:

> Sorry...
>
> The vtkControlPointArray is the subclass of vtkMappedDataArray. I define a
> variable to indicate that the begin idx of the patch which I assume will be
> set when vtkBezierPatchAdaptor::Next() or vtkBezierPatchAdaptor::GoToPatch()
> is called.
>
> On Thu, Jun 18, 2015 at 9:11 PM, David Thompson <
> david.thompson at kitware.com> wrote:
>
>> Hi Lin,
>>
>> It looks like you forgot to add the header and implementation files to
>> the commit.
>>
>>         David
>>
>> > On Jun 18, 2015, at 9:08 PM, Lin M <majcjc at gmail.com> wrote:
>> >
>> > Hi Dr. Thompson,
>> >
>> > I have added one commit which contains a vtkMappedDataArray subclass
>> but I'm not sure I totally get the idea about the in-situ data structures.
>> Can you take a look at it please? (
>> https://gitlab.kitware.com/splines/vtk/merge_requests/4)
>> >
>> > Best,
>> > Lin
>> >
>> > On Thu, Jun 18, 2015 at 10:47 AM, David Thompson <
>> david.thompson at kitware.com> wrote:
>> > Hi Lin,
>> >
>> > > From some examples I saw, usually we put some points in vtkPoints,
>> store the connectivity in cellArray and add them to a dataset (vtkPolyData,
>> vtkStructuredGrid or vtkUnstructureGrid). So is that we store the control
>> point of multiple patches in the vtkPoints where we replace the
>> vtkDataArray with vtkMappedDataArray now? And in a vtkMappedDataArray, we
>> store all the points for all patches together but we overwrite how to
>> iterate the array.
>> >
>> > That is nearly correct. We will accept
>> >
>> >     vtkDataObject* ControlPointData;
>> >
>> > from the user. For the case we will implement first, ControlPointData's
>> actual type will be the vtkStructuredGrid subclass of vtkDataObject. The
>> vtkStructuredGrid instance can hold many user-supplied vtkDataArray
>> instances:
>> >
>> >     vtkStructuredGrid* structuredControlPoints =
>> >       vtkStructuredGrid::SafeDownCast(ControlPointData);
>> >
>> >     // Control points to map from parameter-space to world coordinates:
>> >     vtkDataArray* geometricControlPoints =
>> >       structuredControlPoints->GetPoints()->GetData();
>> >
>> >     // Control points to map from paramter-space to scalar fields:
>> >     vtkDataSetAttributes* scalarFields =
>> structuredControlPoints->GetPointData();
>> >     vtkIdType numScalarFields = scalarFields->GetNumberOfArrays();
>> >     for (vtkIdType i = 0; i < numScalarFields; ++i)
>> >       { // scalarFieldControlPoints will hold things like temperature,
>> pressure, etc.:
>> >       vtkDataArray* scalarFieldControlPoints =
>> scalarFields->GetArray(i);
>> >       }
>> >
>> > Because the user supplies these arrays, we cannot force them to be
>> vtkMappedDataArray. Instead, we can make a vtkMappedDataArray subclass that
>> owns a reference to one of the arrays above and only returns one patch's
>> values from the user-supplied array (which holds the values for all patches
>> in the spline).
>> >
>> > The BezierPatchAdaptor below would return instances of our
>> vtkMappedDataArray when its GetPatchPoints method is called. Now that I've
>> written some more out, it looks like the API should be changed a little bit
>> so that users can ask for a particular array (geometricControlPoints or
>> scalarFieldControlPoints):
>> >
>> > class vtkBezierPatchAdaptor : public vtkObject
>> > {
>> > public:
>> >   virtual void SetControlPointData(vtkDataObject* controlPointData);
>> >   vtkGetObjectMacro(vtkDataObject,ControlPointData);
>> >
>> >   // Methods to iterate over patches:
>> >   // ... same as below ...
>> >
>> >   // Methods to access the current patch:
>> >   // ...
>> >   virtual vtkSmartPointer<vtkMappedArray> GetPatchPoints(int
>> scalarField) const = 0;
>> >   // ...
>> > };
>> >
>> > This way, GetPatchPoints() could return the vtkMappedDataArray for
>> geometricControlPoints when the "int scalarField" argument is negative
>> value and a vtkMappedDataArray for one of the scalarFieldControlPoints
>> arrays when scalarField is positive.
>> >
>> > Having GetPatchPoints() return a smart pointer to a vtkMappedDataArray
>> subclass would also get around the issue that vtkPoints expects its
>> vtkDataArray to have 3 components per tuple (where ours will have 4 for
>> geometricControlPoints or an arbitrary number for scalarFieldControlPoints).
>> >
>> > The vtkMappedDataArray instances would own a weak reference back the
>> vtkBezierPatchAdaptor which created them and a weak reference to the
>> geometricControlPoints or scalarFieldControlPoints array it draws values
>> from. When vtkBezierPatchAdaptor::Next() or
>> vtkBezierPatchAdaptor::GoToPatch() is called, the adaptor would iterate
>> over all of the vtkMappedDataArray instances it owns and change an internal
>> variable so they would return values for the proper patch. That way the
>> vtkMappedDataArray instances only have to be created once for each spline
>> dataset, not once per patch.
>> >
>> > Is that clear enough, or should I sketch out a header file for our
>> vtkMappedDataArray subclass?
>> >
>> >         David
>> >
>> > > On Wed, Jun 17, 2015 at 10:22 PM, David Thompson <
>> david.thompson at kitware.com> wrote:
>> > > Hi Lin,
>> > >
>> > >> Sorry for late reply. Since the midterm is coming, I'll definitely
>> speed up the development from now on.
>> > >
>> > > We both need to do a little more work. I have been looking at how to
>> read data from PetIGA so we can show some actual simulation data and have
>> some 3-D volumetric examples.
>> > >
>> > > It would be nice to have a patch ready to merge into VTK's master
>> branch at the midterm that provides spline interpolation and tests it for
>> all 3 parametric dimensions (curves, surfaces, and volumes). The means
>> producing triangles and tetrahedra, not just polylines.
>> > >
>> > >> I have a question about the class design in your last email. To my
>> understanding, control points for one patch is stored in a vtkDataArray.
>> > >
>> > > Close. I think that we should use the vtkMappedDataArray class to
>> hold control points for multiple patches but program it to appear as if
>> points for each individual patch are stored in patch-order.
>> > >
>> > >> Do you mean store multiple vtkDataArray regarding to multiple
>> patches in the vtkDataObject?
>> > >
>> > > There would be one data array to hold point coordinates, but other
>> arrays would hold simulation variables like temperature, pressure,
>> velocity, and so on.
>> > >
>> > >> If so, what class do I need to use for vtkDataObject?
>> > >
>> > > The class outline below is an abstract class. A concrete
>> implementation for NURBs would require   the base class's ControlPointData
>> to be an instance of vtkStructuredGrid. A T-spline implementation might
>> expect ControlPointData to be a vtkUnstructuredGrid. I think all we should
>> do this summer is the NURBs case.
>> > >
>> > >     David
>> > >
>> > >>
>> > >> On Wed, Jun 10, 2015 at 2:39 PM, David Thompson <
>> david.thompson at kitware.com> wrote:
>> > >> Hi Lin,
>> > >>
>> > >> > I have made it support 3D ellipse with function ...
>> > >>
>> > >> Great!
>> > >>
>> > >> > As you can see in the python test, I call this function 4 times
>> for each quadrant to generate the entire ellipse. Since we need to support
>> multiple patches, I think it's better to define a new dataset class for
>> bezier patches as you mentioned before about  creating a new
>> vtkControlPoints class that inherits from vtkPoints and allows for an extra
>> coordinate.
>> > >>
>> > >> Rather than create new dataset types, I would like to use existing
>> datatypes to store the data and make an adaptor to iterate over them. That
>> way existing pipelines could modify scalar values defined on control points
>> (and perhaps even patches). For instance, B-splines could be represented as
>> a vtkStructuredGrid whose FieldData contains a special knot array (special
>> in the sense that the array must be of the proper size and with a fixed
>> name like "_vtkKnotVector").
>> > >>
>> > >> The adaptor would take a vtkDataObject as input and provide
>> iterator-style access to each patch defined by the dataset. Specific
>> subclasses of the adaptor would be B-splines (which expect the
>> vtkDataObject to be a vtkStructuredGrid) or T-splines (which might expect a
>> vtkUniformGridAMR) or even point-based splines (PB-splines as defined in
>> Sederberg's T-spline paper, which could expect any dataset derived
>> vtkPointSet).
>> > >>
>> > >> class vtkBezierPatchAdaptor : public vtkObject
>> > >> {
>> > >> public:
>> > >>   virtual void SetControlPointData(vtkDataObject* controlPointData);
>> > >>   vtkGetObjectMacro(vtkDataObject,ControlPointData);
>> > >>
>> > >>   // Methods to iterate over patches:
>> > >>   virtual void Begin() = 0;
>> > >>   virtual bool IsAtEnd() = 0;
>> > >>   virtual bool GoToPatch(vtkIdType patchId) = 0; // random access
>> iteration
>> > >>   virtual bool Next() = 0;
>> > >>
>> > >>   // Methods to access the current patch:
>> > >>   virtual int GetPatchDimension() const = 0;
>> > >>   virtual void GetPatchShape() const = 0;
>> > >>     // returns VTK_TRIANGLE/VTK_QUAD when PatchDimension==2,
>> > >>     // returns VTK_HEXAHEDRON/VTK_TETRA when PatchDimension==3
>> > >>   virtual void GetPatchDegree(int* degreeOut) const = 0;
>> > >>   virtual void GetPatchParameterRange(double* paramsOut) const = 0;
>> > >>   virtual void GetPatchPoints(vtkPoints* pointsOut) const = 0;
>> > >>
>> > >>   // Some helper methods that would make Python wrappings usable:
>> > >>   int GetPatchDegree(int dim) const
>> > >>     {
>> > >>     std::vector<int> degree(this->GetPatchDimension());
>> > >>     this->GetPatchDegree(&degree[0]);
>> > >>     return degree[dim];
>> > >>     }
>> > >>   void GetPatchParameterRange(int dim, double paramRange[2])
>> > >>     {
>> > >>     std::vector<double> range(2 * this->GetPatchDimension());
>> > >>     this->GetPatchDegree(&range[0]);
>> > >>     paramRange[0] = [2 * dim];
>> > >>     paramRange[1] = [2 * dim + 1];
>> > >>     }
>> > >>
>> > >> protected:
>> > >>   vtkDataObject* ControlPointData;
>> > >> };
>> > >>
>> > >> The B-spline subclass could then iterate over patches by keeping a
>> current "cell ID," which would be incremented by calling Next(). When asked
>> for the *patch* points (not the input points), the adaptor would create a
>> vtkMappedDataArray (see http://www.vtk.org/Wiki/VTK/InSituDataStructure
>> for more information) that did not copy control point coordinates from its
>> ControlPointData->GetPoints() but instead used the implicit connectivity to
>> provide access to underlying B-spline points.
>> > >>
>> > >> For example, consider the simple case of a rectangular B-spline with
>> degree 1 (bi-linear). We might be given a 5x6 grid of control points as
>> input and asked to iterate over all the patches. Each patch is simply a
>> quadrilateral, and there are (5-1)*(6-1) = 20 of them.
>> > >>
>> > >>   adaptor->Begin(); // would initialize an internal "cell ID" to 0
>> > >>   adaptor->IsAtEnd(); // would return false for "cell ID" values in
>> [0,19] and true otherwise.
>> > >>   adaptor->GetPatchDimension(); // would return 2
>> > >>   adaptor->GetPatchShape(); // would return VTK_QUAD
>> > >>   adaptor->GetPatchDegree(degreeOut); // would populate degreeOut
>> with [1,1]
>> > >>   adaptor->GetPatchPoints(pointsOut); // would populate pointsOut
>> with a vtkMappedDataArray.
>> > >>
>> > >> The vtkMappedDataArray would report having 4 tuples (one for each
>> corner of the quad... when the degree is higher, is would report the
>> product of (degreeOut[i]+1) for all i in GetPatchDimension()). The actual
>> points reported would depend on the "cell ID" in the adaptor.
>> > >>
>> > >> I have not figured out yet how the "w" homogeneous coordinate would
>> work with vtkPoints. A different adaptor API might work better (keeping the
>> "w" coordinate separate from the other points).
>> > >>
>> > >> > Another question is that currently the domain of parameter
>> coordinate is [0, 1] for each patch. Do you think it's better to make the
>> domain continuously, namely [0, 0.25] for the first quadrant, [0.25, 0.75]
>> for the second quadrant, etc?
>> > >>
>> > >> If we focus on the B-spline adaptor above, we get that for free
>> since the returned knot vector could be normalized to the range [0,1].
>> > >>
>> > >>         David
>> > >>
>> > >
>> >
>> >
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtk-developers/attachments/20150618/1fc139a5/attachment-0001.html>


More information about the vtk-developers mailing list