Exchange Toolkit
ExchangeToolkit.h
1 #pragma once
2 
456 #include <vector>
457 #include <set>
458 #include <unordered_map>
459 #include <functional>
460 #include <memory>
461 #include <algorithm>
462 #include <iterator>
463 
464 #ifdef _MSC_VER
465 #pragma warning(push)
466 #pragma warning(disable : 4503)
467 #endif
468 
469 namespace ts3d {
477  class CheckResult {
478  public:
484  static CheckResult &instance( void ) {
485  static CheckResult _instance;
486  return _instance;
487  }
488 
493  void setFailureCallback( std::function<bool(CheckResult const&)> failure_cb ) {
494  _failureCallback = failure_cb;
495  }
496 
499  std::string const &file( void ) const {
500  return _file;
501  }
502 
505  int const &line( void ) const {
506  return _line;
507  }
508 
511  std::string const &fn( void ) const {
512  return _fn;
513  }
514 
517  A3DStatus const &result( void ) const {
518  return _result;
519  }
520 
521 
525  bool _record( std::string const file, int const line_no, std::string const fn, A3DStatus const result ) {
526  _file = file;
527  _line = line_no;
528  _fn = fn;
529  _result = result;
530  if( _result != A3D_SUCCESS && _failureCallback ) {
531  return _failureCallback(*this);
532  }
533  return A3D_SUCCESS == _result;
534  }
535 
536  private:
537  CheckResult( void ) {}
538  CheckResult( CheckResult const &other ) = delete;
539 
540  std::string _file;
541  int _line = 0;
542  std::string _fn;
543  A3DStatus _result = A3D_SUCCESS;
544  std::function<bool(CheckResult const&)> _failureCallback = [](ts3d::CheckResult const &r ) {
545  std::string const error_string = A3DMiscGetErrorMsg( r.result() );
546  std::cerr << "API FAILURE: " << r.fn() << " [" << r.file() << ":" << r.line() << "] == " << error_string << "(" << r.result() << ")" << std::endl;
547  return false;
548  };
549 
550  };
551 }
552 
558 #define CheckResult( f ) \
559  ts3d::CheckResult::instance()._record( __FILE__, __LINE__, #f, f )
560 
570 #define A3D_HELPERS( A3D_VOID_TYPE ) \
571 namespace ts3d {\
572  \
573  \
574  \
575 struct A3D_VOID_TYPE ## Wrapper { \
576  \
577  \
578  using DataType = A3D_VOID_TYPE ## Data; \
579  \
580 \
581  \
582  A3D_VOID_TYPE ## Wrapper( A3D_VOID_TYPE *ntt = nullptr ) { \
583  A3D_INITIALIZE_DATA( A3D_VOID_TYPE ## Data, _d ); \
584  if( ntt ) A3D_VOID_TYPE ## Get( ntt, &_d ); \
585  } \
586  \
587  \
588  ~A3D_VOID_TYPE ## Wrapper( void ) { \
589  A3D_VOID_TYPE ## Get( nullptr, &_d ); \
590  } \
591  \
592  \
593  DataType const *operator->() const { \
594  return &_d; \
595  } \
596  \
597  \
598  \
599  \
600  DataType *operator->() { \
601  return &_d; \
602  } \
603  \
604  \
605  \
607  void reset( A3D_VOID_TYPE *ntt ) { \
608  A3D_VOID_TYPE ## Get( nullptr, &_d ); \
609  if( ntt ) A3D_VOID_TYPE ## Get( ntt, &_d ); \
610  }\
611  \
612  \
613  DataType _d; \
614  }; \
615 }
616 
617 A3D_HELPERS(A3DAsmFilter)
618 A3D_HELPERS(A3DAsmModelFile)
619 A3D_HELPERS(A3DAsmPartDefinition)
620 A3D_HELPERS(A3DAsmProductOccurrence)
621 A3D_HELPERS(A3DCrvBlend02Boundary)
622 A3D_HELPERS(A3DCrvCircle)
623 A3D_HELPERS(A3DCrvComposite)
624 A3D_HELPERS(A3DCrvEllipse)
625 A3D_HELPERS(A3DCrvEquation)
626 A3D_HELPERS(A3DCrvHelix)
627 A3D_HELPERS(A3DCrvHyperbola)
628 A3D_HELPERS(A3DCrvIntersection)
629 A3D_HELPERS(A3DCrvLine)
630 A3D_HELPERS(A3DCrvNurbs)
631 A3D_HELPERS(A3DCrvOffset)
632 A3D_HELPERS(A3DCrvOnSurf)
633 A3D_HELPERS(A3DCrvParabola)
634 A3D_HELPERS(A3DCrvPolyLine)
635 A3D_HELPERS(A3DCrvTransform)
636 A3D_HELPERS(A3DDrawingBlockBasic)
637 A3D_HELPERS(A3DDrawingBlockOperator)
638 A3D_HELPERS(A3DDrawingClipFrame)
639 A3D_HELPERS(A3DDrawingCurve)
640 A3D_HELPERS(A3DDrawingFilledArea)
641 A3D_HELPERS(A3DDrawingModel)
642 A3D_HELPERS(A3DDrawingPicture)
643 A3D_HELPERS(A3DDrawingSheet)
644 A3D_HELPERS(A3DDrawingSheetFormat)
645 A3D_HELPERS(A3DDrawingVertices)
646 A3D_HELPERS(A3DDrawingView)
647 A3D_HELPERS(A3DFRMFeature)
648 A3D_HELPERS(A3DFRMFeatureLinkedItem)
649 A3D_HELPERS(A3DFRMFeatureTree)
650 A3D_HELPERS(A3DFRMParameter)
651 A3D_HELPERS(A3DGlobal)
652 A3D_HELPERS(A3DGraphAmbientLight)
653 A3D_HELPERS(A3DGraphCamera)
654 A3D_HELPERS(A3DGraphDirectionalLight)
655 A3D_HELPERS(A3DGraphPointLight)
656 A3D_HELPERS(A3DGraphSceneDisplayParameters)
657 A3D_HELPERS(A3DGraphSpotLight)
658 A3D_HELPERS(A3DGraphTextureTransformation)
659 A3D_HELPERS(A3DGraphics)
660 A3D_HELPERS(A3DHLRRepresentationItem)
661 A3D_HELPERS(A3DMDDimensionCombinedToleranceFormat)
662 A3D_HELPERS(A3DMDDimensionExtentionLine)
663 A3D_HELPERS(A3DMDDimensionExtremity)
664 A3D_HELPERS(A3DMDDimensionForeshortened)
665 A3D_HELPERS(A3DMDDimensionFunnel)
666 A3D_HELPERS(A3DMDDimensionLine)
667 A3D_HELPERS(A3DMDDimensionLineSymbol)
668 A3D_HELPERS(A3DMDDimensionSecondPart)
669 A3D_HELPERS(A3DMDDimensionSimpleToleranceFormat)
670 A3D_HELPERS(A3DMDDimensionValue)
671 A3D_HELPERS(A3DMDDimensionValueFormat)
672 A3D_HELPERS(A3DMDFCFDraftingRow)
673 A3D_HELPERS(A3DMDFCFDrawingRow)
674 A3D_HELPERS(A3DMDFCFIndicator)
675 A3D_HELPERS(A3DMDFCFRowDatum)
676 A3D_HELPERS(A3DMDFCFToleranceValue)
677 A3D_HELPERS(A3DMDFCProjectedZone)
678 A3D_HELPERS(A3DMDFCTolerancePerUnit)
679 A3D_HELPERS(A3DMDFCValue)
680 A3D_HELPERS(A3DMDFeatureControlFrame)
681 A3D_HELPERS(A3DMDLeaderDefinition)
682 A3D_HELPERS(A3DMDLeaderSymbol)
683 A3D_HELPERS(A3DMDMarkupLeaderStub)
684 A3D_HELPERS(A3DMDPosition2D)
685 A3D_HELPERS(A3DMDPosition3D)
686 A3D_HELPERS(A3DMDPositionReference)
687 A3D_HELPERS(A3DMDTextPosition)
688 A3D_HELPERS(A3DMDTextProperties)
689 A3D_HELPERS(A3DMDToleranceSize)
690 A3D_HELPERS(A3DMDToleranceSizeValue)
691 A3D_HELPERS(A3DMarkupBalloon)
692 A3D_HELPERS(A3DMarkupCoordinate)
693 A3D_HELPERS(A3DMarkupDatum)
694 A3D_HELPERS(A3DMarkupDefinition)
695 A3D_HELPERS(A3DMarkupDimension)
696 A3D_HELPERS(A3DMarkupFastener)
697 A3D_HELPERS(A3DMarkupGDT)
698 A3D_HELPERS(A3DMarkupLineWelding)
699 A3D_HELPERS(A3DMarkupLocator)
700 A3D_HELPERS(A3DMarkupMeasurementPoint)
701 A3D_HELPERS(A3DMarkupRichText)
702 A3D_HELPERS(A3DMarkupRoughness)
703 A3D_HELPERS(A3DMarkupSpotWelding)
704 A3D_HELPERS(A3DMarkupText)
705 A3D_HELPERS(A3DMathFct1DArctanCos)
706 A3D_HELPERS(A3DMathFct1DCombination)
707 A3D_HELPERS(A3DMathFct1DFraction)
708 A3D_HELPERS(A3DMathFct1DPolynom)
709 A3D_HELPERS(A3DMathFct1DTrigonometric)
710 A3D_HELPERS(A3DMathFct3DLinear)
711 A3D_HELPERS(A3DMathFct3DNonLinear)
712 A3D_HELPERS(A3DMiscAttribute)
713 A3D_HELPERS(A3DMiscCartesianTransformation)
714 A3D_HELPERS(A3DMiscCascadedAttributes)
715 A3D_HELPERS(A3DMiscEntityReference)
716 A3D_HELPERS(A3DMiscGeneralTransformation)
717 A3D_HELPERS(A3DMiscMarkupLinkedItem)
718 A3D_HELPERS(A3DMiscReferenceOnCsysItem)
719 A3D_HELPERS(A3DMiscReferenceOnTess)
720 A3D_HELPERS(A3DMiscReferenceOnTopology)
721 A3D_HELPERS(A3DMkpAnnotationItem)
722 A3D_HELPERS(A3DMkpAnnotationReference)
723 A3D_HELPERS(A3DMkpAnnotationSet)
724 A3D_HELPERS(A3DMkpLeader)
725 A3D_HELPERS(A3DMkpMarkup)
726 A3D_HELPERS(A3DMkpRTFField)
727 A3D_HELPERS(A3DMkpView)
728 A3D_HELPERS(A3DRiBrepModel)
729 A3D_HELPERS(A3DRiCoordinateSystem)
730 A3D_HELPERS(A3DRiCurve)
731 A3D_HELPERS(A3DRiDirection)
732 A3D_HELPERS(A3DRiPlane)
733 A3D_HELPERS(A3DRiPointSet)
734 A3D_HELPERS(A3DRiPolyBrepModel)
735 A3D_HELPERS(A3DRiPolyWire)
736 A3D_HELPERS(A3DRiRepresentationItem)
737 A3D_HELPERS(A3DRiSet)
738 A3D_HELPERS(A3DRootBase)
739 A3D_HELPERS(A3DRootBaseWithGraphics)
740 A3D_HELPERS(A3DSurfBlend01)
741 A3D_HELPERS(A3DSurfBlend02)
742 A3D_HELPERS(A3DSurfBlend03)
743 A3D_HELPERS(A3DSurfCone)
744 A3D_HELPERS(A3DSurfCylinder)
745 A3D_HELPERS(A3DSurfCylindrical)
746 A3D_HELPERS(A3DSurfExtrusion)
747 A3D_HELPERS(A3DSurfFromCurves)
748 A3D_HELPERS(A3DSurfNurbs)
749 A3D_HELPERS(A3DSurfOffset)
750 A3D_HELPERS(A3DSurfPipe)
751 A3D_HELPERS(A3DSurfPlane)
752 A3D_HELPERS(A3DSurfRevolution)
753 A3D_HELPERS(A3DSurfRuled)
754 A3D_HELPERS(A3DSurfSphere)
755 A3D_HELPERS(A3DSurfTorus)
756 A3D_HELPERS(A3DSurfTransform)
757 A3D_HELPERS(A3DTess3D)
758 A3D_HELPERS(A3DTess3DWire)
759 A3D_HELPERS(A3DTessBase)
760 A3D_HELPERS(A3DTessMarkup)
761 A3D_HELPERS(A3DTopoBody)
762 A3D_HELPERS(A3DTopoBrepData)
763 A3D_HELPERS(A3DTopoCoEdge)
764 A3D_HELPERS(A3DTopoConnex)
765 A3D_HELPERS(A3DTopoContext)
766 A3D_HELPERS(A3DTopoEdge)
767 A3D_HELPERS(A3DTopoFace)
768 A3D_HELPERS(A3DTopoLoop)
769 A3D_HELPERS(A3DTopoMultipleVertex)
770 A3D_HELPERS(A3DTopoShell)
771 A3D_HELPERS(A3DTopoSingleWireBody)
772 A3D_HELPERS(A3DTopoUniqueVertex)
773 A3D_HELPERS(A3DTopoWireEdge)
774 
775 
776 
777 namespace ts3d {
782  template<typename T, typename S>
783  std::vector<T> toVector( T *d, S const &sz ) {
784  return std::vector<T>( d, d+sz );
785  }
786 }
787 
788 namespace {
789  std::pair<A3DBool, double> getUnitFromPO( A3DAsmProductOccurrence *po ) {
790  if( nullptr == po ) {
791  return std::make_pair(static_cast<A3DBool>( false ), 0. );
792  }
793 
795 
796  if(!d->m_bUnitFromCAD && nullptr != d->m_pPrototype ) {
797  return getUnitFromPO( d->m_pPrototype );
798  }
799 
800  return std::make_pair( d->m_bUnitFromCAD, d->m_dUnit );
801  }
802 
803  double getUnitFactor( std::vector<A3DAsmProductOccurrence*> const &pos ) {
804  for( auto po : pos ) {
805  auto po_unit = getUnitFromPO( po );
806  if(po_unit.first) {
807  return po_unit.second;
808  } else {
810  auto const child_pos = ts3d::toVector( d->m_ppPOccurrences, d->m_uiPOccurrencesSize );
811  return getUnitFactor( child_pos );
812  }
813  }
814  return -1.;
815  }
816 }
817 
818 namespace ts3d {
822  using EntityArray = std::vector<A3DEntity*>;
823 
827  using EntitySet = std::set<A3DEntity*>;
828 
832  static inline bool isRepresentationItem( A3DEEntityType const &t ) {
833  return (kA3DTypeRiRepresentationItem == t ||
834  kA3DTypeRiSet == t ||
835  kA3DTypeRiCurve == t ||
836  kA3DTypeRiPlane == t ||
837  kA3DTypeRiPointSet == t ||
838  kA3DTypeRiPolyWire == t ||
839  kA3DTypeRiPolyBrepModel == t ||
840  kA3DTypeRiBrepModel == t ||
841  kA3DTypeRiDirection == t);
842  }
843 
847  static inline bool isTessBase( A3DEEntityType const &t ) {
848  return (kA3DTypeTessBase == t ||
849  kA3DTypeTess3D == t ||
850  kA3DTypeTess3DWire == t ||
851  kA3DTypeTessMarkup == t);
852  }
853 
857  static inline bool isAnnotationEntity( A3DEEntityType const &t ) {
858  return (kA3DTypeMkpAnnotationItem == t ||
859  kA3DTypeMkpAnnotationSet == t ||
860  kA3DTypeMkpAnnotationReference == t);
861  }
862 
866  static inline bool isMarkup( A3DEEntityType const &t ) {
867  return (kA3DTypeMDPosition2D == t ||
868  kA3DTypeMDPosition3D == t ||
869  kA3DTypeMDPositionReference == t ||
870  kA3DTypeMarkupCoordinate == t ||
871  kA3DTypeMarkupText == t ||
872  kA3DTypeMDTextPosition == t ||
873  kA3DTypeMarkupRichText == t ||
874  kA3DTypeMarkupDimension == t ||
875  kA3DTypeMarkupDatum == t ||
876  kA3DTypeMarkupGDT == t ||
877  kA3DTypeMarkupRoughness == t ||
878  kA3DTypeMarkupBalloon == t ||
879  kA3DTypeMarkupFastener == t ||
880  kA3DTypeMarkupLocator == t ||
881  kA3DTypeMarkupMeasurementPoint == t ||
882  kA3DTypeMarkupLineWelding == t ||
883  kA3DTypeMarkupSpotWelding == t);
884  }
885 
890  static inline A3DEEntityType getEntityType( A3DEntity *ntt ) {
891  auto result = kA3DTypeUnknown;
892  if( nullptr != ntt ) {
893  A3DEntityGetType( ntt, &result );
894  }
895  return result;
896  }
897 
903  enum class PrototypeOption {
905  Use,
907  DoNotUse
908  };
909 
914  static inline A3DAsmPartDefinition *getPartDefinition( A3DAsmProductOccurrence *po, PrototypeOption const &opt = PrototypeOption::Use ) {
915  if( nullptr == po ) {
916  return nullptr;
917  }
919  return d->m_pPart ? d->m_pPart : (opt == PrototypeOption::Use ? getPartDefinition( d->m_pPrototype, opt ) : nullptr );
920  }
921 
925  static inline EntityArray getProductOccurrences( A3DAsmProductOccurrence *po, PrototypeOption const &opt = PrototypeOption::Use ) {
926  if( nullptr == po ) {
927  return EntityArray();
928  }
929 
931  return d->m_uiPOccurrencesSize != 0 ? toVector( d->m_ppPOccurrences, d->m_uiPOccurrencesSize ) : (opt == PrototypeOption::Use ? getProductOccurrences( d->m_pPrototype, opt ) : EntityArray() );
932  }
933 
938  static inline double getUnit( A3DAsmModelFile *modelFile ) {
939  A3DAsmModelFileWrapper d( modelFile );
940  return d->m_bUnitFromCAD ? d->m_dUnit : getUnitFactor( toVector( d->m_ppPOccurrences, d->m_uiPOccurrencesSize ) );
941  }
942 }
943 
946 #define kA3DTypeTopoVertex static_cast<A3DEEntityType>(kA3DTypeTopo + 18)
947 
950 #define kA3DTypeMkpAnnotationEntity static_cast<A3DEEntityType>(kA3DTypeMkp + 7)
951 
952 
953 
954 namespace ts3d {
964 
965 
971  using InstancePathArray = std::vector<InstancePath>;
972 
990  static InstancePathArray getLeafInstances( A3DEntity *owner, A3DEEntityType const &leaf_type );
991 
993  static inline EntitySet getUniqueParts( A3DAsmModelFile *modelFile );
994 
998  using InstancePathMap = std::unordered_map<A3DEntity*, InstancePathArray>;
999 
1007  static inline EntitySet getUniqueLeafEntities( A3DEntity *owner, A3DEEntityType const &leaf_type );
1008 
1011  static inline EntitySet getUniqueChildren( A3DEntity *owner, A3DEEntityType const &leaf_type ) {
1012  return getUniqueLeafEntities( owner, leaf_type );
1013  }
1014 
1023  static inline EntitySet getUniqueLeafEntities( A3DEntity *owner, A3DEEntityType const &leaf_type, InstancePathMap &instance_path_map );
1024 
1027  static inline EntitySet getUniqueChildren( A3DEntity *owner, A3DEEntityType const &leaf_type, InstancePathMap &instance_path_map ) {
1028  return getUniqueLeafEntities( owner, leaf_type, instance_path_map );
1029  }
1030 
1037  static inline InstancePath getOwningInstance( InstancePath const &instance_path, A3DEEntityType const &owner_type );
1038 
1045  static inline EntityArray getChildren( A3DEntity *parent, A3DEEntityType const &child_type );
1046 
1047 }
1048 
1049 
1050 namespace std {
1052  template <> struct hash<A3DEEntityType> {
1053  size_t operator()(A3DEEntityType const& s) const noexcept {
1054  return s;
1055  }
1056  };
1057  template<> struct hash<ts3d::InstancePath> {
1058  size_t operator()(ts3d::InstancePath const &i ) const noexcept {
1059  auto seed = i.size();
1060  auto const magic_number = reinterpret_cast<size_t>( A3DAsmModelFileGet );
1061  for( auto &ntt : i ) {
1062  seed ^= reinterpret_cast<size_t>( ntt ) + magic_number + (seed << 6) + (seed >>2 );
1063  }
1064  return seed;
1065  }
1066  };
1067 }
1068 
1069 namespace {
1070  using namespace ts3d;
1071  using TypeSet = std::set<A3DEEntityType>;
1072  using TypePath = std::vector<A3DEEntityType>;
1073  using TypePathArray = std::vector<TypePath>;
1074 
1075  // Function object that can be invoked to obtain an EntityArray
1076  // of the child objects
1077  using GetterFunction = std::function<EntityArray (A3DEntity*)>;
1078 
1079  // The GetterMap is used to look up a getter function for a
1080  // particular child object type
1081  using GetterMap = std::unordered_map<A3DEEntityType, GetterFunction>;
1082 
1083  // The GetterMapsByType is used to look up a GetterMap for a
1084  // particular owning object type
1085  using GetterMapsByType = std::unordered_map<A3DEEntityType, GetterMap>;
1086 
1087  // This is the static instance of a GetterMapsByType. It is
1088  // initialized with parent type to { child type } hash, and
1089  // for each child type it contains a function object for
1090  // obtaining the children of that type. See the typedef
1091  // statements above to better understand the initializer
1092  // syntax.
1093  static GetterMapsByType _getterMapByType = {
1094  { // an entry in GetterMapsByType
1095  kA3DTypeAsmModelFile, // A3DEEntityType (owning object type)
1096  { // GetterMap
1097  { // an entry in GetterMap
1098  kA3DTypeAsmProductOccurrence, // A3DEEntityType (child object type)
1099  [](A3DEntity *ntt) { // GetteFunction (function for getting children)
1100  A3DAsmModelFileWrapper d( ntt );
1101  return toVector( d->m_ppPOccurrences, d->m_uiPOccurrencesSize );
1102  }
1103  }
1104  }
1105  },
1106  {
1107  kA3DTypeAsmProductOccurrence,
1108  {
1109  {
1110  kA3DTypeAsmProductOccurrence,
1111  [](A3DEntity *ntt) {
1112  return getProductOccurrences( ntt, PrototypeOption::Use );
1113  }
1114  },
1115  {
1116  kA3DTypeAsmPartDefinition,
1117  [](A3DEntity *ntt) {
1118  auto const part_definition = getPartDefinition( ntt, PrototypeOption::Use );
1119  return nullptr == part_definition ? EntityArray() : EntityArray( 1, part_definition );
1120  }
1121  },
1122  {
1123  kA3DTypeMkpView,
1124  [](A3DEntity *ntt) {
1126  return toVector( d->m_ppViews, d->m_uiViewsSize );
1127  }
1128  },
1129  {
1130  kA3DTypeGraphCamera,
1131  [](A3DEntity *ntt) {
1133  return toVector( d->m_ppCamera, d->m_uiCameraSize );
1134  }
1135  },
1136  {
1137  kA3DTypeMkpAnnotationEntity,
1138  [](A3DEntity *ntt) {
1140  return toVector( d->m_ppAnnotations, d->m_uiAnnotationsSize );
1141  }
1142  }
1143  }
1144  },
1145  {
1146  kA3DTypeAsmPartDefinition,
1147  {
1148  {
1149  kA3DTypeRiRepresentationItem,
1150  [](A3DEntity *ntt) {
1151  A3DAsmPartDefinitionWrapper d( ntt );
1152  return toVector( d->m_ppRepItems, d->m_uiRepItemsSize );
1153  }
1154  },
1155  {
1156  kA3DTypeMkpAnnotationEntity,
1157  [](A3DEntity *ntt) {
1158  A3DAsmPartDefinitionWrapper d( ntt );
1159  return toVector( d->m_ppAnnotations, d->m_uiAnnotationsSize );
1160  }
1161  },
1162  {
1163  kA3DTypeMkpView,
1164  []( A3DEntity *ntt) {
1165  A3DAsmPartDefinitionWrapper d( ntt );
1166  return toVector( d->m_ppViews, d->m_uiViewsSize );
1167  }
1168  }
1169  }
1170  },
1171  {
1172  kA3DTypeRiRepresentationItem,
1173  {
1174  {
1175  kA3DTypeRiRepresentationItem,
1176  [](A3DEntity *ntt) {
1177  if( kA3DTypeRiSet == getEntityType( ntt ) ) {
1178  A3DRiSetWrapper d( ntt );
1179  return toVector( d->m_ppRepItems, d->m_uiRepItemsSize );
1180  }
1181  return EntityArray();
1182  }
1183  },
1184  {
1185  kA3DTypeTopoBrepData,
1186  [](A3DEntity *ntt) {
1187  auto const ntt_type = getEntityType( ntt );
1188  if( kA3DTypeRiBrepModel == ntt_type ) {
1189  A3DRiBrepModelWrapper d( ntt );
1190  return EntityArray( 1, d->m_pBrepData );
1191  } else if( kA3DTypeRiPlane == ntt_type ) {
1192  A3DRiPlaneWrapper d( ntt );
1193  return EntityArray( 1, d->m_pBrepData );
1194  }
1195  return EntityArray();
1196  }
1197  },
1198  {
1199  kA3DTypeTopoSingleWireBody,
1200  [](A3DEntity *ntt) {
1201  if( kA3DTypeRiCurve == getEntityType( ntt ) ) {
1202  A3DRiCurveWrapper d( ntt );
1203  return EntityArray( 1, d->m_pBody );
1204  }
1205  return EntityArray();
1206  }
1207  }
1208  }
1209  },
1210  {
1211  kA3DTypeTopoBrepData,
1212  {
1213  {
1214  kA3DTypeTopoConnex,
1215  [](A3DEntity *ntt) {
1216  A3DTopoBrepDataWrapper d( ntt );
1217  return toVector( d->m_ppConnexes, d->m_uiConnexSize );
1218  }
1219  }
1220  }
1221  },
1222  {
1223  kA3DTypeTopoConnex,
1224  {
1225  {
1226  kA3DTypeTopoShell,
1227  [](A3DEntity *ntt) {
1228  A3DTopoConnexWrapper d( ntt );
1229  return toVector( d->m_ppShells, d->m_uiShellSize );
1230  }
1231  }
1232  }
1233  },
1234  {
1235  kA3DTypeTopoShell,
1236  {
1237  {
1238  kA3DTypeTopoFace,
1239  [](A3DEntity *ntt) {
1240  A3DTopoShellWrapper d( ntt );
1241  return toVector( d->m_ppFaces, d->m_uiFaceSize );
1242  }
1243  }
1244  }
1245  },
1246  {
1247  kA3DTypeTopoFace,
1248  {
1249  {
1250  kA3DTypeTopoLoop,
1251  [](A3DEntity *ntt) {
1252  A3DTopoFaceWrapper d( ntt );
1253  return toVector( d->m_ppLoops, d->m_uiLoopSize );
1254  }
1255  }
1256  }
1257  },
1258  {
1259  kA3DTypeTopoLoop,
1260  {
1261  {
1262  kA3DTypeTopoCoEdge,
1263  [](A3DEntity *ntt) {
1264  A3DTopoLoopWrapper d( ntt );
1265  return toVector( d->m_ppCoEdges, d->m_uiCoEdgeSize );
1266  }
1267  }
1268  }
1269  },
1270  {
1271  kA3DTypeTopoCoEdge,
1272  {
1273  {
1274  kA3DTypeTopoEdge,
1275  []( A3DEntity *ntt ) {
1276  A3DTopoCoEdgeWrapper d( ntt );
1277  return EntityArray( 1, d->m_pEdge );
1278 
1279  }
1280  }
1281  }
1282  },
1283  {
1284  kA3DTypeTopoEdge,
1285  {
1286  {
1287  kA3DTypeTopoVertex,
1288  []( A3DEntity *ntt ) {
1289  A3DTopoEdgeWrapper d( ntt );
1291  result.reserve( 2 );
1292  result.push_back( d->m_pStartVertex );
1293  result.push_back( d->m_pEndVertex );
1294  return result;
1295  }
1296  }
1297  }
1298  },
1299  {
1300  kA3DTypeTopoSingleWireBody,
1301  {
1302  {
1303  kA3DTypeTopoWireEdge,
1304  []( A3DEntity *ntt ) {
1306  return EntityArray( 1, d->m_pWireEdge );
1307  }
1308  }
1309  }
1310  },
1311  {
1312  kA3DTypeMkpAnnotationEntity,
1313  {
1314  {
1315  kA3DTypeMkpAnnotationEntity,
1316  []( A3DEntity *ntt ) {
1317  if( kA3DTypeMkpAnnotationSet == getEntityType( ntt ) ) {
1318  A3DMkpAnnotationSetWrapper d( ntt );
1319  return toVector( d->m_ppAnnotations, d->m_uiAnnotationsSize );
1320  }
1321  return EntityArray();
1322  }
1323  },
1324  {
1325  kA3DTypeMiscMarkupLinkedItem,
1326  []( A3DEntity *ntt ) {
1327  if( kA3DTypeMkpAnnotationReference == getEntityType( ntt ) ) {
1329  return toVector( d->m_ppLinkedItems, d->m_uiLinkedItemsSize );
1330  }
1331  return EntityArray();
1332  }
1333  },
1334  {
1335  kA3DTypeMkpMarkup, // Base type, matches all markups
1336  []( A3DEntity *ntt ) {
1337  if( kA3DTypeMkpAnnotationItem == getEntityType( ntt ) ) {
1338  A3DMkpAnnotationItemWrapper d( ntt );
1339  return EntityArray( 1, d->m_pMarkup );
1340  }
1341  return EntityArray();
1342  }
1343  }
1344  }
1345  },
1346  {
1347  kA3DTypeMkpMarkup,
1348  {
1349  {
1350  kA3DTypeMiscMarkupLinkedItem,
1351  []( A3DEntity *ntt ) {
1352  A3DMkpMarkupWrapper d( ntt );
1353  return toVector( d->m_ppLinkedItems, d->m_uiLinkedItemsSize );
1354  }
1355  },
1356  {
1357  kA3DTypeMkpLeader,
1358  []( A3DEntity *ntt ) {
1359  A3DMkpMarkupWrapper d( ntt );
1360  return toVector( d->m_ppLeaders, d->m_uiLeadersSize );
1361  }
1362  }
1363  }
1364  }
1365  };
1366 
1367  // For an entity type child_type, this function returns
1368  // a list of entity types that can contain the child type
1369  static inline TypeSet getPossibleParents( A3DEEntityType const &child_type ) {
1370  static std::unordered_map<A3DEEntityType, TypeSet> _cache;
1371  auto const it = _cache.find( child_type );
1372  if( std::end( _cache ) != it ) {
1373  return it->second;
1374  }
1375 
1376  TypeSet possible_parents;
1377  for( auto const owning_type_entry : _getterMapByType ) {
1378  auto const owning_type = owning_type_entry.first;
1379  for( auto const child_type_entry : owning_type_entry.second ) {
1380  if( child_type_entry.first == child_type ) {
1381  possible_parents.insert( owning_type );
1382  break;
1383  }
1384  }
1385  }
1386  _cache[child_type] = possible_parents;
1387  return possible_parents;
1388  }
1389 
1390  // Since some entity types "derived", this function is a helper
1391  // used to obtain a "base" type for entity_type
1392  static inline A3DEEntityType getBaseType( A3DEEntityType const &entity_type ) {
1393  auto base_type = entity_type;
1394  if( isRepresentationItem( entity_type ) ) {
1395  base_type = kA3DTypeRiRepresentationItem;
1396  } else if( isTessBase( entity_type ) ) {
1397  base_type = kA3DTypeTessBase;
1398  } else if( kA3DTypeTopoUniqueVertex == entity_type || kA3DTypeTopoMultipleVertex == entity_type ) {
1399  base_type = kA3DTypeTopoVertex;
1400  } else if( isAnnotationEntity( entity_type ) ) {
1401  base_type = kA3DTypeMkpAnnotationEntity;
1402  } else if( isMarkup( entity_type ) ) {
1403  base_type = kA3DTypeMkpMarkup;
1404  }
1405  return base_type;
1406  }
1407 
1408  // This function can be used to obtain a set of type paths where the parent type
1409  // and leaf child type values are both given. Each type path returned is one
1410  // possible way to traverse the Exchange data structures such that the beginning
1411  // entity type and ending entity type are equal to the input parameters.
1412  static TypePathArray getPossibleTypePaths( A3DEEntityType const &parent_type, A3DEEntityType const &child_type ) {
1413 
1414  // check to see if the given owner and child type values are present in the cache
1415  static std::unordered_map< A3DEEntityType, std::unordered_map< A3DEEntityType, TypePathArray >> _cache;
1416  auto const parent_type_it = _cache.find( parent_type );
1417  if(std::end( _cache ) != parent_type_it ) {
1418  auto const child_type_it = parent_type_it->second.find( child_type );
1419  if( std::end( parent_type_it->second ) != child_type_it ) {
1420  return child_type_it->second;
1421  }
1422  }
1423 
1424  // result is not present in the cache, so compute it
1425  TypePathArray type_paths;
1426  auto const possible_parents = getPossibleParents( child_type );
1427  if( std::end( possible_parents ) != possible_parents.find( parent_type ) ) {
1428  // child entity type is an immediate child of parent entity type
1429  TypePath type_path;
1430  type_path.push_back( parent_type );
1431  type_path.push_back( child_type );
1432  type_paths.push_back( type_path );
1433  } else {
1434  // child entity type is not an immediate child of parent entity type
1435  // so we must iterate over the list of all possible parent types
1436  // and for each of those parent types, examine up the ownership chain
1437  for( auto const intermediate_parent_type : possible_parents ) {
1438  if( intermediate_parent_type != child_type ) {
1439  auto const intermediate_type_paths = getPossibleTypePaths( parent_type, intermediate_parent_type );
1440  for( auto const intermediate_type_path : intermediate_type_paths ) {
1441  type_paths.push_back( intermediate_type_path );
1442  type_paths.back().push_back( child_type );
1443  }
1444  }
1445  }
1446  }
1447  // augment the cache
1448 
1449  _cache[parent_type][child_type] = type_paths;
1450  return type_paths;
1451  }
1452 
1453  static ts3d::InstancePathArray getInstancePaths( A3DEntity *owner, TypePath const &type_path, ts3d::InstancePath const &instance_path = ts3d::InstancePath() ) {
1454  ts3d::InstancePathArray instance_paths;
1455  auto const owner_type = ts3d::getEntityType( owner );
1456  auto const owner_base_type = getBaseType( owner_type );
1457  auto const owner_decomposer_it = _getterMapByType.find( owner_base_type );
1458  auto base_instance_path = instance_path;
1459  base_instance_path.push_back( owner );
1460 
1461  if(std::end( _getterMapByType ) == owner_decomposer_it ) {
1462  if( type_path.size() == 1 && owner_base_type == type_path.back() ) {
1463  instance_paths.push_back( base_instance_path );
1464  }
1465  return instance_paths;
1466  }
1467 
1468 
1469  if( kA3DTypeAsmProductOccurrence == owner_base_type ) {
1470  auto const children = owner_decomposer_it->second[kA3DTypeAsmProductOccurrence]( owner );
1471  if( !children.empty() ) {
1472  for( auto child : children ) {
1473  auto const child_instance_paths = getInstancePaths( child, type_path, base_instance_path );
1474  std::copy( child_instance_paths.begin(), child_instance_paths.end(), std::back_inserter( instance_paths ) );
1475  }
1476  }
1477  } else if( kA3DTypeRiSet == owner_type ) {
1478  auto const children = owner_decomposer_it->second[kA3DTypeRiRepresentationItem]( owner );
1479  if( !children.empty() ) {
1480  for( auto child : children ) {
1481  auto const child_instance_paths = getInstancePaths( child, type_path, base_instance_path );
1482  std::copy( child_instance_paths.begin(), child_instance_paths.end(), std::back_inserter( instance_paths ) );
1483  }
1484  return instance_paths;
1485  }
1486  } else if( kA3DTypeMkpAnnotationSet == owner_type ) {
1487  auto const children = owner_decomposer_it->second[kA3DTypeMkpAnnotationEntity]( owner );
1488  if( !children.empty() ) {
1489  for( auto child : children ) {
1490  auto const child_instance_paths = getInstancePaths( child, type_path, base_instance_path );
1491  std::copy( child_instance_paths.begin(), child_instance_paths.end(), std::back_inserter( instance_paths ) );
1492  }
1493  }
1494  }
1495 
1496  TypePath const child_type_path( type_path.begin() + 1, type_path.end() );
1497  if(child_type_path.empty()) {
1498  instance_paths.push_back( base_instance_path );
1499  return instance_paths;
1500  }
1501  auto const children = owner_decomposer_it->second[child_type_path.front()]( owner );
1502  for(auto child : children ) {
1503  auto const child_instance_paths = getInstancePaths( child, child_type_path, base_instance_path );
1504  std::copy( child_instance_paths.begin(), child_instance_paths.end(), std::back_inserter( instance_paths ) );
1505  }
1506  return instance_paths;
1507  }
1508 }
1509 
1510 ts3d::InstancePathArray ts3d::getLeafInstances( A3DEntity *owner, A3DEEntityType const &leaf_type ) {
1512  auto const owner_base_type = getBaseType( getEntityType( owner ) );
1513  auto const leaf_base_type = getBaseType( leaf_type );
1514 
1515  auto const possible_type_paths = getPossibleTypePaths( owner_base_type, leaf_base_type );
1516  for( auto const possible_type_path : possible_type_paths ) {
1517  if( possible_type_path.empty() ) {
1518  continue;
1519  }
1520  auto const instance_paths = getInstancePaths( owner, possible_type_path );
1521  if( leaf_base_type != leaf_type ) {
1522  std::copy_if( instance_paths.begin(), instance_paths.end(), std::back_inserter( result ),
1523  [leaf_type](InstancePath const &instance_path) {
1524  auto const leaf_entity = instance_path.back();
1525  return getEntityType( leaf_entity ) == leaf_type;
1526  });
1527  } else {
1528  std::copy( instance_paths.begin(), instance_paths.end(), std::back_inserter( result ) );
1529  }
1530  }
1531 
1532  return result;
1533 }
1534 
1535 ts3d::EntitySet ts3d::getUniqueParts( A3DAsmModelFile *modelFile ) {
1536  return getUniqueLeafEntities( modelFile, kA3DTypeAsmPartDefinition );
1537 }
1538 
1539 ts3d::EntitySet ts3d::getUniqueLeafEntities( A3DEntity *owner, A3DEEntityType const &leaf_type ) {
1540  EntitySet result;
1541  auto const paths = getLeafInstances( owner, leaf_type );
1542  for( auto path : paths ) {
1543  result.insert( path.back() );
1544  }
1545  return result;
1546 }
1547 
1548 ts3d::EntitySet ts3d::getUniqueLeafEntities( A3DEntity *owner, A3DEEntityType const &leaf_type, InstancePathMap &instance_path_map ) {
1549  EntitySet result;
1550  auto const paths = getLeafInstances( owner, leaf_type );
1551  for( auto path : paths) {
1552  result.insert( path.back() );
1553  instance_path_map[path.back()].emplace_back( path );
1554  }
1555  return result;
1556 }
1557 
1558 ts3d::InstancePath ts3d::getOwningInstance( InstancePath const &instance_path, A3DEEntityType const &owner_type ) {
1559  auto result = instance_path;
1560  while( !result.empty() && getEntityType( result.back() ) != owner_type ) {
1561  result.pop_back();
1562  }
1563  return result;
1564 }
1565 
1566 ts3d::EntityArray ts3d::getChildren( A3DEntity *owner, A3DEEntityType const &child_type ) {
1567  auto const owner_type = ts3d::getEntityType( owner );
1568  auto const owner_base_type = getBaseType( owner_type );
1569  auto const child_base_type = getBaseType( child_type );
1570  auto const owner_decomposer_it = _getterMapByType.find( owner_base_type );
1571 
1573  auto const decomposer_it = owner_decomposer_it->second.find(child_base_type);
1574  if (std::end(owner_decomposer_it->second) == decomposer_it) {
1575  return result;
1576  }
1577  auto const children = decomposer_it->second( owner );
1578  std::copy_if( std::begin( children ), std::end( children ), std::back_inserter( result ), [child_type, child_base_type]( A3DEntity *child ) {
1579  return child_type == child_base_type || getEntityType( child ) == child_type;
1580  });
1581  return result;
1582 }
1583 
1584 
1585 namespace {
1586  static inline std::string getName( A3DEntity *ntt ) {
1587  ts3d::A3DRootBaseWrapper d( ntt );
1588  if( d->m_pcName ) {
1589  return d->m_pcName;
1590  }
1591 
1592  auto const t = ts3d::getEntityType( ntt );
1593  if( kA3DTypeAsmProductOccurrence == t ) {
1595  return getName( d->m_pPrototype );
1596  }
1597 
1598  return std::string();
1599  }
1600 
1601  A3DMiscTransformation *getLocation( A3DAsmProductOccurrence *po ) {
1602  if( nullptr == po ) {
1603  return nullptr;
1604  }
1605  A3DAsmProductOccurrenceData d;
1606  A3D_INITIALIZE_DATA( A3DAsmModelFileData, d );
1607  A3DAsmProductOccurrenceGet( po, &d );
1608  auto location = d.m_pLocation;
1609  auto prototype = d.m_pPrototype;
1610  A3DAsmProductOccurrenceGet( nullptr, &d );
1611  return location ? location : getLocation( prototype );
1612  }
1613 }
1614 
1615 namespace ts3d {
1616  class Instance;
1620  using InstancePtr = std::shared_ptr<Instance>;
1621 
1630  class Instance {
1631  public:
1634  Instance( InstancePath const &path )
1635  : _path( path ) {
1636  }
1637 
1638 
1641  Instance( Instance const &other )
1642  : _path( other._path ) {
1643  }
1644 
1645 
1648  Instance( Instance &&other )
1649  : _path( std::move( other._path ) ) {
1650  }
1651 
1652 
1655  virtual ~Instance( void ) {
1656  reset( InstancePath() );
1657  }
1658 
1661  Instance &operator=( Instance const &other ) {
1662  _path = other._path;
1663  return *this;
1664  }
1665 
1669  _path = std::move( other._path );
1670  return *this;
1671  }
1672 
1675  bool operator==( Instance const &other ) const {
1676  return _path == other._path;
1677  }
1678 
1681  std::string getName( void ) const {
1682  return ::getName( leaf() );
1683  }
1684 
1687  std::string getType( void ) const {
1688  return A3DMiscGetEntityTypeMsg( leafType() );
1689  }
1690 
1693  InstancePath const &path( void ) const {
1694  return _path;
1695  }
1696 
1699  Instance owner( void ) const {
1700  if( _path.size() < 2 ) {
1701  return Instance( InstancePath() );
1702  }
1703  auto owner_path = _path;
1704  owner_path.pop_back();
1705  return Instance( owner_path );
1706  }
1707 
1708 
1711  void reset( InstancePath const &new_path ) {
1712  if( new_path == _path ) {
1713  return;
1714  }
1715 
1716  _path = new_path;
1717 
1718  for( auto attrib : _cascaded_attribs ) {
1719  A3DMiscCascadedAttributesDelete( attrib );
1720  }
1721 
1722  _cascaded_attribs_data.reset( nullptr );
1723  }
1724 
1727  A3DEntity *leaf( void ) const {
1728  return _path.empty() ? nullptr : _path.back();
1729  }
1730 
1733  A3DEEntityType leafType( void ) const {
1734  return getEntityType( leaf() );
1735  }
1736 
1737 
1738 
1743  bool getNetRemoved( void ) const {
1744  return A3D_TRUE == getCascadedAttributesData()->m_bRemoved;
1745  }
1746 
1747 
1750  bool getNetShow( void ) const {
1751  return A3D_TRUE == getCascadedAttributesData()->m_bShow;
1752  }
1753 
1756  A3DGraphStyleData getNetStyle( void ) const {
1757  return getCascadedAttributesData()->m_sStyle;
1758  }
1759 
1762  A3DUns16 getNetLayer( void ) const {
1763  return getCascadedAttributesData()->m_usLayer;
1764  }
1767  protected:
1769  A3DMiscCascadedAttributesWrapper const &getCascadedAttributesData( void ) const {
1770  if( _cascaded_attribs.empty() ) {
1771  getCascadedAttributes();
1772  }
1773  return _cascaded_attribs_data;
1774  }
1775 
1777  A3DMiscCascadedAttributes *getCascadedAttributes( void ) const {
1778  if(_cascaded_attribs.empty() ) {
1779  _cascaded_attribs.push_back( nullptr );
1780  CheckResult( A3DMiscCascadedAttributesCreate( &_cascaded_attribs.back() ) );
1781  for( auto ntt : _path ) {
1782  if( A3DEntityIsBaseWithGraphicsType( ntt ) ) {
1783  auto father = _cascaded_attribs.back();
1784  _cascaded_attribs.push_back( nullptr );
1785  CheckResult( A3DMiscCascadedAttributesCreate( &_cascaded_attribs.back() ) );
1786  CheckResult( A3DMiscCascadedAttributesPush( _cascaded_attribs.back(), ntt, father ) );
1787  }
1788  }
1789  if( !_cascaded_attribs.empty() ) {
1790  _cascaded_attribs_data.reset( _cascaded_attribs.back() );
1791  }
1792  }
1793  return _cascaded_attribs.empty() ? nullptr : _cascaded_attribs.back();
1794  }
1795 
1797  InstancePath _path;
1799  mutable std::vector<A3DMiscCascadedAttributes*> _cascaded_attribs;
1801  mutable A3DMiscCascadedAttributesWrapper _cascaded_attribs_data;
1802  };
1803 
1808  class TessBaseInstance : public Instance {
1809  public:
1813  : Instance( path ) {
1814  if( !isTessBase( leafType() ) ) {
1815  throw std::invalid_argument( "Expected leaf node type of A3DTessBase. " );
1816  }
1817  _d.reset( leaf() );
1818  }
1819 
1820 
1824  double const *coords( void ) const {
1825  return _d->m_pdCoords;
1826  }
1827 
1830  A3DUns32 coordsSize( void ) const {
1831  return _d->m_uiCoordSize;
1832  }
1833 
1834  private:
1835  A3DTessBaseWrapper _d;
1836  };
1837 
1843  public:
1845  TessFaceDataHelper( A3DTessFaceData const &d, A3DUns32 const *triangulatedIndexes, A3DUns32 const *wireIndexes ) {
1846  auto sz_tri_idx = 0u;
1847  auto ti_index = d.m_uiStartTriangulated;
1848  if(kA3DTessFaceDataTriangle & d.m_usUsedEntitiesFlags) {
1849  auto const num_tris = d.m_puiSizesTriangulated[sz_tri_idx++];
1850  for(auto tri = 0u; tri < num_tris; tri++) {
1851  for(auto vert = 0u; vert < 3u; vert++) {
1852  _normals.push_back( triangulatedIndexes[ti_index++] );
1853  _vertices.push_back( triangulatedIndexes[ti_index++] );
1854  }
1855  }
1856  }
1857  if(d.m_uiSizesTriangulatedSize > sz_tri_idx && kA3DTessFaceDataTriangleFan & d.m_usUsedEntitiesFlags) {
1858  auto const num_fans = d.m_puiSizesTriangulated[sz_tri_idx++];
1859  for(auto fan_idx = 0u; fan_idx < num_fans; ++fan_idx) {
1860  auto const num_pts = d.m_puiSizesTriangulated[sz_tri_idx++];
1861  auto const root_n = triangulatedIndexes[ti_index++];
1862  auto const root_v = triangulatedIndexes[ti_index++];
1863  for(auto vert = 1u; vert < num_pts - 1u; vert++) {
1864  _normals.push_back( root_n );
1865  _vertices.push_back( root_v );
1866 
1867  _normals.push_back( triangulatedIndexes[ti_index++] );
1868  _vertices.push_back( triangulatedIndexes[ti_index++] );
1869 
1870  _normals.push_back( triangulatedIndexes[ti_index] );
1871  _vertices.push_back( triangulatedIndexes[ti_index + 1] );
1872  }
1873  ti_index += 2;
1874  }
1875  }
1876  if(d.m_uiSizesTriangulatedSize > sz_tri_idx && kA3DTessFaceDataTriangleStripe & d.m_usUsedEntitiesFlags) {
1877  auto const num_tri_stips = d.m_puiSizesTriangulated[sz_tri_idx++];
1878  for(auto strip_idx = 0u; strip_idx < num_tri_stips; ++strip_idx) {
1879  auto const num_pts = d.m_puiSizesTriangulated[sz_tri_idx++];
1880  ti_index += 2;
1881  for(auto vert = 1u; vert < num_pts - 1u; vert++) {
1882  auto const prev_n = triangulatedIndexes[ti_index - 2];
1883  auto const prev_v = triangulatedIndexes[ti_index - 1];
1884  auto const current_n = triangulatedIndexes[ti_index++];
1885  auto const current_v = triangulatedIndexes[ti_index++];
1886  auto const next_n = triangulatedIndexes[ti_index];
1887  auto const next_v = triangulatedIndexes[ti_index + 1];
1888 
1889  _normals.push_back( current_n );
1890  _vertices.push_back( current_v );
1891  _normals.push_back( vert % 2 ? next_n : prev_n );
1892  _vertices.push_back( vert % 2 ? next_v : prev_v );
1893  _normals.push_back( vert % 2 ? prev_n : next_n );
1894  _vertices.push_back( vert % 2 ? prev_v : next_v );
1895  }
1896  ti_index += 2;
1897  }
1898  }
1899  if(d.m_uiSizesTriangulatedSize > sz_tri_idx && kA3DTessFaceDataTriangleOneNormal & d.m_usUsedEntitiesFlags) {
1900  auto const num_tris_1normal = d.m_puiSizesTriangulated[sz_tri_idx++];
1901  for(auto tri = 0u; tri < num_tris_1normal; tri++) {
1902  auto n = triangulatedIndexes[ti_index++];
1903  for(auto vert = 0u; vert < 3u; vert++) {
1904  _normals.push_back( n );
1905  _vertices.push_back( triangulatedIndexes[ti_index++] );
1906  }
1907  }
1908  }
1909 
1910  if(d.m_uiSizesTriangulatedSize > sz_tri_idx && kA3DTessFaceDataTriangleFanOneNormal & d.m_usUsedEntitiesFlags) {
1911  auto const num_fans_1normal = d.m_puiSizesTriangulated[sz_tri_idx++];
1912  for(auto fan_idx = 0u; fan_idx < num_fans_1normal; ++fan_idx) {
1913  auto const has_vertex_normals = 0 == (d.m_puiSizesTriangulated[sz_tri_idx] & kA3DTessFaceDataNormalSingle);
1914  auto const num_pts = d.m_puiSizesTriangulated[sz_tri_idx++] & kA3DTessFaceDataNormalMask;
1915  auto const root_n = triangulatedIndexes[ti_index++];
1916  auto const root_v = triangulatedIndexes[ti_index++];
1917  for(auto vert = 1u; vert < num_pts - 1u; vert++) {
1918  auto const n = (has_vertex_normals ? triangulatedIndexes[ti_index++] : root_n);
1919  auto const v = triangulatedIndexes[ti_index++];
1920 
1921  auto const next_n = (has_vertex_normals ? triangulatedIndexes[ti_index] : root_n);
1922  auto const next_v = triangulatedIndexes[ti_index + (has_vertex_normals ? 1 : 0)];
1923 
1924  _normals.push_back( root_n );
1925  _vertices.push_back( root_v );
1926  _normals.push_back( n );
1927  _vertices.push_back( v );
1928  _normals.push_back( next_n );
1929  _vertices.push_back( next_v );
1930  }
1931  ti_index += (has_vertex_normals ? 2 : 1);
1932  }
1933  }
1934  if(d.m_uiSizesTriangulatedSize > sz_tri_idx && kA3DTessFaceDataTriangleStripeOneNormal & d.m_usUsedEntitiesFlags) {
1935  auto const num_tri_stips = d.m_puiSizesTriangulated[sz_tri_idx++];
1936  for(auto strip_idx = 0u; strip_idx < num_tri_stips; ++strip_idx) {
1937  auto const has_vertex_normals = 0 == (d.m_puiSizesTriangulated[sz_tri_idx] & kA3DTessFaceDataNormalSingle);
1938  auto const series_normal = triangulatedIndexes[ti_index];
1939  auto const num_pts = d.m_puiSizesTriangulated[sz_tri_idx++] & kA3DTessFaceDataNormalMask;
1940  ti_index += 2;
1941  for(auto vert = 1u; vert < num_pts - 1u; vert++) {
1942  auto const prev_n = (has_vertex_normals ? triangulatedIndexes[ti_index - 2] : series_normal);
1943  auto const prev_v = triangulatedIndexes[ti_index - 1];
1944 
1945  auto const current_n = (has_vertex_normals ? triangulatedIndexes[ti_index++] : series_normal);
1946  auto const current_v = triangulatedIndexes[ti_index++];
1947 
1948  auto const next_n = (has_vertex_normals ? triangulatedIndexes[ti_index] : series_normal);
1949  auto const next_v = triangulatedIndexes[ti_index + (has_vertex_normals ? 1 : 0)];
1950 
1951  _normals.push_back( current_n );
1952  _vertices.push_back( current_v );
1953  _normals.push_back( vert % 2 ? next_n : prev_n );
1954  _vertices.push_back( vert % 2 ? next_v : prev_v );
1955  _normals.push_back( vert % 2 ? prev_n : next_n );
1956  _vertices.push_back( vert % 2 ? prev_v : next_v );
1957  }
1958  ti_index += (has_vertex_normals ? 2 : 1);
1959  }
1960  }
1961  if(d.m_uiSizesTriangulatedSize > sz_tri_idx && kA3DTessFaceDataTriangleTextured & d.m_usUsedEntitiesFlags) {
1962  auto const num_tris = d.m_puiSizesTriangulated[sz_tri_idx++];
1963  for(auto tri_idx = 0u; tri_idx < num_tris; tri_idx++) {
1964  for(auto vert_idx = 0u; vert_idx < 3u; vert_idx++) {
1965  _normals.push_back( triangulatedIndexes[ti_index++] );
1966  for( auto i = 0u; i < d.m_uiTextureCoordIndexesSize; ++i ) {
1967  _texture.push_back( triangulatedIndexes[ti_index++] );
1968  }
1969  _vertices.push_back( triangulatedIndexes[ti_index++] );
1970  }
1971  }
1972  }
1973  if(d.m_uiSizesTriangulatedSize > sz_tri_idx && kA3DTessFaceDataTriangleFanTextured & d.m_usUsedEntitiesFlags) {
1974  auto const num_fans_textured = d.m_puiSizesTriangulated[sz_tri_idx++];
1975  for(auto fan_idx = 0u; fan_idx < num_fans_textured; ++fan_idx) {
1976  auto const num_pts = d.m_puiSizesTriangulated[sz_tri_idx++];
1977  auto const n = triangulatedIndexes[ti_index++];
1978  std::vector<A3DUns32> t;
1979  for( auto i = 0u; i < d.m_uiTextureCoordIndexesSize; ++i ) {
1980  t.push_back( triangulatedIndexes[ti_index++] );
1981  }
1982  auto const v = triangulatedIndexes[ti_index++];
1983  for(auto vert = 1u; vert < num_pts - 1u; vert++) {
1984  _normals.push_back( n );
1985  _texture.insert( _texture.end(), t.begin(), t.end() );
1986  _vertices.push_back( v );
1987 
1988  _normals.push_back( triangulatedIndexes[ti_index++] );
1989  for( auto i = 0u; i < d.m_uiTextureCoordIndexesSize; ++i ) {
1990  _texture.push_back( triangulatedIndexes[ti_index++] );
1991  }
1992  _vertices.push_back( triangulatedIndexes[ti_index++] );
1993 
1994  _normals.push_back( triangulatedIndexes[ti_index++] );
1995  for( auto i = 0u; i < d.m_uiTextureCoordIndexesSize; ++i ) {
1996  _texture.push_back( triangulatedIndexes[ti_index++] );
1997  }
1998  _vertices.push_back( triangulatedIndexes[ti_index++] );
1999  }
2000  }
2001  }
2002  if(d.m_uiSizesTriangulatedSize > sz_tri_idx && kA3DTessFaceDataTriangleStripeTextured & d.m_usUsedEntitiesFlags) {
2003  auto const num_tri_stips = d.m_puiSizesTriangulated[sz_tri_idx++];
2004  for(auto strip_idx = 0u; strip_idx < num_tri_stips; ++strip_idx) {
2005  auto const num_pts = d.m_puiSizesTriangulated[sz_tri_idx++];
2006  for(auto vert = 1u; vert < num_pts - 1u; vert++) {
2007  auto const prev_n = triangulatedIndexes[ti_index - (2 + d.m_uiTextureCoordIndexesSize)];
2008  std::vector<A3DUns32> prev_t;
2009  for( auto i = ti_index - (1 + d.m_uiTextureCoordIndexesSize); i < ti_index - 1; ++i ) {
2010  prev_t.push_back( triangulatedIndexes[i] );
2011  }
2012  auto const prev_v = triangulatedIndexes[ti_index - 1];
2013 
2014  auto const current_n = triangulatedIndexes[ti_index++];
2015  std::vector<A3DUns32> current_t;
2016  for( auto i = 0u; i < d.m_uiTextureCoordIndexesSize; ++i ) {
2017  current_t.push_back( triangulatedIndexes[ti_index++] );
2018  }
2019  auto const current_v = triangulatedIndexes[ti_index++];
2020 
2021  auto const next_n = triangulatedIndexes[ti_index];
2022  std::vector<A3DUns32> next_t;
2023  for( auto i = 0u; i < d.m_uiTextureCoordIndexesSize; ++i ) {
2024  next_t.push_back( triangulatedIndexes[ ti_index + i + 1] );
2025  }
2026  auto const next_v = triangulatedIndexes[ti_index + 1 + d.m_uiTextureCoordIndexesSize];
2027 
2028  _normals.push_back( current_n );
2029  _texture.insert( _texture.end(), current_t.begin(), current_t.end() );
2030  _vertices.push_back( current_v );
2031 
2032  _normals.push_back( vert % 2 ? next_n : prev_n );
2033  _texture.insert( _texture.end(), vert % 2 ? next_t.begin() : prev_t.begin(), vert % 2 ? next_t.end() : prev_t.end() );
2034  _vertices.push_back( vert % 2 ? next_v : prev_v );
2035 
2036  _normals.push_back( vert % 2 ? prev_n : next_n );
2037  _texture.insert( _texture.end(), vert % 2 ? prev_t.begin() : next_t.begin(), vert % 2 ? prev_t.end() : next_t.end() );
2038  _vertices.push_back( vert % 2 ? prev_v : next_v );
2039  }
2040  }
2041  }
2042  if(d.m_uiSizesTriangulatedSize > sz_tri_idx && kA3DTessFaceDataTriangleOneNormalTextured & d.m_usUsedEntitiesFlags) {
2043  auto const has_vertex_normals = 0 == (d.m_puiSizesTriangulated[sz_tri_idx] & kA3DTessFaceDataNormalSingle);
2044  auto const series_normal = triangulatedIndexes[ti_index];
2045  auto const num_tris_1normal_textured = d.m_puiSizesTriangulated[sz_tri_idx++];
2046  for(auto tri = 0u; tri < num_tris_1normal_textured; tri++) {
2047  for(auto vert = 0u; vert < 3u; vert++) {
2048  _normals.push_back( has_vertex_normals ? triangulatedIndexes[ti_index++] : series_normal );
2049  for( auto i = 0u; i < d.m_uiTextureCoordIndexesSize; ++i ) {
2050  _texture.push_back( triangulatedIndexes[ti_index++] );
2051  }
2052  _vertices.push_back( triangulatedIndexes[ti_index++] );
2053  }
2054  }
2055  }
2056  if(d.m_uiSizesTriangulatedSize > sz_tri_idx && kA3DTessFaceDataTriangleFanOneNormalTextured & d.m_usUsedEntitiesFlags) {
2057  auto const num_fans_textured = d.m_puiSizesTriangulated[sz_tri_idx++];
2058  for(auto fan_idx = 0u; fan_idx < num_fans_textured; ++fan_idx) {
2059  auto const root_n = triangulatedIndexes[ti_index++];
2060  std::vector<A3DUns32> root_t;
2061  for( auto i = 0u; i < d.m_uiTextureCoordIndexesSize; ++i ) {
2062  root_t.push_back( triangulatedIndexes[ti_index++] );
2063  }
2064  auto const root_v = triangulatedIndexes[ti_index++];
2065  auto const has_vertex_normals = 0 == (d.m_puiSizesTriangulated[sz_tri_idx] & kA3DTessFaceDataNormalSingle);
2066  auto const num_pts = d.m_puiSizesTriangulated[sz_tri_idx++] & kA3DTessFaceDataNormalMask;
2067  for(auto vert = 1u; vert < num_pts - 1u; vert++) {
2068  _normals.push_back( root_n );
2069  _texture.insert( _texture.end(), root_t.begin(), root_t.end() );
2070  _vertices.push_back( root_v );
2071 
2072  _normals.push_back( has_vertex_normals ? triangulatedIndexes[ti_index++] : root_n );
2073  for( auto i = 0u; i < d.m_uiTextureCoordIndexesSize; ++i ) {
2074  _texture.push_back( triangulatedIndexes[ti_index++] );
2075  }
2076  _vertices.push_back( triangulatedIndexes[ti_index++] );
2077 
2078  _normals.push_back( has_vertex_normals ? triangulatedIndexes[ti_index] : root_n );
2079  for( auto i = 0u; i < d.m_uiTextureCoordIndexesSize; ++i ) {
2080  _texture.push_back( triangulatedIndexes[ti_index + i + 1] );
2081  }
2082  _vertices.push_back( triangulatedIndexes[ti_index + 1 + (has_vertex_normals ? d.m_uiTextureCoordIndexesSize : 0)] );
2083  }
2084  }
2085  }
2086  if(d.m_uiSizesTriangulatedSize > sz_tri_idx && kA3DTessFaceDataTriangleStripeOneNormalTextured & d.m_usUsedEntitiesFlags) {
2087  auto const num_tri_stips = d.m_puiSizesTriangulated[sz_tri_idx++];
2088  for(auto strip_idx = 0u; strip_idx < num_tri_stips; ++strip_idx) {
2089  auto const has_vertex_normals = 0 == (d.m_puiSizesTriangulated[sz_tri_idx] & kA3DTessFaceDataNormalSingle);
2090  auto const num_pts = d.m_puiSizesTriangulated[sz_tri_idx++] & kA3DTessFaceDataNormalMask;
2091  auto const series_normal = triangulatedIndexes[ti_index];
2092  ti_index += 2 + d.m_uiStyleIndexesSize;
2093  for(auto vert = 1u; vert < num_pts - 1u; vert++) {
2094  auto const prev_n = has_vertex_normals ? triangulatedIndexes[ti_index - (2 + d.m_uiTextureCoordIndexesSize)] : series_normal;
2095  auto const prev_v = triangulatedIndexes[ti_index - 1];
2096 
2097 
2098  auto const current_n = has_vertex_normals ? triangulatedIndexes[ti_index++] : series_normal;
2099  ti_index += d.m_uiTextureCoordIndexesSize;
2100  auto const current_v = triangulatedIndexes[ti_index++];
2101 
2102  auto const next_n = has_vertex_normals ? triangulatedIndexes[ti_index] : series_normal;
2103  auto const next_v = triangulatedIndexes[ti_index + 1 + (has_vertex_normals ? d.m_uiTextureCoordIndexesSize : 0)];
2104 
2105  _normals.push_back( current_n );
2106  _vertices.push_back( current_v );
2107  _normals.push_back( vert % 2 ? next_n : prev_n );
2108  _vertices.push_back( vert % 2 ? next_v : prev_v );
2109  _normals.push_back( vert % 2 ? prev_n : next_n );
2110  _vertices.push_back( vert % 2 ? prev_v : next_v );
2111  }
2112  }
2113  }
2114 
2115  auto wi_index = d.m_uiStartWire;
2116  TessLoop current_loop;
2117  for( auto idx = 0u; idx < d.m_uiSizesWiresSize; ++idx ) {
2118  auto const nverts_with_flags = d.m_puiSizesWires[idx];
2119  auto const nvertices = nverts_with_flags & ~kA3DTessFaceDataWireIsClosing & ~kA3DTessFaceDataWireIsNotDrawn;
2120  auto const is_closing = nverts_with_flags & kA3DTessFaceDataWireIsClosing;
2121  auto const is_hidden = nverts_with_flags & kA3DTessFaceDataWireIsNotDrawn;
2122  TessEdge current_edge;
2123  current_edge._visible = !is_hidden;
2124  for(auto vidx = 0u; vidx < nvertices; ++vidx ) {
2125  current_edge._vertices.push_back( wireIndexes[wi_index++] );
2126  }
2127  current_loop._edges.push_back( current_edge );
2128 
2129  if(is_closing) {
2130  _loops.push_back( current_loop );
2131  current_loop._edges.clear();
2132  }
2133  }
2134  }
2136  TessFaceDataHelper( TessFaceDataHelper const &other )
2137  : _vertices( other._vertices ), _normals( other._normals ), _texture( other._texture ) {
2138  }
2139 
2142  : _vertices( std::move( other._vertices ) ), _normals( std::move( other._normals ) ), _texture( std::move( other._texture ) ) {
2143  }
2144 
2145 
2147  TessFaceDataHelper &operator=( TessFaceDataHelper const &other ) {
2148  _vertices = other._vertices;
2149  _normals = other._normals;
2150  _texture = other._texture;
2151  return *this;
2152  }
2154  TessFaceDataHelper &operator=( TessFaceDataHelper &&other ) {
2155  _vertices = std::move( other._vertices );
2156  _normals = std::move( other._normals );
2157  _texture = std::move( other._texture );
2158  return *this;
2159  }
2160 
2167  std::vector<A3DUns32> const &vertices( void ) const {
2168  return _vertices;
2169  }
2170 
2177  std::vector<A3DUns32> const &normals( void ) const {
2178  return _normals;
2179  }
2180 
2184  std::vector<A3DUns32> const &textures( void ) const {
2185  return _texture;
2186  }
2187 
2191  struct TessEdge {
2193  std::vector<A3DUns32> _vertices;
2195  bool _visible;
2196  };
2197 
2201  struct TessLoop {
2203  std::vector<TessEdge> _edges;
2204  };
2205 
2209  std::vector<TessLoop> const loops( void ) const {
2210  return _loops;
2211  }
2212 
2213  private:
2214  std::vector<A3DUns32> _vertices, _normals, _texture;
2215  std::vector<TessLoop> _loops;
2216  };
2217 
2223  public:
2227  : TessBaseInstance( path ) {
2228  if( kA3DTypeTess3D != leafType() ) {
2229  throw std::invalid_argument("Expected A3DTess3D leaf not type." );
2230  }
2231  _d.reset( leaf() );
2232  }
2233 
2237  double const *normals( void ) const {
2238  return _d->m_pdNormals;
2239  }
2240 
2243  A3DUns32 normalsSize( void ) const {
2244  return _d->m_uiNormalSize;
2245  }
2246 
2250  double const *texCoords( void ) const {
2251  return _d->m_pdTextureCoords;
2252  }
2253 
2256  A3DUns32 texCoordsSize( void ) const {
2257  return _d->m_uiTextureCoordSize;
2258  }
2259 
2263  A3DUns32 faceSize( void ) const {
2264  return _d->m_uiFaceTessSize;
2265  }
2266 
2272  TessFaceDataHelper getIndexMeshForFace( A3DUns32 const &face_idx ) const {
2273  if( face_idx >= _d->m_uiFaceTessSize ) {
2274  throw std::out_of_range( "Index of face requested for index mesh is out of range." );
2275  }
2276  return TessFaceDataHelper( _d->m_psFaceTessData[face_idx], _d->m_puiTriangulatedIndexes, _d->m_puiWireIndexes );
2277  }
2278 
2279  private:
2280  A3DTess3DWrapper _d;
2281  };
2282 
2288  public:
2291  Tess3DWireInstance( InstancePath const &path );
2292 
2295  A3DUns32 getNumberOfWires( void ) const;
2296 
2299  struct WireData {
2301  std::vector<A3DUns32> _vertices;
2303  bool _closed;
2306  };
2307 
2310  enum class ColorSpec {
2312  RGB,
2314  RGBA
2315  };
2316 
2318  ColorSpec getColorSpecification( void ) const;
2319 
2321  enum class ColorApplication {
2323  PerVertex,
2325  PerSegment
2326  };
2327 
2328  private:
2331  };
2332 }
2333 
2334 namespace ts3d {
2340  public:
2344  : Instance( path ) {
2345  if( !isRepresentationItem( leafType() ) ) {
2346  throw std::invalid_argument( "The leaf node in the instance path must be a representation item." );
2347  }
2348  }
2349 
2354  std::shared_ptr<TessBaseInstance> getTessellation( void ) const {
2355  A3DRiRepresentationItemWrapper d( leaf() );
2356  auto tess_type = kA3DTypeUnknown;
2357  A3DEntityGetType( d->m_pTessBase, &tess_type );
2358  auto tess_path = path();
2359  tess_path.push_back( d->m_pTessBase );
2360  switch( tess_type ) {
2361  case kA3DTypeTess3D:
2362  return std::make_shared<Tess3DInstance>( tess_path );
2363  break;
2364  case kA3DTypeTess3DWire:
2365  break;
2366  default:
2367  break;
2368  }
2369  return nullptr;
2370  }
2371 
2376  bool getNetRemoved( A3DUns32 const face_idx ) const {
2377  return A3D_TRUE == getCascadedAttributesData( face_idx )->m_bRemoved;
2378  }
2379 
2380 
2383  bool getNetShow( A3DUns32 const face_idx ) const {
2384  return A3D_TRUE == getCascadedAttributesData( face_idx )->m_bShow;
2385  }
2386 
2389  A3DGraphStyleData getNetStyle( A3DUns32 const face_idx ) const {
2390  return getCascadedAttributesData( face_idx )->m_sStyle;
2391  }
2392 
2395  A3DUns16 getNetLayer( A3DUns32 const face_idx ) const {
2396  return getCascadedAttributesData( face_idx )->m_usLayer;
2397  }
2400  protected:
2401  A3DMiscCascadedAttributesWrapper getCascadedAttributesData( A3DUns32 const face_idx ) const {
2402  if( _cascaded_attribs.empty() ) {
2403  getCascadedAttributes();
2404  }
2405 
2406  auto cascaded_attribs_copy = _cascaded_attribs;
2407  auto father = cascaded_attribs_copy.back();
2408  cascaded_attribs_copy.push_back( nullptr );
2409  CheckResult( A3DMiscCascadedAttributesCreate( &cascaded_attribs_copy.back() ) );
2410 
2411  A3DRiRepresentationItemWrapper d( leaf() );
2412  A3DTess3DWrapper tess_d( d->m_pTessBase );
2413  CheckResult( A3DMiscCascadedAttributesPushTessFace( cascaded_attribs_copy.back(), leaf(), d->m_pTessBase, &tess_d->m_psFaceTessData[face_idx], face_idx, father ) );
2414  auto result = A3DMiscCascadedAttributesWrapper( cascaded_attribs_copy.back() );
2415  CheckResult( A3DMiscCascadedAttributesDelete( cascaded_attribs_copy.back() ) );
2416  return result;
2417  }
2418  };
2419 
2420  inline A3DVector3dData zeroVector( void ) {
2421  A3DVector3dData result;
2422  A3D_INITIALIZE_DATA( A3DVector3dData, result );
2423  result.m_dX = result.m_dY = result.m_dZ = 0.;
2424  return result;
2425 
2426  }
2427 
2428  inline A3DVector3dData operator+(A3DVector3dData const &lhs, A3DVector3dData const &rhs ) {
2429  A3DVector3dData result;
2430  A3D_INITIALIZE_DATA( A3DVector3dData, result );
2431  result.m_dX = lhs.m_dX + rhs.m_dX;
2432  result.m_dY = lhs.m_dY + rhs.m_dY;
2433  result.m_dZ = lhs.m_dZ + rhs.m_dZ;
2434  return result;
2435  }
2436 
2437  inline A3DVector3dData &operator+=(A3DVector3dData &lhs, A3DVector3dData const &rhs ) {
2438  lhs = lhs + rhs;
2439  return lhs;
2440  }
2441 
2442  inline A3DVector3dData operator-(A3DVector3dData const &lhs, A3DVector3dData const &rhs ) {
2443  A3DVector3dData result;
2444  A3D_INITIALIZE_DATA( A3DVector3dData, result );
2445  result.m_dX = lhs.m_dX - rhs.m_dX;
2446  result.m_dY = lhs.m_dY - rhs.m_dY;
2447  result.m_dZ = lhs.m_dZ - rhs.m_dZ;
2448  return result;
2449  }
2450 
2451  inline A3DVector3dData operator-( A3DVector3dData const &lhs ) {
2452  A3DVector3dData result;
2453  A3D_INITIALIZE_DATA( A3DVector3dData, result );
2454  result.m_dX = -lhs.m_dX;
2455  result.m_dY = -lhs.m_dY;
2456  result.m_dZ = -lhs.m_dZ;
2457  return result;
2458  }
2459 
2460  inline A3DVector3dData &operator-=(A3DVector3dData &lhs, A3DVector3dData const &rhs ) {
2461  lhs = lhs - rhs;
2462  return lhs;
2463  }
2464 
2465  inline A3DVector3dData operator*(A3DVector3dData const &lhs, double const &rhs ) {
2466  A3DVector3dData result;
2467  A3D_INITIALIZE_DATA( A3DVector3dData, result );
2468  result.m_dX = lhs.m_dX * rhs;
2469  result.m_dY = lhs.m_dY * rhs;
2470  result.m_dZ = lhs.m_dZ * rhs;
2471  return result;
2472  }
2473 
2474  inline A3DVector3dData operator*(double const &lhs, A3DVector3dData const &rhs ) {
2475  return rhs * lhs;
2476  }
2477 
2478  inline A3DVector3dData &operator*=(A3DVector3dData &lhs, double const &rhs ) {
2479  lhs.m_dX *= rhs;
2480  lhs.m_dY *= rhs;
2481  lhs.m_dZ *= rhs;
2482  return lhs;
2483  }
2484 
2485  inline A3DVector3dData operator/(A3DVector3dData const &lhs, double const &rhs ) {
2486  A3DVector3dData result;
2487  A3D_INITIALIZE_DATA( A3DVector3dData, result );
2488  result.m_dX = lhs.m_dX / rhs;
2489  result.m_dY = lhs.m_dY / rhs;
2490  result.m_dZ = lhs.m_dZ / rhs;
2491  return result;
2492  }
2493 
2494  inline A3DVector3dData &operator/=(A3DVector3dData &lhs, double const &rhs ) {
2495  lhs.m_dX /= rhs;
2496  lhs.m_dY /= rhs;
2497  lhs.m_dZ /= rhs;
2498  return lhs;
2499  }
2500 
2501  inline A3DVector3dData cross( A3DVector3dData const &lhs, A3DVector3dData const &rhs ) {
2502  A3DVector3dData result;
2503  A3D_INITIALIZE_DATA( A3DVector3dData, result );
2504  result.m_dX = lhs.m_dY * rhs.m_dZ - lhs.m_dZ * rhs.m_dY;
2505  result.m_dY = lhs.m_dZ * rhs.m_dX - lhs.m_dX * rhs.m_dZ;
2506  result.m_dZ = lhs.m_dX * rhs.m_dY - lhs.m_dY * rhs.m_dX;
2507  return result;
2508  }
2509 
2510  inline double dot( A3DVector3dData const &lhs, A3DVector3dData const &rhs ) {
2511  return lhs.m_dX * rhs.m_dX + lhs.m_dY * rhs.m_dY + lhs.m_dZ * rhs.m_dZ;
2512  }
2513 
2514  inline double length2( A3DVector3dData const &v ) {
2515  return dot( v, v );
2516  }
2517 
2518  inline double length( A3DVector3dData const &v ) {
2519  return sqrt( length2( v ) );
2520  }
2521 
2522  inline A3DVector3dData& normalize( A3DVector3dData &v ) {
2523  v /= length( v );
2524  return v;
2525  }
2526 
2527  inline A3DVector3dData normalized( A3DVector3dData const &v ) {
2528  auto result = v;
2529  return normalize( result );
2530  }
2531 
2532  inline bool operator==(A3DVector3dData const &lhs, A3DVector3dData const &rhs ) {
2533  static auto const RESOLUTION = 1.e-9;
2534  return length( lhs - rhs ) < RESOLUTION;
2535  }
2536 
2537  inline bool operator!=(A3DVector3dData const &lhs, A3DVector3dData const &rhs ) {
2538  static auto const RESOLUTION = 1.e-9;
2539  return length( lhs - rhs ) > RESOLUTION;
2540  }
2541 
2542  inline A3DBoundingBoxData &include( A3DBoundingBoxData &bb, A3DVector3dData const &pt ) {
2543  bb.m_sMin.m_dX = std::min( bb.m_sMin.m_dX, pt.m_dX );
2544  bb.m_sMin.m_dY = std::min( bb.m_sMin.m_dY, pt.m_dY );
2545  bb.m_sMin.m_dZ = std::min( bb.m_sMin.m_dZ, pt.m_dZ );
2546 
2547  bb.m_sMax.m_dX = std::max( bb.m_sMax.m_dX, pt.m_dX );
2548  bb.m_sMax.m_dY = std::max( bb.m_sMax.m_dY, pt.m_dY );
2549  bb.m_sMax.m_dZ = std::max( bb.m_sMax.m_dZ, pt.m_dZ );
2550 
2551  return bb;
2552  }
2553 
2554  inline A3DVector3dData center( A3DBoundingBoxData const &bb ) {
2555  return bb.m_sMin + (bb.m_sMax - bb.m_sMin) * 0.5;
2556  }
2557 }
2558 
2559 #ifdef _MSC_VER
2560 #pragma warning(pop)
2561 #endif
2562 
Provides a wrapper for accessing A3DTopoShellData.
Definition: ExchangeToolkit.h:770
Provides a wrapper for accessing A3DAsmPartDefinitionData.
Definition: ExchangeToolkit.h:619
Provides a wrapper for accessing A3DMkpMarkupData.
Definition: ExchangeToolkit.h:725
static bool isMarkup(A3DEEntityType const &t)
Check if type is A3DMkpMarkup or derived type.
Definition: ExchangeToolkit.h:866
std::unordered_map< A3DEntity *, InstancePathArray > InstancePathMap
Used for looking up instance path for a given unique child.
Definition: ExchangeToolkit.h:998
Provides a wrapper for accessing A3DTessBaseData.
Definition: ExchangeToolkit.h:759
double const * normals(void) const
Obtains a pointer to an array of normal coordinates. The length of this array is determined by normal...
Definition: ExchangeToolkit.h:2237
bool operator==(Instance const &other) const
Compare paths.
Definition: ExchangeToolkit.h:1675
static double getUnit(A3DAsmModelFile *modelFile)
Obtains the unit scaling factor (units/mm) for a given input model file.
Definition: ExchangeToolkit.h:938
bool _closed
Indicated if the wire is closing.
Definition: ExchangeToolkit.h:2303
Provides a wrapper for accessing A3DRiCurveData.
Definition: ExchangeToolkit.h:730
A3DUns32 texCoordsSize(void) const
Provides the length of the texCoords array.
Definition: ExchangeToolkit.h:2256
std::vector< A3DUns32 > const & vertices(void) const
Gets the list of vertex index values defining the triangles of the mesh for this face. The length of this vector should be a multiple of 3. Index values should be accessed as triplets, each value defining the offset in the TessBaseInstance::coords() array.
Definition: ExchangeToolkit.h:2167
Provides a wrapper for accessing A3DRiBrepModelData.
Definition: ExchangeToolkit.h:728
std::string getName(void) const
Gets the object name.
Definition: ExchangeToolkit.h:1681
std::vector< A3DUns32 > _vertices
Array indexes for the vertices.
Definition: ExchangeToolkit.h:2193
Provides easy access to wire tessellation data.
Definition: ExchangeToolkit.h:2287
Provides a wrapper for accessing A3DTopoBrepDataData.
Definition: ExchangeToolkit.h:762
Provides a wrapper for accessing A3DMkpAnnotationSetData.
Definition: ExchangeToolkit.h:723
TessFaceDataHelper getIndexMeshForFace(A3DUns32 const &face_idx) const
Gets an object that wraps the tessellation data of a given face.
Definition: ExchangeToolkit.h:2272
A3DGraphStyleData getNetStyle(void) const
Gets the net style.
Definition: ExchangeToolkit.h:1756
A3DGraphStyleData getNetStyle(A3DUns32 const face_idx) const
Gets the net style.
Definition: ExchangeToolkit.h:2389
bool _connected_to_previous
Indicates if the wire is connected to the previous wire.
Definition: ExchangeToolkit.h:2305
Provides a wrapper for accessing A3DMkpAnnotationReferenceData.
Definition: ExchangeToolkit.h:722
Encapsulates the functionality desired to easily retrieve normal and texture coordinates for a tessel...
Definition: ExchangeToolkit.h:2222
Base class for easing access to tessellation data. Provides access to coordinate values.
Definition: ExchangeToolkit.h:1808
static A3DAsmPartDefinition * getPartDefinition(A3DAsmProductOccurrence *po, PrototypeOption const &opt=PrototypeOption::Use)
Gets a part definition from a product occurrence, optionally using recursion to query the prototype...
Definition: ExchangeToolkit.h:914
A collection of TessEdge objects representing a single closed series of edges that bound a face...
Definition: ExchangeToolkit.h:2201
static bool isTessBase(A3DEEntityType const &t)
Check if type is TessBase or derived TessBase type.
Definition: ExchangeToolkit.h:847
std::string getType(void) const
Gets the object type as a string.
Definition: ExchangeToolkit.h:1687
std::shared_ptr< Instance > InstancePtr
Abstraction of a shared pointer to an Instance object.
Definition: ExchangeToolkit.h:1620
bool getNetShow(void) const
Gets the net show.
Definition: ExchangeToolkit.h:1750
Provides a wrapper for accessing A3DRootBaseData.
Definition: ExchangeToolkit.h:738
bool getNetRemoved(void) const
Gets the net removed.
Definition: ExchangeToolkit.h:1743
STL namespace.
Provides a wrapper for accessing A3DTopoSingleWireBodyData.
Definition: ExchangeToolkit.h:771
std::vector< TessEdge > _edges
Collection of edges that make up this loop.
Definition: ExchangeToolkit.h:2203
TessBaseInstance(InstancePath const &path)
throws if leaf type is not "derived" from A3DTessBase
Definition: ExchangeToolkit.h:1812
Provides a wrapper for accessing A3DAsmModelFileData.
Definition: ExchangeToolkit.h:618
Provides a wrapper for accessing A3DTopoConnexData.
Definition: ExchangeToolkit.h:764
A3DEEntityType leafType(void) const
Gets the type of the leaf entity.
Definition: ExchangeToolkit.h:1733
std::vector< A3DUns32 > const & normals(void) const
Gets the list of vertex index values defining the normal vectors at each vertex location. The length of this vector should be a multiple of 3. Index values should be accessed as triplets, each value defining the offset in the Tess3DInstance::normals() array.
Definition: ExchangeToolkit.h:2177
This class is used to log calls to the Exchange API.
Definition: ExchangeToolkit.h:477
static InstancePathArray getLeafInstances(A3DEntity *owner, A3DEEntityType const &leaf_type)
Returns an array of instance paths, each with a leaf entity type corresponding to leaf_type...
Definition: ExchangeToolkit.h:1510
bool _record(std::string const file, int const line_no, std::string const fn, A3DStatus const result)
Used internally by the CheckResult macro to log a function call.
Definition: ExchangeToolkit.h:525
ColorSpec
How color is specified.
Definition: ExchangeToolkit.h:2310
Provides a wrapper for accessing A3DTopoEdgeData.
Definition: ExchangeToolkit.h:766
Provides a wrapper for accessing A3DMkpAnnotationItemData.
Definition: ExchangeToolkit.h:721
This specific type of an Instance expects the leaf node to be of type kA3DTypeRiRepresentationItem.
Definition: ExchangeToolkit.h:2339
int const & line(void) const
Gets the line number where the last call was invoked from.
Definition: ExchangeToolkit.h:505
std::shared_ptr< TessBaseInstance > getTessellation(void) const
Provides a concrete type for the tessellation instance Will be one of type:
Definition: ExchangeToolkit.h:2354
virtual ~Instance(void)
Destructor.
Definition: ExchangeToolkit.h:1655
EntityArray InstancePath
The InstancePath type is used to identify a particular path through the hierarchy of Exchange objects...
Definition: ExchangeToolkit.h:963
InstancePath const & path(void) const
Gets the InstancePath this Instance references.
Definition: ExchangeToolkit.h:1693
Instance(Instance &&other)
Move constructor.
Definition: ExchangeToolkit.h:1648
std::set< A3DEntity * > EntitySet
Used to absract an unordered collection of unique Exchange objects.
Definition: ExchangeToolkit.h:827
A3DStatus const & result(void) const
Gets the return code resulting from the last function call.
Definition: ExchangeToolkit.h:517
bool _visible
Visibility flag.
Definition: ExchangeToolkit.h:2195
static bool isRepresentationItem(A3DEEntityType const &t)
Check if type is Ri or derived Ri type.
Definition: ExchangeToolkit.h:832
Instance & operator=(Instance &&other)
Move assign.
Definition: ExchangeToolkit.h:1668
#define A3D_HELPERS(A3D_VOID_TYPE)
This macro is used to define a struct that can be used to more easily obtain and access the Exchange ...
Definition: ExchangeToolkit.h:570
A3DUns32 faceSize(void) const
Provides the total number of faces with available tessellation data.
Definition: ExchangeToolkit.h:2263
Instance owner(void) const
Gets an Instance object for the parent.
Definition: ExchangeToolkit.h:1699
bool getNetRemoved(A3DUns32 const face_idx) const
Gets the net removed.
Definition: ExchangeToolkit.h:2376
Provides a wrapper for accessing A3DTopoFaceData.
Definition: ExchangeToolkit.h:767
Structure describing wire data.
Definition: ExchangeToolkit.h:2299
std::vector< T > toVector(T *d, S const &sz)
This function can be used to more easily construct a vector of objects.
Definition: ExchangeToolkit.h:783
An instance should be thought of as a specific path through the Exchange product structure to a parti...
Definition: ExchangeToolkit.h:1630
A3DUns16 getNetLayer(A3DUns32 const face_idx) const
Gets the net layer.
Definition: ExchangeToolkit.h:2395
Instance(InstancePath const &path)
Constructs an Instance from the provided InstancePath.
Definition: ExchangeToolkit.h:1634
static CheckResult & instance(void)
Gets the global instances of the CheckResult object. The returned object can be used to examine infor...
Definition: ExchangeToolkit.h:484
A3DUns32 coordsSize(void) const
The length of the coords() array.
Definition: ExchangeToolkit.h:1830
The ts3d namespace is used to contain all Exchange Toolkit functionality.
Definition: ExchangeEigenBridge.h:6
Provides a wrapper for accessing A3DTopoLoopData.
Definition: ExchangeToolkit.h:768
std::vector< InstancePath > InstancePathArray
Used as a collection of InstancePath objects. When you ask for all leaf nodes of a particular leaf no...
Definition: ExchangeToolkit.h:971
static EntitySet getUniqueLeafEntities(A3DEntity *owner, A3DEEntityType const &leaf_type)
Returns a set of A3DEntity pointers that are unique leaf entities of type leaf_type of the provided o...
Definition: ExchangeToolkit.h:1539
std::vector< A3DUns32 > _vertices
The vertex index values.
Definition: ExchangeToolkit.h:2301
Provides a wrapper for accessing A3DRiRepresentationItemData.
Definition: ExchangeToolkit.h:736
std::vector< A3DEntity * > EntityArray
Used to abstract an ordered collection of Exchange objects.
Definition: ExchangeToolkit.h:822
static InstancePath getOwningInstance(InstancePath const &instance_path, A3DEEntityType const &owner_type)
Easily obtain a subset of an InstancePath with a final node of a specific type.
Definition: ExchangeToolkit.h:1558
static bool isAnnotationEntity(A3DEEntityType const &t)
Check if type is A3DMkpAnnotationEntity or derived type.
Definition: ExchangeToolkit.h:857
ColorApplication
How is the color applied?
Definition: ExchangeToolkit.h:2321
bool getNetShow(A3DUns32 const face_idx) const
Gets the net show.
Definition: ExchangeToolkit.h:2383
void reset(InstancePath const &new_path)
Resets the InstancePath this Instance references.
Definition: ExchangeToolkit.h:1711
static EntitySet getUniqueChildren(A3DEntity *owner, A3DEEntityType const &leaf_type)
Definition: ExchangeToolkit.h:1011
Provides a wrapper for accessing A3DTess3DWireData.
Definition: ExchangeToolkit.h:758
A3DUns16 getNetLayer(void) const
Gets the net layer.
Definition: ExchangeToolkit.h:1762
double const * coords(void) const
Gets the array of coordinate values for the tesselation. This array is of length coordsSize().
Definition: ExchangeToolkit.h:1824
Provides a wrapper for accessing A3DRiSetData.
Definition: ExchangeToolkit.h:737
Provides a wrapper for accessing A3DTopoCoEdgeData.
Definition: ExchangeToolkit.h:763
Provides a wrapper for accessing A3DMiscCascadedAttributesData.
Definition: ExchangeToolkit.h:714
std::vector< A3DUns32 > const & textures(void) const
Gets the list of texture coordinate values.
Definition: ExchangeToolkit.h:2184
std::vector< TessLoop > const loops(void) const
Provides a list of TessLoop objects representing the edge loops that bound this face.
Definition: ExchangeToolkit.h:2209
static EntityArray getChildren(A3DEntity *parent, A3DEEntityType const &child_type)
Gets all immediate children (if any) of a specified type from a parent object.
Definition: ExchangeToolkit.h:1566
A3DUns32 normalsSize(void) const
Provides the size of the normal array.
Definition: ExchangeToolkit.h:2243
std::string const & fn(void) const
Gets the stringified representation of the last function call.
Definition: ExchangeToolkit.h:511
Tess3DInstance(InstancePath const &path)
Throws if leaf type is not kA3DTypeTess3D.
Definition: ExchangeToolkit.h:2226
static A3DEEntityType getEntityType(A3DEntity *ntt)
A simple wrapper to allow use inline without having to declare a temporary variable to the return val...
Definition: ExchangeToolkit.h:890
RepresentationItemInstance(InstancePath const &path)
throws if leaf entity is not type kA3DTypeRiRepresentationItem
Definition: ExchangeToolkit.h:2343
double const * texCoords(void) const
Obtains a pointer to an array of texture coordinates. The length of this array is determined by texCo...
Definition: ExchangeToolkit.h:2250
Provides a wrapper for accessing A3DAsmProductOccurrenceData.
Definition: ExchangeToolkit.h:620
void setFailureCallback(std::function< bool(CheckResult const &)> failure_cb)
Sets the callback function that is invoked when an call is made and the result value is not A3D_SUCCE...
Definition: ExchangeToolkit.h:493
This is a helper class used to more easily provide access to the indexed mesh data for a given face...
Definition: ExchangeToolkit.h:1842
Provides a wrapper for accessing A3DRiPlaneData.
Definition: ExchangeToolkit.h:732
static EntityArray getProductOccurrences(A3DAsmProductOccurrence *po, PrototypeOption const &opt=PrototypeOption::Use)
Gets the child product occurrences from a parent, optionally using recursion to query the prototype...
Definition: ExchangeToolkit.h:925
Index list of vertices for the tessellation of a specific edge.
Definition: ExchangeToolkit.h:2191
Instance(Instance const &other)
Copy constructor.
Definition: ExchangeToolkit.h:1641
std::string const & file(void) const
Gets the filename where the last call was invoked from.
Definition: ExchangeToolkit.h:499
Instance & operator=(Instance const &other)
Assignment.
Definition: ExchangeToolkit.h:1661
Provides a wrapper for accessing A3DTess3DData.
Definition: ExchangeToolkit.h:757
A3DEntity * leaf(void) const
Gets the leaf entity pointer.
Definition: ExchangeToolkit.h:1727