Hello Carsten,

IMHO we are in the realm of modulo bug :-)

Below, I have copied the two relevant functions with their comments.

My scenario:

MaterialGroup* mgrp = ...;
vector<OSG::ReflexiveContainerType*> shareTypes;
shareTypes.push_back(&MyMaterial::getClassType());
cloned_mgrp = deepClone(mgrp, shareTypes, ...);


Method deepClone calls dstField->shareValues(srcField) if

TypePredicates::typeDerivedFrom(
                        shareTypes.begin(),
                        shareTypes.end  (), *rcType))

results true. 'rcType' is the MaterialGroup's 'material' field:

const ReflexiveContainerType *rcType =
                dynamic_cast<const ReflexiveContainerType *>(
                    &pointerType->getContentType());

Now, the predicate 'typeDerivedFrom' results in true if any of the
sequence's elements is a base class of the third parameter 'type',
i.e. rcType, i.e. "Material". That is the way 'typeDerivedFrom'
is implemented.

Hope I could clarify my point ;-)

Best,
Johannes


/*! Tests if type is derived from any of the types in the sequence
    specified by [begin, end). The sequence must consist of pointers
    to TypeBase objects (or a derived class).

    \param[in] begin Start of sequence.
    \param[in] end End of sequence.
    \param[in] type Type that is tested.
    \return true, if type is derived from any of the types in
        [begin, end), false otherwise.
 */
template <class InIteratorTypeT> inline
bool TypePredicates::typeDerivedFrom(      InIteratorTypeT  begin,
                                           InIteratorTypeT  end,
                                     const OSG::TypeBase   &type  )
{
    return (std::find_if(begin, end,
                         TypePredicates::IsBaseOf(type)) != end);
}

/*! Creates a deep copy ...

    \param[in] src FieldContainer to clone.
    \param[in] shareTypes Types that should be shared instead of cloned.
    \param[in] ignoreTypes Types that should be ignored.
    \param[in] shareGroupIds Type groups that should be shared instead
        of cloned.
    \param[in] ignoreGroupIds Type groups that should be ignored.
    ...
 */
FieldContainerTransitPtr deepClone(
          OSG::FieldContainer const                        *src,
    const std::vector<const OSG::ReflexiveContainerType *> &shareTypes,
    const std::vector<const OSG::ReflexiveContainerType *> &ignoreTypes,
    const std::vector<OSG::UInt16>                         &shareGroupIds,
    const std::vector<OSG::UInt16>                         &ignoreGroupIds)
{
    if(src == NULL)
        return FieldContainerTransitPtr(NULL);

    const FieldContainerType &fcType  = src->getType();
    FieldContainerTransitPtr  fcClone = fcType.createContainer();

    UInt32 fCount = osgMin(fcType            .getNumFieldDescs(),
                           fcClone->getType().getNumFieldDescs() );

    for(UInt32 i = 1; i <= fCount; ++i)
    {
        const FieldDescriptionBase *fDesc = fcType.getFieldDesc(i);

        if(fDesc->isInternal())
            continue;

        GetFieldHandlePtr  srcField = src    ->getField (i);
        EditFieldHandlePtr dstField = fcClone->editField(i);

        if(dstField == NULL || dstField->isValid() == false ||
           srcField == NULL || srcField->isValid() == false)
        {
            continue;
        }

        if(srcField->isPointerField() == false)
        {
            dstField->copyValues(srcField);
        }
        else
        {
            // get type info for values stored in field
            const DataType &contentType = srcField->getType().getContentType();

            // check if it's a "pointer to FC" type (needed, because
            // AttachmentMap also passes the above isPointerType() check)
            const PointerType *pointerType =
                dynamic_cast<const PointerType *>(&contentType);

            // punt, share if it is something that is not "pointer to FC"
            if(pointerType == NULL)
            {
                dstField->shareValues(srcField);
                continue;
            }

            // get type info for pointed-to FC type
            const ReflexiveContainerType *rcType =
                dynamic_cast<const ReflexiveContainerType *>(
                    &pointerType->getContentType());

            // punt, share if it is something that is not derived from RC
            if(rcType == NULL)
            {
                dstField->shareValues(srcField);
                continue;
            }

            // check if type should be ignored
            if(!TypePredicates::typeInGroupIds(
                    ignoreGroupIds.begin(),
                    ignoreGroupIds.end  (), *rcType) &&
               !TypePredicates::typeDerivedFrom(
                    ignoreTypes.begin(),
                    ignoreTypes.end  (), *rcType)      )
            {
                // check if type should by shared
                if(TypePredicates::typeInGroupIds(
                        shareGroupIds.begin(),
                        shareGroupIds.end  (), *rcType) ||
                   TypePredicates::typeDerivedFrom(
                        shareTypes.begin(),
                        shareTypes.end  (), *rcType)      )
                {
                    dstField->shareValues(srcField);
                }
                else
                {
                    dstField->cloneValues(srcField,
                                          shareTypes,
                                          ignoreTypes,
                                          shareGroupIds,
                                          ignoreGroupIds);
                }
            }
        }
    }

    return fcClone;
}


________________________________
From: Carsten Neumann <carsten.p.neum...@gmail.com>
Sent: Wednesday, March 10, 2021 7:52 PM
To: OpenSG (opensg-users@lists.sourceforge.net)
Subject: Re: [Opensg-users] Method deepClone possibly not correct

    Hello Johannes,

On Wed, Mar 10, 2021 at 1:08 PM Johannes Brunen 
<jbru...@datasolid.de<mailto:jbru...@datasolid.de>> wrote:
> Say I have a container with a material field (MaterialGroup) in it and I want 
> that my special material (MyMaterial) must not to be deep cloned but shared. 
> So I provide myMaterial to the shareTypes parameter of the deepClone method.
>
>
> deepClone checks for each of the fields of the given 'src' container the 
> following in order to decide if the field is to be cloned or shared:
>
>
>                 // check if type should by shared
>
>                 if(TypePredicates::typeInGroupIds(
>                         shareGroupIds.begin(),
>                         shareGroupIds.end  (), *rcType) ||
>                    TypePredicates::typeDerivedFrom(
>                         shareTypes.begin(),
>                         shareTypes.end  (), *rcType)      )

the way I'm reading this, it means if the field we are looking at is derived 
from any of the types in shareTypes it gets shared, which sounds correct to me.

> Now the function TypePredicates::typeDerivedFrom states
>
>
> /*! Tests if \a type is derived from any of the types in the sequence
>     specified by [\a begin, \a end). The sequence must consist of pointers
>     to TypeBase objects (or a derived class), e.g.
>     std::vector\<const FieldContainerType *\>.
>
>     \param[in] begin Start of sequence.
>     \param[in] end End of sequence.
>     \param[in] type Type that is tested.
>     \return true, if \a type is derived from any of the types in
>         [\a begin, \a end), false otherwise.
>  */
> template <class InIteratorTypeT> inline
> bool TypePredicates::typeDerivedFrom(      InIteratorTypeT  begin,
>                                            InIteratorTypeT  end,
>                                      const OSG::TypeBase   &type  )
>
>
> In my case MyMaterial is derived from Material but the test gives only true 
> if Material would be derived from MyMaterial what is not the case.

I'm not following this reasoning; I think I'm overlooking something, sorry. If 
you put MyMaterial's type into the list, other Materials should not be shared, 
but MyMaterials (and types derived from MyMaterial) should be shared; at least 
I believe that was the idea modulo bugs.

Cheers,
Carsten
_______________________________________________
Opensg-users mailing list
Opensg-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensg-users

Reply via email to