diff --git a/C3d/Include/action_b_shaper.h b/C3d/Include/action_b_shaper.h index 8dd9538..3854fab 100644 --- a/C3d/Include/action_b_shaper.h +++ b/C3d/Include/action_b_shaper.h @@ -122,8 +122,8 @@ public: MbeCreateBRepMode bMode = cbm_Default ) : useRelativeTolerance( useRelTol ) , smoothBoundaryEdges ( smoothBoundary ) - , tolerance ( tol ) , bAngle ( angle ) + , tolerance ( tol ) , surfReconstructMode ( reconMode ) , brepCreationMode ( bMode ) {} @@ -491,4 +491,5 @@ MATH_FUNC( MbResultType ) ConvertCollectionToShell( MbCollection & collection, M */ // --- MATH_FUNC( MbResultType ) FitSurfaceToGrid( const MbGrid & grid, const MbSurfaceFitToGridParameters & params, MbSurfaceFitToGridResults & results ); + #endif // __ACTION_B_SHAPER_H diff --git a/C3d/Include/action_curve3d.h b/C3d/Include/action_curve3d.h index dba3c39..1fb288c 100644 --- a/C3d/Include/action_curve3d.h +++ b/C3d/Include/action_curve3d.h @@ -217,12 +217,12 @@ MATH_FUNC (MbResultType) NurbsCurve( const SArray & pointList, \ingroup Curve3D_Modeling */ // --- -MATH_FUNC (double) NurbsFitting( const std::vector & pointList, - bool curveClosed, - size_t degree, - size_t mode, - double & accuracy, - MbCurve3D *& result ); +DEPRECATE_DECLARE MATH_FUNC (double) NurbsFitting( const std::vector & pointList, + bool curveClosed, + size_t degree, + size_t mode, + double & accuracy, + MbCurve3D *& result ); //------------------------------------------------------------------------------ @@ -1577,8 +1577,8 @@ MATH_FUNC (MbResultType) CreateContourChamfer( const MbContourChamferParams & pa //------------------------------------------------------------------------------- /** \brief \ru Построить развертку кривых и точек на плоскость. \en Construct unwrapped curves and points. \~ - \details \ru Построение развертки кривых и точек на плоскость. См. также #CurvesUnwrapping.\n - \en Construct unwrapped curves and points on a plane. Also check out #CurvesUnwrapping.\n \~ + \details \ru Построение развертки кривых и точек на плоскость.\n + \en Construct unwrapped curves and points on a plane.\n \~ \param[in] params - \ru Параметры разворачивания. \en Unwrapping parameters. \~ \param[out] result - \ru Результат разворачивания. @@ -1595,8 +1595,8 @@ MATH_FUNC (MbResultType) UnwrapCurve( const MbCurvesWrappingParams & parameters //------------------------------------------------------------------------------- /** \brief \ru Выполнить операцию сворачивания кривых и точек на поверхность. \en Perform the operation of wrapping curves and points on a surface. \~ - \details \ru Выполнить операцию сворачивания кривых на поверхность. См. также #CurvesWrapping.\n - \en Perform the operation of wrapping curves on a surface. Also check out #CurvesWrapping.\n \~ + \details \ru Выполнить операцию сворачивания кривых на поверхность.\n + \en Perform the operation of wrapping curves on a surface.\n \~ \param[in] params - \ru Параметры сворачивания. \en Wrapping parameters. \~ \param[out] result - \ru Результат сворачивания. diff --git a/C3d/Include/action_polymesh.h b/C3d/Include/action_polymesh.h index 46d869d..9bdedb8 100644 --- a/C3d/Include/action_polymesh.h +++ b/C3d/Include/action_polymesh.h @@ -27,6 +27,10 @@ class MbDrapeShellResults; class MbRemeshParams; class MbShellLinearizationParams; class MbMergePolymeshParams; +class MbMeshSmoothingParams; +class MbPolyline3D; +class MbPolylinePolymeshProjectParams; +class MbPolylinePolymeshProjectResults; //------------------------------------------------------------------------------ @@ -315,11 +319,50 @@ MATH_FUNC( MbResultType ) DrapeShell( const MbDrapeShellParams & params, MbDrape \en Merging parameters. \~ \param[in-out] meshTo - \ru Полигональный объект, который аккумулирует результат объединения. \en A polygonal object, accumulating merged objects. \~ - \return \ru Код результата операции, rt_Success если объекты успешно объединены. + \return \ru Код результата операции, rt_Success, если объекты успешно объединены. \en Returns the operation result code, rt_Success if the objects are successfully merged. \n \warning \ru В разработке. \en Under development.\~ */ // --- MATH_FUNC( MbResultType ) MergePolymeshes( const MbPolymesh & meshFrom, const MbMergePolymeshParams & params, MbPolymesh & meshTo ); + +//------------------------------------------------------------------------------ +/** \brief \ru Сгладить полигональный объект по набору входных параметров сглаживания. + \en Smooth a polygonal object using a set of input smoothing parameters. \~ + \param[in] params - \ru Параметры сглаживания. + \en Smoothing parameters. \~ + \param[in-out] mesh - \ru Полигональный объект. + \en A polygonal object. \~ + \return \ru Код результата операции, rt_Success если объект успешно сглажен. + \en Returns the operation result code, rt_Success if the object is successfully smoothed. \n + \warning \ru В разработке. + \en Under development.\~ +*/ // --- +MATH_FUNC( MbResultType ) SmoothPolymesh( const MbMeshSmoothingParams & params, MbPolymesh & mesh ); + + + +//------------------------------------------------------------------------------ +/** \brief \ru Спроецировать полилинию на полигональный объект. + \en Project a polyline on a polygonal object. \~ + \details \ru Спроецировать полилинию на полигональный объект. + Если на некотором участке полилиния проецируется внутрь фасета, он разделяется на несколько фасетов. + При этом создаются новые рёбра полигонального объекта. + \en Project a polyline on a polygonal object. + In case of projecting a polyline's fragment inside a facet, it splits into new ones, so new edges are created. \~ + \param[in-out] mesh - \ru Полигональный объект. + \en A polygonal object being projected on. \~ + \param[in] params - \ru Параметры проецирования полилинии на полигональный объект. + \en Parameters for projecting a polyline on a polymesh. \~ + \param[out] results - \ru Результат проецирования полилинии на полигональный объект. + \en Result of projecting a polyline on a polymesh. \~ + \return \ru Код результата операции, rt_Success, если проекция успешно построена. + \en Returns the operation result code, rt_Success if a polyline is successfully projected. \n + \warning \ru В разработке. + \en Under development.\~ +*/ // --- +MATH_FUNC( MbResultType ) ProjectPolylineOnPolymesh( MbPolymesh & mesh, const MbPolylinePolymeshProjectParams & params, MbPolylinePolymeshProjectResults & results ); + + #endif // __ACTION_POLYMESH_H diff --git a/C3d/Include/action_wireframe.h b/C3d/Include/action_wireframe.h index f9e620c..3579cff 100644 --- a/C3d/Include/action_wireframe.h +++ b/C3d/Include/action_wireframe.h @@ -19,6 +19,7 @@ class MbNurbsWireFrameParams; class MbTrimmedWireFrameParams; class MbWireFrameProjParams; class MbWireFrameProjResult; +class MbOffsetWireFrameParams; //------------------------------------------------------------------------------ @@ -201,4 +202,28 @@ MATH_FUNC( MbResultType ) ExtendWireFrame( c3d::WireFrameSPtr & const MbCurveExtensionParameters3D & params, c3d::WireFrameSPtr & result ); + +//------------------------------------------------------------------------------ +/** \brief \ru Создать эквидистантный каркас. + \en Create an offset wire frame. \~ + \details \ru Создать эквидистантный каркас смещением базового каркаса. + \en Create an offset wire frame by shifting the base wire frame. \~ + \param[in] wireFrame - \ru Исходный каркас. + \en The initial wire frame. \~ + \param[in] sameWire - \ru Режим копирования входного каркаса. + \en Whether to copy the input wire frame. \~ + \param[in] params - \ru Параметры операции. + \en Operation parameters. \~ + \param[out] result - \ru Эквидистантный каркас. + \en The offset wire frame. \~ + \return \ru Возвращает код результата операции. + \en Returns operation result code. \~ + \ingroup WireFrame_Modeling +*/ +// --- +MATH_FUNC( MbResultType ) CreateOffsetWireFrame( c3d::WireFrameSPtr & wireFrame, + MbeCopyMode sameWire, + const MbOffsetWireFrameParams & params, + c3d::WireFrameSPtr & result ); + #endif // __ACTION_WIREFRAME_H diff --git a/C3d/Include/attr_hotpoint_attribute.h b/C3d/Include/attr_hotpoint_attribute.h index e7edb71..7723519 100644 --- a/C3d/Include/attr_hotpoint_attribute.h +++ b/C3d/Include/attr_hotpoint_attribute.h @@ -44,13 +44,14 @@ public: */ //--- enum class MbeHotPointType : uint16 { - undefinedHP = 0, ///< \ru Неопределенный тип. \en Undefined type. - draftHP, ///< \ru Хот-точка операции уклона. \en The draft operation hot point. - conicSectionHP, ///< \ru Хот-точка операции построения переменного конического сечения. \en The conic section operation hot point. - DMFilletRadiusSetHP, ///< \ru Хот-точка операции прямого моделирования по установке радиусов граням скругления. \en The direct modeling operation's hot point by set fillet face's radius. - elementaryHP, ///< \ru Хот-точка операции построения элементарного тела. \en The elementary solid operation hot point. - DMReplaceFacesHP, ///< \ru Хот-точка операции замены граней. \en Hot point of the face replacement operation. - DMOffsetFacesHP, ///< \ru Хот-точка операции замены граней на эквидистантные. \en Hot point of the operation of replacement faces with the offset ones. + undefinedHP = 0, ///< \ru Неопределенный тип. \en Undefined type. + draftHP, ///< \ru Хот-точка операции уклона. \en The draft operation hot point. + conicSectionHP, ///< \ru Хот-точка операции построения переменного конического сечения. \en The conic section operation hot point. + DMFilletRadiusSetHP, ///< \ru Хот-точка операции прямого моделирования по установке радиусов граням скругления. \en The direct modeling operation's hot point by set fillet face's radius. + elementaryHP, ///< \ru Хот-точка операции построения элементарного тела. \en The elementary solid operation hot point. + DMReplaceFacesHP, ///< \ru Хот-точка операции замены граней. \en Hot point of the face replacement operation. + DMOffsetFacesHP, ///< \ru Хот-точка операции замены граней на эквидистантные. \en Hot point of the operation of replacement faces with the offset ones. + DMReplaceFacesGroupHP, ///< \ru Хот-точка операции замены группы граней. \en Hot point of the operation of replacement faces group. // \ru Вставлять новые типы перед этим типом. \en Insert new types before this type. endHP = SYS_MAX_INT16 }; diff --git a/C3d/Include/attr_user_attribute.h b/C3d/Include/attr_user_attribute.h index 255ba4a..bba1457 100644 --- a/C3d/Include/attr_user_attribute.h +++ b/C3d/Include/attr_user_attribute.h @@ -40,6 +40,8 @@ class MATH_CLASS MbFixAttrSet; class IAttrDefinition { public: + virtual ~IAttrDefinition() = default; + /// \ru Преобразовать из пользовательского в "системный". \en Convert user attribute to "system" one. virtual MbUserAttribute * ReduceUserAttrib ( const MbExternalAttribute & source ) = 0; diff --git a/C3d/Include/attribute_item.h b/C3d/Include/attribute_item.h index 29a8110..5cd7419 100644 --- a/C3d/Include/attribute_item.h +++ b/C3d/Include/attribute_item.h @@ -600,7 +600,9 @@ namespace c3d // namespace C3D constexpr TCHAR c3dStr_SavedViewUpVector[] = _T( "c3d_SavedView_UpVector" ); /** \ru Подсказка для масштаба текущего вида. \en Hint for the scale of the current view. \~*/ constexpr TCHAR c3dStr_SavedViewScale[] = _T( "c3d_SavedView_Scale" ); - + /** \ru Подсказка для типа текущего вида (ортогональный/перспективный). Хранится в виде значения bool. + \en Hint for the type of the current view (orthogonal/perspective). Stored as a bool value. \~*/ + constexpr TCHAR c3dStr_SavedViewPerspective[] = _T( "c3d_SavedView_Perspective" ); } // namespace C3D diff --git a/C3d/Include/cdet_data.h b/C3d/Include/cdet_data.h index 25747ef..331afbd 100644 --- a/C3d/Include/cdet_data.h +++ b/C3d/Include/cdet_data.h @@ -90,7 +90,7 @@ struct MATH_CLASS cdet_query enum cback_res ///< Result code of the callback function { CBACK_VOID - , CBACK_SUFFICIENT ///< This code means that an app stops collision query for given pair of lumps. + , CBACK_SUFFICIENT ///< This code means that an app stops collision query for the given pair of geometric objects. , CBACK_SKIP ///< Skip testing the given pair. , CBACK_NEED ///< Enable testing the given pair. , CBACK_BREAK ///< Break search of all collisions of the set. @@ -112,9 +112,9 @@ struct MATH_CLASS cdet_query struct geom_element ///< Structure representing a collision detection geometry. { - cdet_app_item appItem; - const MbRefItem * refItem; - const MbMatrix3D * wMatrix; + cdet_app_item appItem; ///< Application pointer to a geometric object. + const MbRefItem * refItem; ///< Pointer to the collided face or grid. + const MbMatrix3D * wMatrix; ///< Matrix mapping the collided item to The world CS of the scene. geom_element() : appItem( nullptr ) , refItem( nullptr ) diff --git a/C3d/Include/check_geometry.h b/C3d/Include/check_geometry.h index 7b2d4cf..00e4e31 100644 --- a/C3d/Include/check_geometry.h +++ b/C3d/Include/check_geometry.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -1227,7 +1228,7 @@ public: /// \ru Режим проверки самопересечений. \en Mode of self intersection checking. enum class MbeCheckSelfIntMode { - Auto , /// \ru Автоматический режим. \en Auto mode. + Auto , /// \ru Автоматический режим (проверять пересечение граней, включая самопересечения). \en Auto mode (check intersection of faces including self-intersections). SelfIntFacesOnly , /// \ru Проверять только самопересечение граней. \en Check only self-intersection of faces. IntDfferentFacesOnly /// \ru Проверять только пересечение различных граней. \en Check only the intersection of different faces. }; @@ -1235,6 +1236,8 @@ public: private: MbeCheckSelfIntMode _mode; ///< \ru Режим проверки самопересечений. \en Mode of self intersection checking. VERSION _version; ///< \ru Версия алгоритма. \en Algorithm version. + std::unique_ptr _stepData; ///< \ru Данные для вычисления шага при триангуляции. \en Data for step calculation during triangulation. + public: mutable IProgressIndicator * _progress; ///< \ru Индикатор прогресса выполнения операции. \en A progress indicator of the operation. @@ -1243,7 +1246,7 @@ public: MbShellSelfIntParams(); /** \brief \ru Конструктор проверки на самопересечение оболочки. \en Constructor of checking for self-intersection of shell. \~ - \details \ru Конструктор проверки на самопересечение оболчки. + \details \ru Конструктор проверки на самопересечение оболочки. \en Constructor of checking for self-intersection of shell. \~ \param[in] version - \ru Версия алгоритма. \en Algorithm version. \~ @@ -1253,7 +1256,7 @@ public: MbShellSelfIntParams( VERSION version, IProgressIndicator * prog = nullptr ); /** \brief \ru Конструктор проверки на самопересечение оболочки. \en Constructor of checking for self-intersection of shell. \~ - \details \ru Конструктор проверки на самопересечение оболчки. + \details \ru Конструктор проверки на самопересечение оболочки. \en Constructor of checking for self-intersection of shell. \~ \param[in] mode - \ru Режим проверки самопересечений. \en Mode of self intersection checking. \~ @@ -1263,6 +1266,20 @@ public: \en A progress indicator of the operation. */ MbShellSelfIntParams( MbeCheckSelfIntMode mode, VERSION version, IProgressIndicator * prog = nullptr ); + /** \brief \ru Конструктор проверки на самопересечение оболочки с помощью анализа сеток. + \en Constructor of checking for self-intersection of shell by meshes check. \~ + \details \ru Конструктор проверки на самопересечение оболочки с помощью анализа сеток. + \en Constructor of checking for self-intersection of shell by meshes check. \~ + \param[in] stepData - \ru Данные для вычисления шага при триангуляции. + \en Data for step calculation during triangulation. \~ + \param[in] version - \ru Версия алгоритма. + \en Algorithm version. \~ + \param[in] prog - \ru Индикатор прогресса выполнения операции. + \en A progress indicator of the operation. + \warning \ru Пока не готово. \en Not yet ready. +*/ + MbShellSelfIntParams( const MbStepData & stepData, VERSION version = Math::DefaultMathVersion(), IProgressIndicator * prog = nullptr ); + /// \ru Деструктор. \en Destructor. ~MbShellSelfIntParams() {} public: @@ -1272,6 +1289,9 @@ public: void SetMode( MbeCheckSelfIntMode mode ) { _mode = mode; } /// \ru Получить версию алгоритма. \en Get the algorithm version. VERSION GetVersion() const { return _version; } + // \ru Получить данные для расчета шага. \en Get data for the step calculation. \~ + const MbStepData * GetStepData() const { return _stepData.get(); } + OBVIOUS_PRIVATE_COPY( MbShellSelfIntParams ) }; @@ -1292,7 +1312,7 @@ private: \en Result of intersection/self-intersection of faces. \~ \details \ru Результат пересечения/самопересечения граней. Если '_facesIndices' содержат одинаковые индексы, значит грань с данным индексом самопересекается. - Кривые пересечения не вычисляются для сомопересечения и '_curves' будет пустым. \n + Кривые пересечения не вычисляются для самопересечения и '_curves' будет пустым. \n \en The result of intersection/self-intersection of edges. If '_facesIndices' contains identical indices, which means the face with this index intersects itself. Intersection curves are not calculated for self-intersection and '_curves' will be empty. \n \~ @@ -1359,8 +1379,8 @@ public: If intersectionCurves = nullptr - intersection curves do not return. \~ \return \ru Возвращает: - false, если результата с заданым индексом не содержится; - true, если результата с заданым индексом найден; + false, если результата с заданным индексом не содержится; + true, если результата с заданным индексом найден; \en Returns: false, if there is no result with the given index; true, if a result with the given index is found; \~ @@ -1370,6 +1390,8 @@ public: size_t Count() const { return _selfIntResults.size(); } /// \ru Установить значения по умолчанию. \en Set defaults. void Reset() { _selfIntResults.clear(); }; + /// \ru Зарезервировать размер массива пар пересекающихся и самопересекающихся граней. \en Reserve the size the array of pairs of intersecting and self-intersecting faces. + void ReserveResult( size_t count ) { _selfIntResults.reserve( count ); } OBVIOUS_PRIVATE_COPY( MbShellSelfIntResults ) }; diff --git a/C3d/Include/conv_exchange_settings.h b/C3d/Include/conv_exchange_settings.h index 4260d5c..8a5f44f 100644 --- a/C3d/Include/conv_exchange_settings.h +++ b/C3d/Include/conv_exchange_settings.h @@ -409,9 +409,9 @@ public : public: /// \ru Получить имя документа. \en Get document's name. virtual const std::string GetDocumentName () const = 0; //{ return std::string( GetDocName().get_str() ); }; - /// \ru Получить имя файла для конвертирования. \en Get file name for converting. - virtual const c3d::path_string FullFilePath () const = 0 ;//{ return c3d::path_string( GetFileName().c_str() ); }; - /// \ru Является ли файл текстовым. \en Whether the file is a text file. + /// \ru Получить имя файла для конвертирования. \en Get file name for converting. + virtual const c3d::path_string FullFilePath() const = 0;//{ return c3d::path_string( GetFileName().c_str() ); }; + /// \ru Является ли файл текстовым. \en Whether the file is a text file. virtual bool IsFileAscii () const = 0; /// \ru Получить версию формата при экспорте. \en Get the version of format for export. virtual long int GetFormatVersion () const { return EXPORT_DEFAULT; }; @@ -529,6 +529,9 @@ public: /// \ru Определить способ формирования визуальных свойст при чтении из C3D. \en Specify the way how visual properties form while reading from C3D. virtual ColorProcessing GetC3DVisualPropertiesResolutionStrategy() const { return ColorProcessing::cr_Both; } + + /// \ru Импортировать полигональные объекты как объекты с топологической информацией. \en Import polygonal objects as objects with topological information. + virtual bool ImportMeshesWithTopology() const { return false; } }; // IConvertorProperty3D @@ -576,6 +579,7 @@ public: double appUnitsFactor; ///< \ru Единицы длины модели пользовательского приложения. \en Length units of the model used in user application. bool attatchIdAttributes; ///< \ru Следует ли формировать атрибут на основе идентификатора элемнта в файле. \en Whether to attatch the element's id in file as attribute. bool auditEnabled; + bool importMeshesWithTopology; ///< \ru Сохранять сетки в MbMesh (false) или в MbPolymesh (true). \en Save meshes to MbMesh (false) or to MbPolymesh (true). ColorProcessing visualPropertiesFormation; ///< \ru Способ формирования визуальных свойст при чтении из C3D. \en The way how visual properties form while reading from C3D. SPtr pruductIdMaker; ///< \ru Генератор однострочного идентификатора по данным об изделии. \en Generator of a single-line id based on product information attribute. SPtr scaleRequester; /// \ru Запросчик масштабного коэффициента единиц длины. \en Scale requester. @@ -715,6 +719,9 @@ public: /// \ru Определить способ формирования визуальных свойст при чтении из C3D. \en Specify the way how visual properties form while reading from C3D. ColorProcessing GetC3DVisualPropertiesResolutionStrategy() const override; + /// \ru Импортировать полигональные объекты как объекты с топологической информацией. \en Import polygonal objects as objects with topological information. + bool ImportMeshesWithTopology() const override { return importMeshesWithTopology; } + OBVIOUS_PRIVATE_COPY( ConvConvertorProperty3D ) }; // IConvertorProperty3D @@ -803,4 +810,30 @@ public: bool StdToC3D( const std::string & from, c3d::string_t& to ) override; }; + +//------------------------------------------------------------------------------ +/** \brief \ru Преобразование строк с использованием кодировки Windows-1251. + \en Transform strings using the Windows-1251 encoding. + \ingroup Base_Tools_String +*/ +class CONV_CLASS IC3DCharEncodingTransformerWindows1251 : public IC3DCharEncodingTransformer +{ +public: + ~IC3DCharEncodingTransformerWindows1251() override = default; + + //------------------------------------------------------------------------------ + /** \brief \ru Преобразовать строку C3D в строку STD. + \en Transform C3D string to the STD one. \~ + \ingroup Base_Tools_String + */ + bool C3DToStd( const c3d::string_t& from, std::string & to ) override; + + //------------------------------------------------------------------------------ + /** \brief \ru Преобразовать строку STD в строку C3D. + \en Transform STD string to the C3D one. \~ + \ingroup Base_Tools_String + */ + bool StdToC3D( const std::string & from, c3d::string_t& to ) override; +}; + #endif // __CONV_EXCHANGE_SETTINGS_H diff --git a/C3d/Include/conv_model_tree_linearized.h b/C3d/Include/conv_model_tree_linearized.h index 1566404..676c8be 100644 --- a/C3d/Include/conv_model_tree_linearized.h +++ b/C3d/Include/conv_model_tree_linearized.h @@ -1,4 +1,7 @@ -#include +#ifndef MODEL_TREE_LINEARIZED_H +#define MODEL_TREE_LINEARIZED_H + +#include #include #include #include @@ -50,18 +53,18 @@ class LinearizedContainer { ReferencedItemType item; mutable std::vector references; public: + // Конструктор по умолчанию + LinearizedContainer() = default; + + // Конструктор копирования по умолчанию + LinearizedContainer(const LinearizedContainer& i) = default; + // Конструктор - LinearizedContainer( const ReferencedItemType& it ) + LinearizedContainer(const ReferencedItemType& it) : item( it ) , references() { } - // Конструктор копирования - LinearizedContainer( const LinearizedContainer& i ) - : item( i.item ) - , references( i.references ) { - } - // Оператор сравнения bool operator ==(const LinearizedContainer& to) const { return item == to.item; @@ -117,9 +120,14 @@ public: // Деструктор ~LinearizedTreeDocument(); -public: + PartsLinearized GetPartsList() const; + + AssembliesLinearized GetAssembliesList() const; + // Заполнить данные void FillLinearizedData(); + + private: // Заполнены ли данные bool IsFilled(); @@ -153,4 +161,6 @@ public: void SolidPlaneCutting( const MbSolid & solid, std::vector & cutRes ); // Резка тела MbResultType SolidCut( const MbSolid & solid, const MbSurface & surf, bool forward ); -}; \ No newline at end of file +}; + +#endif //MODEL_TREE_LINEARIZED_H \ No newline at end of file diff --git a/C3d/Include/conv_res_type.h b/C3d/Include/conv_res_type.h index 703ff9c..b1c056c 100644 --- a/C3d/Include/conv_res_type.h +++ b/C3d/Include/conv_res_type.h @@ -32,5 +32,12 @@ enum MbeConvResType { cnv_UnsupportedVersion ///< \ru Неподдерживаемая версия формата. \en Unsupported format version. }; +//------------------------------------------------------------------------------ +/** \brief \ru Получить строковое описание результата конвертирования. +\en Get string description of the result of converting operation. +\ingroup Data_Interface +*/ +// --- +CONV_FUNC (std::string) MbeConvResTypeToString(MbeConvResType result); #endif \ No newline at end of file diff --git a/C3d/Include/conv_topo_mesh.h b/C3d/Include/conv_topo_mesh.h index 8df60d7..baa5c1a 100644 --- a/C3d/Include/conv_topo_mesh.h +++ b/C3d/Include/conv_topo_mesh.h @@ -19,8 +19,7 @@ class MbGrid; class MbFloatGrid; -class MbMesh; -class MbTriangle; +class MbItem; namespace JTC { @@ -45,14 +44,12 @@ namespace JTC { typedef std::vector MeshVertexVector; typedef std::vector MeshPolygonVector; - typedef std::pair TrianglePair; - - //------------------------------------------------------------------------------ // Сетка с топологической информацией // --- class CONV_CLASS TopoMesh : public MbRefItem { - SPtr mesh; + protected: + SPtr item; TopoGridVector grids; MeshVertexVector ownPoints; MeshPolygonVector ownFacePolygons; @@ -67,10 +64,10 @@ namespace JTC { virtual ~TopoMesh(); /// Инициализировать - bool Init( const MbMesh& mesh, bool enableDiagnostics = false ); + bool Init( const MbItem& mesh, bool enableDiagnostics = false ); /// Получить сетку - const MbMesh* GetMesh() const; + SPtr GetMesh() const; /// Число полигонов size_t MeshPolygonsCount() const; @@ -89,7 +86,7 @@ namespace JTC { /// Получить вырожденные треуголники std::map< size_t, std::vector > GetDegeneratedTriangles() const; - + /// Получить граничные точки сетки std::vector GetBoundaryPoints() const; @@ -97,7 +94,7 @@ namespace JTC { void Reset(); /// Получить следующую в цепочке граничную вершину. - size_t NextBoundaryVertex( size_t indexBoundaryVertex, const std::vector& allBoundary ) const; + //unused:size_t NextBoundaryVertex( size_t indexBoundaryVertex, const std::vector& allBoundary ) const; /// Сформировать внешнюю границу начиная с указанной вершины. bool InitVoidBoundFrom( std::vector& freeBoundaryVerticis ); @@ -105,6 +102,9 @@ namespace JTC { /// Получить точность задания расстояния. double MetricTolerance() const; + /// Получить нормаль на сетке + void GetNormal( size_t indexGrid, size_t indexNormal, MbFloatVector3D& vNormal ) const; + OBVIOUS_PRIVATE_COPY( TopoMesh ) }; diff --git a/C3d/Include/cr_offset_wireframe.h b/C3d/Include/cr_offset_wireframe.h new file mode 100644 index 0000000..59bc039 --- /dev/null +++ b/C3d/Include/cr_offset_wireframe.h @@ -0,0 +1,75 @@ +//////////////////////////////////////////////////////////////////////////////// +/** + \file + \brief \ru Строитель эквидистантного каркаса. + \en Creator of an offset wire frame. +*/ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef __CR_OFFSET_WIREFRAME_H +#define __CR_OFFSET_WIREFRAME_H + + +#include +#include + + +//------------------------------------------------------------------------------ +/** \brief \ru Строитель эквидистантного каркаса. + \en Creator of an offset wire frame. \~ + \details \ru Строитель эквидистантного каркаса. + \en Creator of an offset wire frame. \~ + \ingroup Model_Creators +*/ +// --- +class MATH_CLASS MbOffsetWireFrameCreator : public MbCreator { +private: + MbOffsetWireFrameParams _parameters; ///< \ru Параметры эквидистантного каркаса. \en Parameters of an offset wire frame. + +public: + /** \brief \ru Конструктор по параметрам. + \en Constructor by parameters. \~ + \details \ru Конструктор эквидистантного карскаса в пространстве. + \en Constructor of an offset wire frame in the space. \~ + \param[in] params - \ru Параметры. + \en Parameters. \~ + */ + MbOffsetWireFrameCreator( const MbOffsetWireFrameParams & params ); + + /// \ru Деструктор. \en Destructor. + virtual ~MbOffsetWireFrameCreator(); + +protected: + /// \ru Конструктор копирования. \en Copy-constructor. + MbOffsetWireFrameCreator( const MbOffsetWireFrameCreator & other, + MbRegDuplicate * iReg ); +private: + MbOffsetWireFrameCreator(); ///< \ru Не реализовано. \en Not implemented. + +public: + // \ru Общие функции строителя. \en The common functions of the creator. + MbeCreatorType IsA() const override; ///< \ru Тип элемента. \en A type of element. + MbCreator & Duplicate( MbRegDuplicate * iReg = nullptr) const override; ///< \ru Сделать копию. \en Create a copy. + + bool IsSame ( const MbCreator &, double accuracy) const override; ///< \ru Являются ли объекты равными? \en Determine whether an object is equal? + bool IsSimilar( const MbCreator & ) const override; ///< \ru Являются ли объекты подобными. \en Whether the objects are similar. + bool SetEqual ( const MbCreator & ) override; ///< \ru Сделать равным. \en Make equal. + + void Transform( const MbMatrix3D &, MbRegTransform * = nullptr ) override; ///< \ru Преобразовать элемент согласно матрице. \en Transform element according to the matrix. + void Move ( const MbVector3D &, MbRegTransform * = nullptr ) override; ///< \ru Сдвиг. \en Translation. + void Rotate ( const MbAxis3D &, double angle, MbRegTransform * = nullptr ) override; ///< \ru Повернуть вокруг оси. \en Rotate about an axis. + + MbePrompt GetPropertyName() override; ///< \ru Дать имя свойства объекта. \en Get the object property name. + void GetProperties ( MbProperties & ) override; ///< \ru Выдать свойства объекта. \en Get properties of the object. + void SetProperties ( const MbProperties & ) override; ///< \ru Записать свойства объекта. \en Set properties of the object. + + bool CreateWireFrame( MbWireFrame *&, MbeCopyMode, RPArray * items = nullptr ) override; ///< \ru Построить каркас по журналу построения \en Create an offset wire frame from the history tree. + +DECLARE_PERSISTENT_CLASS_NEW_DEL( MbOffsetWireFrameCreator ) +}; // MbOffsetWireFrameCreator + + +IMPL_PERSISTENT_OPS( MbOffsetWireFrameCreator ) + + +#endif // __CR_OFFSET_WIREFRAME_H diff --git a/C3d/Include/cr_split_data.h b/C3d/Include/cr_split_data.h index d009f85..f475748 100644 --- a/C3d/Include/cr_split_data.h +++ b/C3d/Include/cr_split_data.h @@ -84,10 +84,10 @@ private: public: /// \ru Конструктор. \en Constructor. MbSplitData() - : place ( ) + : sketchContours( ) + , place ( ) , direction ( ) , sense ( orient_BOTH ) - , sketchContours( ) , spaceCurves ( ) , surfaces ( ) , creators ( ) @@ -96,10 +96,10 @@ public: } /// \ru Конструктор по двумерному контуру в локальной системе координат. \en Constructor by two-dimensional contour in the local coordinate system. MbSplitData( const MbPlacement3D & pl, MbeSenseValue dirSense, const MbContour & item, bool same ) - : place ( pl ) + : sketchContours( ) + , place ( pl ) , direction ( ) , sense ( dirSense ) - , sketchContours( ) , spaceCurves ( ) , surfaces ( ) , creators ( ) @@ -111,10 +111,10 @@ public: } /// \ru Конструктор по двумерному контуру в локальной системе координат. \en Constructor by two-dimensional contour in the local coordinate system. MbSplitData( const MbPlacement3D & pl, const MbVector3D & dir, const MbContour & item, bool same ) - : place ( pl ) + : sketchContours( ) + , place ( pl ) , direction ( dir ) , sense ( orient_BOTH ) - , sketchContours( ) , spaceCurves ( ) , surfaces ( ) , creators ( ) @@ -129,10 +129,10 @@ public: /// \ru Конструктор по двумерным контурам в локальной системе координат. \en Constructor by two-dimensional contours in the local coordinate system. template MbSplitData( const MbPlacement3D & pl, MbeSenseValue dirSense, const PlaneContoursVector & items, bool same ) - : place ( pl ) + : sketchContours( ) + , place ( pl ) , direction ( ) , sense ( dirSense ) - , sketchContours( ) , spaceCurves ( ) , surfaces ( ) , creators ( ) @@ -143,10 +143,10 @@ public: /// \ru Конструктор по двумерным контурам в локальной системе координат. \en Constructor by two-dimensional contours in the local coordinate system. template MbSplitData( const MbPlacement3D & pl, const MbVector3D & dir, const PlaneContoursVector & items, bool same ) - : place ( pl ) + : sketchContours( ) + , place ( pl ) , direction ( dir ) , sense ( orient_BOTH ) - , sketchContours( ) , spaceCurves ( ) , surfaces ( ) , creators ( ) @@ -158,10 +158,10 @@ public: } /// \ru Конструктор по пространственным кривым. \en Constructor by spatial curves. MbSplitData( const c3d::ConstSpaceCurvesSPtrVector & items, bool same ) - : place ( ) + : sketchContours( ) + , place ( ) , direction ( ) , sense ( orient_BOTH ) - , sketchContours( ) , spaceCurves ( ) , surfaces ( ) , creators ( ) @@ -171,10 +171,10 @@ public: } /// \ru Конструктор по пространственным кривым. \en Constructor by spatial curves. MbSplitData( const c3d::ConstSpaceCurvesVector & items, bool same ) - : place ( ) + : sketchContours( ) + , place ( ) , direction ( ) , sense ( orient_BOTH ) - , sketchContours( ) , spaceCurves ( ) , surfaces ( ) , creators ( ) @@ -184,10 +184,10 @@ public: } /// \ru Конструктор по поверхности. \en Constructor by a surface. MbSplitData( const MbSurface & item, bool same ) - : place ( ) + : sketchContours( ) + , place ( ) , direction ( ) , sense ( orient_BOTH ) - , sketchContours( ) , spaceCurves ( ) , surfaces ( ) , creators ( ) @@ -199,10 +199,10 @@ public: } /// \ru Конструктор по поверхностям. \en Constructor by surfaces. MbSplitData( const c3d::ConstSurfacesSPtrVector & items, bool same ) - : place ( ) + : sketchContours( ) + , place ( ) , direction ( ) , sense ( orient_BOTH ) - , sketchContours( ) , spaceCurves ( ) , surfaces ( ) , creators ( ) @@ -212,10 +212,10 @@ public: } /// \ru Конструктор по поверхностям. \en Constructor by surfaces. MbSplitData( const c3d::ConstSurfacesVector & items, bool same ) - : place ( ) + : sketchContours( ) + , place ( ) , direction ( ) , sense ( orient_BOTH ) - , sketchContours( ) , spaceCurves ( ) , surfaces ( ) , creators ( ) diff --git a/C3d/Include/cr_wrap_curve.h b/C3d/Include/cr_wrap_curve.h index c34f0be..2514ad3 100644 --- a/C3d/Include/cr_wrap_curve.h +++ b/C3d/Include/cr_wrap_curve.h @@ -32,6 +32,9 @@ public: /// \ru Конструктор по параметрам. \en Constructor by parameters. MbWrapCurveCreator( const MbCurvesWrappingParams & params ); +private: + MbWrapCurveCreator(); // \ru Не реализовано \en Not implemented + public: virtual ~MbWrapCurveCreator() {}; @@ -55,11 +58,8 @@ public: bool CreateWireFrame( MbWireFrame *&, MbeCopyMode, RPArray * items = nullptr ) override; private: - MbWrapCurveCreator(); // \ru Не реализовано \en Not implemented - OBVIOUS_PRIVATE_COPY( MbWrapCurveCreator ) DECLARE_PERSISTENT_CLASS_NEW_DEL( MbWrapCurveCreator ) }; // MbWrapCurveCreator - #endif // __CR_WRAP_CURVE_H diff --git a/C3d/Include/creator.h b/C3d/Include/creator.h index 22a78db..6bbb798 100644 --- a/C3d/Include/creator.h +++ b/C3d/Include/creator.h @@ -102,6 +102,8 @@ enum MbeCreatorType { ct_UnwrapPointCreator = 220, ///< \ru Строитель развёрнутой точки. \en Constructor of the unwrapped point. \n ct_WrapPointCreator = 221, ///< \ru Строитель свёрнутой точки. \en Constructor of the wrapped point. \n + ct_OffsetWireFrameCreator = 222, ///< \ru Строитель эквидистантного каркаса. \en Constructor of the offset wireframe. \n + // \ru Строители полигональных объектов. \en Creators of polygonal objects. ct_SimpleMeshCreator = 400, ///< \ru Строитель полигонального объекта без истории. \en Constructor of a polygonal object without history. ct_ReverseMeshCreator = 401, ///< \ru Строитель вывернутого полигонального объекта. \en Constructor of a reversed polygonal object. diff --git a/C3d/Include/cur_surface_intersection.h b/C3d/Include/cur_surface_intersection.h index 7706825..68c90ba 100644 --- a/C3d/Include/cur_surface_intersection.h +++ b/C3d/Include/cur_surface_intersection.h @@ -72,10 +72,10 @@ namespace c3d // namespace C3D Кривая пересечения поверхностей используется для стыковки поверхностей или для описания ребра стыковки двух граней. Кривая пересечения может описывать разные типы рёбер стыковки двух граней: \n обычное ребро - поверхности разные, двумерные кривые разные,\n - ребро-шов - поверхность одина и та же, двумерные кривые разные не равные,\n + ребро-шов - поверхность одна и та же, двумерные кривые разные не равные,\n Ребро-линия разъема - поверхности копии, двумерные кривые копии,\n - ребро-край - поверхность одина и та же, двумерная кривая одина и та же,\n - ребро-полюс - поверхность одина и та же, двумерные кривые копии.\n + ребро-край - поверхность одна и та же, двумерная кривая одна и та же,\n + ребро-полюс - поверхность одна и та же, двумерные кривые копии.\n Если две двумерные кривые кривых на поверхности curveOne curveTwo являются контурами, то количество сегментов в них должно быть одинаковым. \en Intersection curve of surfaces contains two curves on intersected surfaces - curveOne and curveTwo, conformed to the next rules:\n @@ -128,7 +128,7 @@ private : { SPtr spaceCurve; ///< \ru Пространственная аппроксимационная кривая. \en The spatial approximating curve. \~ SpaceCurveAuxiliaryData() : spaceCurve( nullptr ) {} - SpaceCurveAuxiliaryData( const SpaceCurveAuxiliaryData & c ) : spaceCurve( nullptr ) { + SpaceCurveAuxiliaryData( const SpaceCurveAuxiliaryData & c ) : AuxiliaryData {}, spaceCurve( nullptr ) { if ( c.spaceCurve != nullptr ) { spaceCurve = static_cast( &c.spaceCurve->Duplicate() ); } diff --git a/C3d/Include/func_nurbs_function.h b/C3d/Include/func_nurbs_function.h index b46c50b..4aa3746 100644 --- a/C3d/Include/func_nurbs_function.h +++ b/C3d/Include/func_nurbs_function.h @@ -53,7 +53,7 @@ protected: public: MbNurbsFunctionAuxiliaryData() : values(), pointsM(), weightM() {} - MbNurbsFunctionAuxiliaryData( const MbNurbsFunctionAuxiliaryData & ) : values(), pointsM(), weightM() {} + MbNurbsFunctionAuxiliaryData( const MbNurbsFunctionAuxiliaryData & ) : AuxiliaryData {}, values(), pointsM(), weightM() {} virtual ~MbNurbsFunctionAuxiliaryData() {} }; diff --git a/C3d/Include/gc_api.h b/C3d/Include/gc_api.h index 8dd5fad..7d1849d 100644 --- a/C3d/Include/gc_api.h +++ b/C3d/Include/gc_api.h @@ -21,7 +21,7 @@ #include #include -#include +#include template class SArray; diff --git a/C3d/Include/gce_api.h b/C3d/Include/gce_api.h index 2457a97..48517c2 100644 --- a/C3d/Include/gce_api.h +++ b/C3d/Include/gce_api.h @@ -337,6 +337,25 @@ GCE_FUNC(pattern_item) GCE_AddLinearPattern( GCE_system gSys, GCE_vec2d trans ); //--- GCE_FUNC(pattern_item) GCE_AddAngularPattern( GCE_system gSys, GCE_point point, double angle ); +//---------------------------------------------------------------------------------------- +/** \brief \ru Объявить составной паттерн по двум данным. + \en Declare a composition pattern of two patterns. \~ + \param[in] gSys - \ru Система ограничений. + \en System of constraints. \~ + \param[in] pItem1 - \ru Первый паттерн. + \en The first pattern. \~ + \param[in] pItem2 - \ru Второй паттерн. + \en The second patttern. \~ + + \return \ru Дескриптор зарегистрированного паттерна. + \en Descriptor of registered pattern. \~ + + \details \ru Метод создает паттерн - композицию двух паттернов. + \en The method creates an composition pattern defined by two patterns. \~ +*/ +//--- +GCE_FUNC(pattern_item) GCE_AddCompositionPattern( GCE_system gSys, pattern_item pItem1, pattern_item pItem2 ); + //---------------------------------------------------------------------------------------- /** \brief \ru Создать k-й экземпляр образца в данном паттерне. \en Create k-th instance of the sample in a given pattern. \~ @@ -359,13 +378,38 @@ GCE_FUNC(pattern_item) GCE_AddAngularPattern( GCE_system gSys, GCE_point point, //--- GCE_FUNC(geom_item) GCE_AddInstance( GCE_system gSys, pattern_item pItem, geom_item sample, int k ); +//---------------------------------------------------------------------------------------- +/** \brief \ru Создать (i, j) экземпляр образца в данном составном паттерне. + \en Create (i, j) instance of the sample in a given composition pattern. \~ + \param[in] gSys - \ru Система ограничений. + \en System of constraints. \~ + \param[in] pItem - \ru Дескриптор паттерна. + \en Descriptor of pattern. \~ + \param[in] sample - \ru Дескриптор образца. + \en Descriptor of sample. \~ + \param[in] i - \ru Номер экземпляра. + \en Copy number. \~ + \param[in] j - \ru Номер экземпляра. + \en Copy number. \~ + + \return \ru Дескриптор зарегистрированного экземпляра. + \en Descriptor of registered instance. \~ + + \details \ru Метод создает (i, j) экземпляр образца в данном составном паттерне. + При i = 0, j = 0 возвращает идентификатор образца. + \en The method creates the (i, j) instance of the sample in the given pattern. + It returns the sample descriptor if i = 0 and j = 0. \~ +*/ +//--- +GCE_FUNC(geom_item) GCE_AddInstance( GCE_system gSys, pattern_item pItem, geom_item sample, int i, int j ); + //---------------------------------------------------------------------------------------- /** \brief \ru Добавить в систему жёсткое множество геометрических объектов. \en Add a rigid set of geometric objects to the system. \~ \details \ru Жёсткое множество - это массив геометрических объектов, зафиксированных друг относительно друга. Жёсткое множество представляет собой геометрический объект, для которого доступен весь функционал работы с геометрическими объектами. Например, у него можно спросить тип (#GCE_GeomType -> GCE_SET) или запросить - положение. С помощью вызовов #GCE_GetPoint и #GCE_GetCoordValue можно получить начало координат и направление оси OX + положение. С помощью вызовов #GCE_GetPointXY и #GCE_GetCoordValue можно получить начало координат и направление оси OX ЛСК жёсткого множества. Чтобы удалить жёсткое множество, надо, как и для любого другого геометрического объекта, вызвать функцию #GCE_RemoveGeom. При этом составляющие жёсткое множество объекты (geoms) при удалении жёсткого множества не удаляются и могут далее быть использованы в решателе. С геометрическими объектами, образующими @@ -375,7 +419,7 @@ GCE_FUNC(geom_item) GCE_AddInstance( GCE_system gSys, pattern_item pItem, geom_i дескриптор самого геометрического объекта из массива geoms, на который накладывается ограничение. \en A rigid set is an array of geometric objects which are fixed relative to each other. It is considered as a geometric object and hence all the functionality for working with geometric objects is available for it. For - example, it's possible to request its type (#GCE_GeomType -> GCE_SET) or get its position invoking #GCE_GetPoint + example, it's possible to request its type (#GCE_GeomType -> GCE_SET) or get its position invoking #GCE_GetPointXY and #GCE_GetCoordValue to get the origin and the direction of the OX axis of the LCS of the rigid set. To remove a rigid set it's necessary to call the function #GCE_RemoveGeom. Geometric objects (geoms) are not deleted together with a rigid set and can be used in the solver after it will be deleted. With geometric objects that have been @@ -828,6 +872,21 @@ GCE_FUNC(geom_item) GCE_FixOffset( GCE_system gSys, geom_item curve ); //--- GCE_FUNC(bool) GCE_IsConstrainedGeom( GCE_system gSys, geom_item g ); +//---------------------------------------------------------------------------------------- +/** \brief \ru Определить смежные ли это ограничение и геометрический объект. + \en Determine whether the constraint and the geometric object are adjacent. \~ + \param[in] gSys - \ru Система ограничений. + \en System of constraints. \~ + \param[in] g - \ru Дескриптор геометрического объекта. + \en Descriptor of geometric object. \~ + \param[in] cItem - \ru Дескриптор ограничения. + \en Descriptor of constraint. \~ + \return \ru true, если ограничение и геометрический объект смежные. + \en true if the constraint and the geometric object are adjacent. \~ +*/ +//--- +GCE_FUNC(bool) GCE_IsAdjacentConstraint( GCE_system gSys, geom_item g, constraint_item cItem ); + //---------------------------------------------------------------------------------------- /** \brief \ru Функция отвечает на вопрос: Имеется ли хотя бы один экземпляр паттерна? \en The function answers the question: Is there an instance of the pattern? \~ @@ -1507,6 +1566,32 @@ GCE_FUNC(constraint_item) GCE_AddLength( GCE_system gSys, geom_item curve, GCE_d //--- GCE_FUNC(constraint_item) GCE_AddPatterned( GCE_system gSys, pattern_item pItem, geom_item sample, geom_item instance, int k ); +//---------------------------------------------------------------------------------------- +/** \brief \ru Связать ограничением паттерна два геометрических объекта. + \en Bind two geometric objects by a pattern constraint. \~ + \param[in] gSys - \ru Система ограничений. + \en System of constraints. \~ + \param[in] pItem1 - \ru Дескриптор первого паттерна. + \en Descriptor of first pattern. \~ + \param[in] pItem2 - \ru Дескриптор второго паттерна. + \en Descriptor of second pattern. \~ + \param[in] sample - \ru Дескриптор образца. + \en Descriptor of sample. \~ + \param[in] instance - \ru Дескриптор экземпляра. + \en Descriptor of instance. \~ + \param[in] i - \ru Номер экземпляра в первом паттерне. + \en Copy number in first pattern. \~ + \param[in] j - \ru Номер экземпляра во втором паттерне. + \en Copy number in second pattern. \~ + \return \ru Дескриптор зарегистрированного ограничения. + \en Descriptor of registered constrained. \~ + + \details \ru Метод связывает два объекта ограничением паттерна. + \en The method binds the two objects by a pattern constraint. \~ +*/ +//--- +GCE_FUNC(constraint_item) GCE_AddPatterned( GCE_system gSys, pattern_item pItem, geom_item sample, geom_item instance, int i, int j ); + //---------------------------------------------------------------------------------------- /** \brief \ru Задать ограничение "Управляющий параметр" или "Фиксация переменной" \en Set the constraint "Driving parameter" or "Fixation of variable" \~ @@ -1825,6 +1910,30 @@ GCE_FUNC(constraint_item) GCE_AddDirectedDistance( GCE_system gSys, geom_item p[ GCE_FUNC(constraint_item) GCE_AddLinearEquation( GCE_system gSys, const double * a , const var_item * v, size_t n, double c ); +//---------------------------------------------------------------------------------------- +/** \brief \ru Задать ориентацию касания. + \en Set the tangent orientation. + \param[in] \ru gSys Система ограничений. + \en gSys System of constraints. \~ + \param[in] \ru constraint Дескриптор ограничения. + \en constraint Constraint's descriptor. \~ + \param[in] \ru alignment Опция выравнивания касания кривых. + \en alignment Curve tangency alignment option. \~ + \return \ru В случае успешного вызова функция вернет новое значение выравнивания, заданного вызовом. + \en If the call is successful, the function will return the new alignment value specified by the call. \~ + \details + \ru В настоящее время функция применяется к ограничению касания (GCE_TANGENT). Данный вызов устанавливает + сонаправленность или противонаправленность касательных (GCE_COORIENTED, GCE_OPPOSITE), + либо делает выбор автоматически, если задать опцию GCE_AUTO_ALIGNMENT. Когда выбрана опцию GCE_CLOSEST, + солвер будет поддерживать взаимную ориентацию согласно текущего размещения геометрии. + \en The function currently applies to the tangency constraint (GCE_TANGENT). The call sets whether + the direction of the geometry tangents are cooriented/opposite or makes the selection automatically + if you set the GCE_AUTO_ALIGNMENT option. When the option GCE_CLOSEST is selected the C3D Solver + should maintain the current geometry positions. \~ +*/ +//--- +GCE_FUNC(GCE_alignment) GCE_SetAlignment( GCE_system gSys, constraint_item constraint, GCE_alignment alignment = GCE_AUTO_ALIGNMENT ); + //---------------------------------------------------------------------------------------- /** \brief \ru Изменить значение управляющего размера. \en Change the value of driving dimension. \~ @@ -2126,7 +2235,14 @@ GCE_FUNC(GCE_result) GCE_Transform( GCE_system gSys, const MbMatrix & mat ); //--- GCE_FUNC(bool) GCE_SetJournal( GCE_system gSys, const char * fName ); -#define FB_NULL_GEOM 0 +//---------------------------------------------------------------------------------------- +/** \brief \ru Выдать журнал записывающий вызовы Solver API, а также другие события, имеющие отношение к взаимодействием с солвером. + \en Get a logger that recording API calls, as well as other events related to interaction with the solver. \~ + \note \ru Вызов используется пока только для тестовых целей. Может быть изменен или удален из API в следующих ревизиях. + \en The call is used for testing purposes only. It may be changed or removed in future revisions. \~ +*/ +//--- +GCE_FUNC(GCE_journal) GCE_SubscribeJournal( GCE_system gSys, GCE_log_func logFunc, GCE_extra_param extParam ); //---------------------------------------------------------------------------------------- /** diff --git a/C3d/Include/gce_callback.h b/C3d/Include/gce_callback.h index 3bbce4e..c041eca 100644 --- a/C3d/Include/gce_callback.h +++ b/C3d/Include/gce_callback.h @@ -30,7 +30,7 @@ using GCE_geom_registered = void (*)( GCE_app_geom ag); ///< Application geom using GCE_geom_unregistered = void (*)( GCE_app_geom ag); using GCE_allow_zero_radius = bool (*)( GCE_app_geom ag); ///< \ru Разрешает окружность нулевого радиуса. \en Allow zero radius of a circle. using GCE_allow_zero_length = bool (*)( GCE_app_geom ag); ///< \ru Разрешает участок кривой или отрезок нулевой длины. \en Allow zero length of a bounded curve or line segments. -using GCE_get_lseg_direction = GCE_vec2d (*)(GCE_app_geom ag); ///< \ru Функция, которая выдет направляющий вектор отрезка. \en Function that returns the direction of a line segment. +using GCE_get_lseg_direction = GCE_vec2d (*)(GCE_app_geom ag); ///< \ru Функция, которая выдает направляющий вектор отрезка. \en Function that returns the direction of a line segment. using GCE_abort = bool (*)(); ///< Query to interrupt calculations //---------------------------------------------------------------------------------------- @@ -90,6 +90,11 @@ GCE_FUNC(GCE_result) GCE_Register( GCE_system gSys, const GCE_callback_table & c //--- GCE_FUNC(void) GCE_Bind( GCE_system, geom_item, GCE_app_geom ); +//---------------------------------------------------------------------------------------- +/// Disassociate an application geometry and a solver's descriptor. +//--- +GCE_FUNC(void) GCE_Unbind( GCE_system, geom_item ); + /** \} Constraints2D_API diff --git a/C3d/Include/gce_equations.h b/C3d/Include/gce_equations.h new file mode 100644 index 0000000..ca43ab3 --- /dev/null +++ b/C3d/Include/gce_equations.h @@ -0,0 +1,131 @@ +////////////////////////////////////////////////////////////////////////////////////////// +/** + \file + \brief \ru Нелинейные уравнения и неравенства, определяемые на стороне Приложения. + \en Nonlinear equations and inequations defined by the application. \~ +*/ +////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __GCE_EQUATIONS_H +#define __GCE_EQUATIONS_H + +#include +#include "gce_geom.h" + +class MtVectorN; +template class RPArray; + +//---------------------------------------------------------------------------------------- +/** \brief \ru Интерфейс численного уравнения, выраженного через набор координат. + \en Interface of the numeric equation expressed via a set of coordinates. + \details \ru Как правило, это алгебраические уравнение общего вида f(x1,x2,..,xn) = g(x1,x2,..,xn) + явно-выраженной форме: x1 = g(x2,x3,..,xn). + \en As a rule, it is an algebraic equation of a general form f(x1,x2,..,xn) = g(x1,x2,..,xn) + or, as a special case, it is an equation in explicit form: x1 = g(x2,x3,..,xn). \~ +*/ +//--- +struct GCE_CLASS ItNumericEquation +{ + enum eval_result_code: char + { + EVAL_RESULT_Undefined = 0, + EVAL_RESULT_Ok, + EVAL_RESULT_OutOfDomaint + }; + struct eval_result + { + eval_result_code resCode = EVAL_RESULT_Undefined; + double funDer = MB_MAXDOUBLE; // Derivative value. + double funVal = MB_MAXDOUBLE; // Function value. + }; + /// \ru Выдать координату с индексом crdIdx. \en Get coordinate with crdIdx index. + virtual ItCoord* Coord( size_t crdIdx ) const = 0; + /// \ru Количество координат, связанных с уравнением. \en Count of coordinates connected with the equation. + virtual size_t NumCoords() const = 0; + /// \ru Вычисление первой производной по координате и значений функции. \en The first derivative by coordinate and the function values calculation. + virtual eval_result Evaluate(const ItCoord* crd, const std::vector& crdVals) const; + /// \ru Выдать координату зависимой переменной (для уравнений заданных в явно-выраженной форме). \en Get the coordinate of dependent variable (for explicit equations). + virtual const ItCoord* DependedCoord() const = 0; + + /** \brief \ru Признак уравнения, заданного в форме присвоения (начиная с Компас V12). + \en Flag of equation specified in form of assignment. + \details + \ru Уравнения, заданные в явно выраженной форме, считающиеся присвоением выражения зависимой переменной: x1 = g(x2,x3,..,xn). + Такие уравнения стремимся вычислять иерархическим способом, сверху-вниз. + \en Equations specified explicitly, considered to be the assignment of dependent variable: x1 = g(x2,x3,..,xn). + It is preferred to compute such equations by hierarchical top-down method. \~ + */ + virtual bool IsExplicit() const = 0; + +public: + virtual refcount_t AddRef() const = 0; + virtual refcount_t Release() const = 0; + +private: + // It will be removed + virtual bool CalcDerive( ItGeomCoord &, const MtVectorN &, double &, double & ) const { return false; } + // It will be removed. + virtual ItGeomCoord * GetCoord( ptrdiff_t ) const { return nullptr; } + // It will be removed. + virtual bool CalcDerive( ItGeomCoord &, const std::vector & /*argLine*/, double & /*fd*/, double & /*f*/ ) const { return false; } + // It will be removed. + virtual ptrdiff_t GetCoordCount() const { return 0; } + // It will be removed. + virtual ptrdiff_t GetDependedCoordIdx() const { return -1; } + +protected: + ~ItNumericEquation() {} +}; + +//---------------------------------------------------------------------------------------- +/** \brief \ru Вычисление первой производной по координате и значений функции. + \en The first derivative by coordinate and the function values calculation. +*/ +//--- +inline ItNumericEquation::eval_result ItNumericEquation::Evaluate(const ItCoord* crd, const std::vector& crdVals) const +{ + eval_result res; + ItGeomCoord * gCrd = dynamic_cast(const_cast(crd)); + if ( gCrd!=nullptr && CalcDerive(*gCrd, crdVals, res.funDer, res.funVal)) + { + res.resCode = EVAL_RESULT_Ok; + } + return res; +} + + +using ItAlgebraicConstraint = ItNumericEquation; + +/** + \addtogroup Constraints2D_API + \{ +*/ + +//---------------------------------------------------------------------------------------- +/** \brief \ru Задать ограничение, реализуемое на стороне клиента. + \en Specify a constraint implemented by the user. \~ + \param[in] gSys - \ru Система ограничений. + \en System of constraints. \~ + \param[in] iEqu - \ru Интерфейс уравнения, заданного пользователем. + \en Interface of the equation specified by the user. \~ + \param[in] varsCount - \ru Количество переменных. + \en Count of variables. \~ + \param[in] varsVector - \ru Вектор переменных. + \en Vector of variables. \~ + \return \ru Дескриптор нового ограничения. + \en Descriptor of a new constraint. \~ +*/ +// --- +GCE_FUNC(constraint_item) GCE_AddEquation( GCE_system gSys + , ItAlgebraicConstraint & iEqu + , size_t varsCount + , const var_item * varsVector ); + +/** + \} + Constraints2D_API +*/ + +#endif // __GCE_EQUATIONS_H + +// eof \ No newline at end of file diff --git a/C3d/Include/gce_routines.h b/C3d/Include/gce_routines.h new file mode 100644 index 0000000..75ab437 --- /dev/null +++ b/C3d/Include/gce_routines.h @@ -0,0 +1,25 @@ +////////////////////////////////////////////////////////////////////////////////////////// +/** + \file + \brief \ru API процедур и функций 2D решателя. + \en API of procedures and functions of 2D solver. \~ +*/ +////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __GCE_ROUTINES_H +#define __GCE_ROUTINES_H + +/** + \addtogroup Constraints2D_API + \{ +*/ + + +/** + \} + Constraints2D_API +*/ + +#endif // __GCE_ROUTINES_H + +// eof \ No newline at end of file diff --git a/C3d/Include/gce_types.h b/C3d/Include/gce_types.h index 8c558b1..8a01980 100644 --- a/C3d/Include/gce_types.h +++ b/C3d/Include/gce_types.h @@ -76,7 +76,7 @@ const pattern_item GCE_NULL_P = GCE_NULL; const double GCE_UNDEFINED_DBL = UNDEFINED_DBL; //---------------------------------------------------------------------------------------- -/// \ru Словарь типов геометрических примитивов. \en Dictionary of geometric primitives types. +/// \ru Словарь геометрических типов данных. \en Dictionary of а geometric data types. //--- typedef enum { @@ -363,6 +363,34 @@ typedef enum } GCE_bisec_variant; +//---------------------------------------------------------------------------------------- +/** \brief \ru Варианты выравнивания направлений. + \en Variants of alignment. \~ + \details \en Значение опции выравнивания используется для выбора из альтернативных решений + ограничения, такого как `GCE_TANGENT`. + \en The alignment value is used to alternate between solutions of a constraint such as `GCE_TANGENT`. + \note \ru Значения этого перечисления могут быть использованы для постоянного хранения и + останутся неизменными в следующих версиях. + \en Values of this enum can be used for permanent storage and will be kept + in the future versions. \~ +*/ +//--- +typedef enum +{ + GCE_NO_ALIGNMENT = 0, ///< \ru Неопределенное значение выравнивания (=не применима к данному ограничению). \en Undefined alignment value (=not applicable to this constraint). + GCE_COORIENTED, ///< \ru Для касания это сонаправленные касательные вектора (=нормали). \en For tangency, these are co-directional tangent vectors (=normal). + GCE_OPPOSITE, ///< \ru Для касания это противонаправленные касательные вектора (=нормали). \en For tangency, these are the opposing tangent vectors (=normal). + + /** \brief \ru Поддерживать способ выравнивания согласно начальному или текущему положению геометрии (соответствует поведению прежних версий). + \en Maintain the alignment according to the initial or current position of the geometry (reproduces behaviour from previous versions). \~ */ + GCE_CLOSEST, + + /** \brief \ru Автоматически выбрать опцию выравнивания, используя начальное приближение геометрии. + \en Automatically determine alignment options using initial geometry approximation. \~ */ + GCE_AUTO_ALIGNMENT, + +} GCE_alignment; + //---------------------------------------------------------------------------------------- /// \ru Координаты вектора. \en Vector coordinates. @@ -380,7 +408,7 @@ struct GCE_CLASS GCE_vecNd { size_t size; double * arg; - GCE_vecNd(): arg(0), size(0) {} + GCE_vecNd(): size(0), arg(0) {} }; //---------------------------------------------------------------------------------------- @@ -568,8 +596,9 @@ struct GCE_CLASS GCE_dim_pars double dimValue; ///< \ru Значение размера, когда var == GCE_NULL_V. \en Value of dimension when var == GCE_NULL_V. GCE_dim_pars() - : dimValue( 0.0 ) - , var( GCE_NULL_V ) + : var( GCE_NULL_V ) + , dimValue( 0.0 ) + {} }; @@ -718,6 +747,48 @@ struct GCT_CLASS GCT_diagnostic_pars {} }; +//---------------------------------------------------------------------------------------- +/** \brief \ru Дополнительные данные колбэка #GCE_log_func, интерпретируемые на стороне приложения. + \en Additional #GCE_log_func callback data interpreted on the application side. \~ + \sa #GCE_log_func +*/ +//--- +struct GCE_CLASS GCE_extra_param +{ + size_t funcId; // Integral identifier of a user-defined callback. + void * funcData; // Pointer to an application data structure. + GCE_extra_param() { funcId = 0, funcData = 0; } +}; + +//---------------------------------------------------------------------------------------- +// It represents a journal that logs Solver API transactions. +//--- +struct ItJrnLogger; + +//---------------------------------------------------------------------------------------- +// It represents a journal that logs Solver API transactions. +//--- +typedef struct +{ + const ItJrnLogger * logger; // Internal C3D Solver logger. + GCE_extra_param extra; // Callback extra data interpreted in the application side. +} GCE_journal; + +//---------------------------------------------------------------------------------------- +// Type of log string. +//--- +typedef enum +{ + GCE_LOG_JournalLine /// \ru Строка отчета о вызове Solver API. \en Reporting string about the Solver API call. + , GCE_LOG_Message /// \ru Строка передает некоторое информативное сообщение. \en The string notifies that something informative happend. + , GCE_LOG_Error /// \ru Строка извещает об ошибочной ситуации. \en Error notification. +} GCE_log_type; + +//---------------------------------------------------------------------------------------- +// Callback function for logging messages from the solver. +//--- +typedef void ( *GCE_log_func )( GCE_journal, GCE_log_type logType, const char* recStr ); + /** \} Constraints2D_API diff --git a/C3d/Include/gcm_api.h b/C3d/Include/gcm_api.h index 50a001d..e167601 100644 --- a/C3d/Include/gcm_api.h +++ b/C3d/Include/gcm_api.h @@ -1134,6 +1134,32 @@ GCM_FUNC(GCM_geom) GCM_GetMovingGeom( GCM_system gSys ); GCM_FUNC(GCM_result) GCM_SolveReposition( GCM_system gSys, GCM_geom g, const MbPlacement3D & newPos, GCM_reposition movType ); +//---------------------------------------------------------------------------------------- +/** + \brief \ru Решить систему для произвольного изменения положения тела в заданной плоскости. + \en Solve the system for an arbitrary change of position of one solid in a given plane. + \param[in] gSys - \ru Система ограничений. + \en System of constraints. \~ + \param[in] movGeom - \ru Компонент, деталь, которой манипулируют. + \en Component, part which is manipulated. \~ + \param[in] projPlane - \ru Нормаль к плоскости, в которой происходит перетаскивание, заданная в ГСК сборки. + \en The normal to the plane in which the dragging occurs, specified in the assembly WCS. \~ + \param[in] cursor - \ru Текущее положение курсора в ГСК.. + \en Current position of a cursor in the WCS. \~ + \return \ru Код результата. \en Result code. \~ + + \details + \ru Процедура, управляющая режимом перетаскивания. При использовании данной функции не требуется предварительно + делать соответствующий ей вызов GCM_PrepareReposition, а так же не требуется вызывать GCM_FinishReposition + по окончании её использования. + \en The procedure that controls the drag and drop mode. When using this function, there is no need to make + a preliminary invoke of GCM_PrepareReposition, and there is no need to invoke GCM_FinishReposition + after using it. \~ +*/ +//--- +GCM_FUNC(GCM_result) GCM_SolveReposition( GCM_system gSys, GCM_geom moveGeom, const MbCartPoint3D & cursor, + const MbVector3D & projPlane ); + /** \brief \ru Решить систему сопряжений для новой позиции курсора в режиме драггинга. \en Solve the system of constraints for new position of cursor in the dragging mode. @@ -1214,7 +1240,7 @@ struct GCT_diagnostic_pars; It's used for testing purposes only. */ //--- -GCM_FUNC(const GCT_diagnostic_pars) GCM_DiagnosticPars( GCM_system gSys ); +GCM_FUNC(GCT_diagnostic_pars) GCM_DiagnosticPars( GCM_system gSys ); //---------------------------------------------------------------------------------------- // Deprecated (2021). Use GCM_GeometryStatus to query about GCM_G_STATUS_Frozen. diff --git a/C3d/Include/gcm_manager.h b/C3d/Include/gcm_manager.h index 78c6ec8..8ae19e1 100644 --- a/C3d/Include/gcm_manager.h +++ b/C3d/Include/gcm_manager.h @@ -88,12 +88,12 @@ public: static const MtParVariant undef; ///< \ru Неопределенное значение. \en Undefined value. public: - MtParVariant() : tag( GCM_ARG_UNDEFINED ), enumVal( SYS_MAX_INT64-2 ) {} // \ru Неопределенное значение \en Undefined value - MtParVariant( float val ) : tag( GCM_ARG_NUMBER ), numVal( static_cast(val) ) {} - MtParVariant( double val ) : tag( GCM_ARG_NUMBER ), numVal( val ) {} + MtParVariant() : enumVal( SYS_MAX_INT64-2 ), tag( GCM_ARG_UNDEFINED ) {} // \ru Неопределенное значение \en Undefined value + MtParVariant( float val ) : numVal( static_cast(val) ), tag( GCM_ARG_NUMBER ) {} + MtParVariant( double val ) : numVal( val ), tag( GCM_ARG_NUMBER ) {} template< class _EnumType > - MtParVariant( _EnumType val ) : tag( GCM_ARG_ENUM ), enumVal( static_cast(val) ) {} - MtParVariant( const GCM_interval & interval ) : tag( GCM_ARG_INTERVAL ), interVal( interval ) {} + MtParVariant( _EnumType val ) : enumVal( static_cast(val) ), tag( GCM_ARG_ENUM ) {} + MtParVariant( const GCM_interval & interval ) : interVal( interval ), tag( GCM_ARG_INTERVAL ) {} public: template< typename _EnumType > diff --git a/C3d/Include/gcm_mates_generator.h b/C3d/Include/gcm_mates_generator.h index 1a9da3a..5f83388 100644 --- a/C3d/Include/gcm_mates_generator.h +++ b/C3d/Include/gcm_mates_generator.h @@ -32,13 +32,13 @@ struct GCM_CLASS TMParameters double realpar; // Dimension value. TMParameters( AlignCondition al, MtMateType mtype, double par = 0. ) - : align ( al ) - , matetype( mtype ) + : matetype( mtype ) + , align ( al ) , realpar ( par ) {} TMParameters( GCM_c_type mtype, double par = 0.0, GCM_alignment al = GCM_NO_ALIGNMENT ) - : align ( al ) - , matetype( mtype ) + : matetype( mtype ) + , align ( al ) , realpar ( par ) {} }; @@ -267,7 +267,7 @@ private: MtGeomSolver & manager; ///< \ru Решатель сборки. \en Solver of the assembly. public: - explicit AssemblyGenerator( MtGeomSolver & m ) : manager( m ), dimConstrs() {} + explicit AssemblyGenerator( MtGeomSolver & m ) : dimConstrs(), manager( m ) {} private: AssemblyGenerator( const AssemblyGenerator & ); diff --git a/C3d/Include/gcm_routines.h b/C3d/Include/gcm_routines.h index a7e0fe1..e3b1a50 100644 --- a/C3d/Include/gcm_routines.h +++ b/C3d/Include/gcm_routines.h @@ -77,8 +77,8 @@ struct GCM_CLASS MtMateParameters public: MtMateParameters() - : myAlignVal( GCM_NO_ALIGNMENT ) - , myDimVal( 0.0 ) + : myDimVal( 0.0 ) + , myAlignVal( GCM_NO_ALIGNMENT ) , myDimEvaluated( false ) , myDimSigned( false ) {} @@ -154,9 +154,9 @@ struct GCM_CLASS MtADimensionTraits double value; ///< \ru Значение размера - угол вращения. \en Dimension value - the angle of rotation. MtADimensionTraits() - : axisZ() - , firstVector() + : firstVector() , secondVector() + , axisZ() , value( 0.0 ) {} }; diff --git a/C3d/Include/gcm_types.h b/C3d/Include/gcm_types.h index 6b77e95..b853fc1 100644 --- a/C3d/Include/gcm_types.h +++ b/C3d/Include/gcm_types.h @@ -339,18 +339,19 @@ typedef enum /* Произвольное поведение (arbitrary behavior). */ - GCM_REPOSITION_FreeRotation ///< \ru Произвольная репозиция с преимуществом вращения. \en Arbitrary reposition with predominant rotation. \~ - , GCM_REPOSITION_FreeMoving ///< \ru Произвольная репозиция с преимуществом перемещения. \en Arbitrary reposition with predominant moving. \~ + GCM_REPOSITION_FreeRotation = 1 ///< \ru Произвольная репозиция с преимуществом вращения. \en Arbitrary reposition with predominant rotation. \~ + , GCM_REPOSITION_FreeMoving = 2 ///< \ru Произвольная репозиция с преимуществом перемещения. \en Arbitrary reposition with predominant moving. \~ /* Строгое поведение (strict behavior). */ - , GCM_REPOSITION_Dragging ///< \ru Перетаскивание в плоскости "экрана". \en Dragging in the plane of the screen. \~ - , GCM_REPOSITION_Rotation ///< \ru Вращение вокруг неподвижной оси. \en Rotation around fixed axis. \~ - , GCM_REPOSITION_Transfer /**< \ru Перенос только для одного твердого тела. \en Shift only one solid. \~ + , GCM_REPOSITION_Dragging = 3///< \ru Перетаскивание в плоскости "экрана". \en Dragging in the plane of the screen. \~ + , GCM_REPOSITION_Rotation = 4///< \ru Вращение вокруг неподвижной оси. \en Rotation around fixed axis. \~ + , GCM_REPOSITION_Transfer = 5/**< \ru Перенос только для одного твердого тела. \en Shift only one solid. \~ \note \ru Этот режим #GCM_REPOSITION_Transfer был задуман для процессов вставки нового тела в сборку САПР. \en This mode #GCM_REPOSITION_Transfer have been intended for insertion processes of a new solid in the CAD assembly. \~ */ + , GCM_REPOSITION_Inactive = 1000 } GCM_reposition; //---------------------------------------------------------------------------------------- @@ -421,19 +422,20 @@ typedef enum \note Internal use only. The feature is under development. */ //--- -typedef struct +struct GCM_CLASS GCM_dof_record { - GCM_dof_result result; ///< \ru Код результата вычисления степени свободы геометрического объекта. \en Resulting code of evaluating the geometric degrees of freedom. \~ + /// \ru Код результата вычисления степени свободы геометрического объекта. \en Resulting code of evaluating the geometric degrees of freedom. \~ + GCM_dof_result result; // Translational degree of freedom info. - size_t tdof; + size_t tdof; GCM_vec3d dir1; GCM_vec3d dir2; // Rotational degree of freedom info. size_t rdof; GCM_point center; - GCM_vec3d axis1; - GCM_vec3d axis2; -} GCM_dof_record; + GCM_vec3d axis1 ; + GCM_vec3d axis2 ; +}; //---------------------------------------------------------------------------------------- /** \brief \ru Статус геометрического объекта. diff --git a/C3d/Include/halfedge_range_iterators.h b/C3d/Include/halfedge_range_iterators.h index 78b43f7..5a07740 100644 --- a/C3d/Include/halfedge_range_iterators.h +++ b/C3d/Include/halfedge_range_iterators.h @@ -170,6 +170,12 @@ struct MATH_CLASS ActiveFacetsBegEndPair */ struct MATH_CLASS EdgeConstIterator { + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = MbHalfedgeEdge; + using pointer = MbHalfedgeEdge *; + using reference = MbHalfedgeEdge &; + const MbHalfedge & _topo; //< \ru Ссылка на топологию. \en Topology reference. bool _bFirst = true; //< \ru Признак того, что не нужно проверять окончание итерации. \en If true there is no need to check the end of the iteration. size_t _edge = SYS_MAX_T; //< \ru Индекс текущего ребра. \en An actual edge index. @@ -236,10 +242,15 @@ struct MATH_CLASS EdgesAroundFacetBegEndPair */ struct MATH_CLASS VertexFacetConstIterator : EdgeFacetConstIterator { + using value_type = MbHalfedgeEdge; + using pointer = MbHalfedgeEdge *; + using reference = MbHalfedgeEdge &; + /// \ru Конструктор. \en Constructor. VertexFacetConstIterator( const MbHalfedge & topo, size_t iF, bool begin = true ) noexcept; /// \ru Доступ к данным. \en Data access. const MbHalfedgeVertex & operator*() const noexcept; + const MbHalfedgeVertex * operator->() const noexcept; }; diff --git a/C3d/Include/lump.h b/C3d/Include/lump.h index e6365df..a08aee4 100644 --- a/C3d/Include/lump.h +++ b/C3d/Include/lump.h @@ -181,7 +181,8 @@ public: {} /// \ru Конструктор копирования с регистратором. \en Copy-constructor with the registrator. MbLumpCube( const MbLumpCube & other ) - : cube( other.cube ) + : MbRefItem {} + , cube( other.cube ) , from( other.from ) , component( other.component ) , identifier( other.identifier ) diff --git a/C3d/Include/map_lump.h b/C3d/Include/map_lump.h index aa18b8b..71b5b4a 100644 --- a/C3d/Include/map_lump.h +++ b/C3d/Include/map_lump.h @@ -209,8 +209,8 @@ public: : component ( _comp ) , identifier( _ident ) , solid ( _solid ) - , name ( &_name ) , from ( _from ) + , name ( &_name ) , wtCurves ( 0, 1, true ) { name.SetOwn(false); @@ -231,8 +231,8 @@ public: : component ( _comp ) , identifier( _ident ) , solid ( nullptr ) - , name ( &_name ) , from ( ) + , name ( &_name ) , wtCurves ( 0, 1, true ) { name.SetOwn(false); diff --git a/C3d/Include/math_version.h b/C3d/Include/math_version.h index d13c6fb..9eaa589 100644 --- a/C3d/Include/math_version.h +++ b/C3d/Include/math_version.h @@ -97,10 +97,12 @@ #define MATH_22_HF3_VERSION 0x16000004L ///< \ru Версия файла - 22.0 HF3. \en The file version - 22.0 HF3. \~ \ingroup Base_Tools #define MATH_22_HF4_VERSION 0x16000005L ///< \ru Версия файла - 22.0 HF4. \en The file version - 22.0 HF4. \~ \ingroup Base_Tools #define MATH_22_HF5_VERSION 0x16000006L ///< \ru Версия файла - 22.0 HF5. \en The file version - 22.0 HF5. \~ \ingroup Base_Tools +#define MATH_22_HF6_VERSION 0x16000007L ///< \ru Версия файла - 22.0 HF6. \en The file version - 22.0 HF6. \~ \ingroup Base_Tools #define MATH_22_UHF_VERSION 0x16000011L ///< \ru Версия файла - 22.0 UHF (Upper Hot Fix). \en The file version - 22.0 UHF (Upper Hot Fix). \~ \ingroup Base_Tools #define C3D_2023_VERSION 0x16001001L ///< \ru Версия файла - C3D 2023. \en The file version - C3D 2023. \~ \ingroup Base_Tools #define MATH_23_VERSION 0x17000001L ///< \ru Версия файла - 23.0. \en The file version - 23.0. \~ \ingroup Base_Tools #define MATH_23_HF1_VERSION 0x17000003L ///< \ru Версия файла - 23.0 HF1. \en The file version - 23.0 HF1. \~ \ingroup Base_Tools +#define MATH_23_HF2_VERSION 0x17000004L ///< \ru Версия файла - 23.0 HF2. \en The file version - 23.0 HF2. \~ \ingroup Base_Tools #define MATH_23_UHF_VERSION 0x17000101L ///< \ru Версия файла - 23.0 UHF (Upper Hot Fix). \en The file version - 23.0 UHF (Upper Hot Fix). \~ \ingroup Base_Tools #define C3D_2024_VERSION 0x17001002L ///< \ru Версия файла - C3D 2024. \en The file version - C3D 2024. \~ \ingroup Base_Tools diff --git a/C3d/Include/math_x.h b/C3d/Include/math_x.h index 7f1b0f4..89b377d 100644 --- a/C3d/Include/math_x.h +++ b/C3d/Include/math_x.h @@ -93,7 +93,7 @@ namespace c3d { #define CONCAT_TKNS(A, B, C, D) A B C D // Concatenate tokens without expanding macro (if invoked from macro, arguments are expanded). #define CONCAT_TOKENS(A, B, C, D) CONCAT_TKNS(A, B, C, D) // Concatenate tokens with expanding macro. -#define DEPR_MSG "This is a deprecated API that will be removed in version 2024!" // Message about a deprecated API. +#define DEPR_MSG "This is a deprecated API that will be removed in version 2025!" // Message about a deprecated API. #define DEPR_MSG_EX(msg) CONCAT_TOKENS(DEPR_MSG, " Use ", #msg, " instead it.") // Message about a deprecated API indicating a replacement API. diff --git a/C3d/Include/mb_point_mating.h b/C3d/Include/mb_point_mating.h index 48534f1..ea7b4c6 100644 --- a/C3d/Include/mb_point_mating.h +++ b/C3d/Include/mb_point_mating.h @@ -131,12 +131,12 @@ MbPntMatingData::MbPntMatingData( const MbeMatingType nType, bool nMovePnts, bool nAttach ) : MbRefItem ( ) - , type ( nType ) , tangent ( (nTang != nullptr) ? new Vector( *nTang ) : nullptr ) , tangentDer1 ( (nTangDer1 != nullptr) ? new Vector( *nTangDer1 ) : nullptr ) , tangentDer2 ( (nTangDer2 != nullptr) ? new Vector( *nTangDer2 ) : nullptr ) - , movePnts ( nMovePnts ) , changedPnts ( nChangedPnts ) + , type ( nType ) + , movePnts ( nMovePnts ) , attach ( nAttach ) { if ( type <= trt_Position ) { // BUG_52162 @@ -153,12 +153,12 @@ MbPntMatingData::MbPntMatingData( const MbeMatingType nType, template MbPntMatingData::MbPntMatingData( const MbPntMatingData & d ) : MbRefItem ( ) - , type ( d.type ) , tangent ( (d.tangent != nullptr) ? new Vector( *d.tangent ) : nullptr ) , tangentDer1 ( (d.tangentDer1 != nullptr) ? new Vector( *d.tangentDer1 ) : nullptr ) , tangentDer2 ( (d.tangentDer2 != nullptr) ? new Vector( *d.tangentDer2 ) : nullptr ) - , movePnts ( d.movePnts ) , changedPnts ( d.changedPnts ) + , type ( d.type ) + , movePnts ( d.movePnts ) , attach ( d.attach ) { } diff --git a/C3d/Include/mb_property_title.h b/C3d/Include/mb_property_title.h index 2ed906a..5e84b74 100644 --- a/C3d/Include/mb_property_title.h +++ b/C3d/Include/mb_property_title.h @@ -181,6 +181,7 @@ enum MbePrompt IDS_ITEM_0274, ///< \ru Усеченный каркас. \en Trimmed wire frame. IDS_ITEM_0275, ///< \ru Развернутая точка. \en Unwrapped point. IDS_ITEM_0276, ///< \ru Свёрнутая точка. \en Wrapped point. + IDS_ITEM_0277, ///< \ru Эквидистантный каркас. \en Offset wire frame. // \ru Типы параметрических поверхностей. \en Types of parametric surfaces. @@ -202,6 +203,7 @@ enum MbePrompt IDS_ITEM_0315, ///< \ru Конически согнутая поверхность. \en Conically Bent Surface. IDS_ITEM_0316, ///< \ru Конически разогнутая поверхность. \en Conically Unbent Surface. IDS_ITEM_0317, ///< \ru Поверхность заметания с изменением образующей. \en Sweep Surface with Changin Generatin. + IDS_ITEM_0318, ///< \ru Линейчато согнутая/разогнутая поверхность. \en Ruled Bent/Unbent Surface. IDS_ITEM_0319, ///< \ru Плоскость. \en Plane. IDS_ITEM_0320, ///< \ru Сферическая поверхность. \en Spherical Surface. IDS_ITEM_0321, ///< \ru Тороидальная поверхность. \en Toroidal Surface. @@ -1341,6 +1343,8 @@ enum MbePrompt IDS_PROP_2033, ///< \ru Индекс части скругления. \en Index of fillet part. IDS_PROP_2034, ///< \ru Опция выбора результата. \en Option for the result selection. + IDS_PROP_2035, ///< \ru Режим адаптации. \en Adaptation mode. + IDS_PROP_LAST = 9999, ///< \ru Наибольшее значение. \en The greatest value. }; diff --git a/C3d/Include/mb_smooth_nurbs_fit_curve.h b/C3d/Include/mb_smooth_nurbs_fit_curve.h index 2645fe7..d07fc6f 100644 --- a/C3d/Include/mb_smooth_nurbs_fit_curve.h +++ b/C3d/Include/mb_smooth_nurbs_fit_curve.h @@ -182,11 +182,11 @@ private: public: /// \ru Конструктор по умолчанию. \en Default constructor. MbApproxNurbsParameters( VERSION version = Math::DefaultMathVersion() ) - : _order ( c3d::NURBS_DEGREE ) + : _bClosed ( false ) + , _order ( c3d::NURBS_DEGREE ) , _methodSmoothing( sm_CurvatureVariance ) , _coefSmoothing ( -1. ) , _tolerance ( c3d::DELTA_MIN ) - , _bClosed ( false ) , _pReference ( nullptr ) , _version ( version ) {} diff --git a/C3d/Include/mb_variables.h b/C3d/Include/mb_variables.h index 7faa600..3f201a6 100644 --- a/C3d/Include/mb_variables.h +++ b/C3d/Include/mb_variables.h @@ -623,7 +623,7 @@ MATH_FUNC(const char *) C3DFileNameOnly( const char * path ); // Suppress a warning "unreferenced formal parameter" -#define C3D_UNUSED_PARAMETER( param ) (void*)(¶m) +#define C3D_UNUSED_PARAMETER( param ) (std::ignore = param) #ifdef C3D_DEBUG diff --git a/C3d/Include/mesh_halfedge_attr.h b/C3d/Include/mesh_halfedge_attr.h index e019447..88f7637 100644 --- a/C3d/Include/mesh_halfedge_attr.h +++ b/C3d/Include/mesh_halfedge_attr.h @@ -22,11 +22,13 @@ class MbHalfedge; #define SIMPLE_FACET_ATTRIBUTE(type, value, nameAttr, typeAttr) \ class MATH_CLASS nameAttr : public MbHalfedgeAttrSimpleValueFacetBase\ {\ + private:\ + const type _def = value;\ public:\ nameAttr( const MbHalfedge & topo ) : MbHalfedgeAttrSimpleValueFacetBase( topo, typeAttr ) {}\ virtual ~nameAttr() {}\ static MbeTypeAttr IsA() { return typeAttr; }\ - type DefaultValue() const override { return value; }\ + const type& DefaultValue() const override { return _def; }\ HALFEDGE_VISITING();\ DECLARE_PERSISTENT_CLASS( nameAttr );\ }; @@ -35,11 +37,13 @@ class MbHalfedge; #define SIMPLE_EDGE_ATTRIBUTE(type, value, nameAttr, typeAttr) \ class MATH_CLASS nameAttr : public MbHalfedgeAttrSimpleValueEdgeBase\ {\ + private:\ + const type _def = value;\ public:\ nameAttr( const MbHalfedge & topo ) : MbHalfedgeAttrSimpleValueEdgeBase( topo, typeAttr ) {}\ virtual ~nameAttr() {}\ static MbeTypeAttr IsA() { return typeAttr; }\ - type DefaultValue() const override { return value; }\ + const type& DefaultValue() const override { return _def; }\ HALFEDGE_VISITING();\ DECLARE_PERSISTENT_CLASS( nameAttr );\ }; @@ -48,11 +52,13 @@ class MbHalfedge; #define SIMPLE_VERTEX_ATTRIBUTE(type, value, nameAttr, typeAttr) \ class MATH_CLASS nameAttr : public MbHalfedgeAttrSimpleValueVertexBase\ {\ + private:\ + const type _def = value;\ public:\ nameAttr( const MbHalfedge & topo ) : MbHalfedgeAttrSimpleValueVertexBase( topo, typeAttr ) {}\ virtual ~nameAttr() {}\ static MbeTypeAttr IsA() { return typeAttr; }\ - type DefaultValue() const override { return value; }\ + const type& DefaultValue() const override { return _def; }\ HALFEDGE_VISITING();\ DECLARE_PERSISTENT_CLASS( nameAttr );\ }; @@ -105,6 +111,8 @@ public: bool CalculateEdgePoint( size_t iEd, double prm, MbCartPoint3D & pt ) const; /// \ru Получить 3Д вершины для последовательности ребер. \en Get 3D points for all vertices in the edges chain. bool GetEdgePathVertices( const c3d::IndicesVector & edges, c3d::SpacePointsVector & points ) const; + /// \ru Получить 3Д вершины для последовательности ребер. \en Get 3D points for all vertices in the edges chain. + bool GetEdgePathVertices( const c3d::IndicesPairsVector & edges, c3d::SpacePointsVector & points ) const; /// \ru Посчитать нормаль треугольного фасета. \en Calculate the normal for the triangle facet. bool CalculateTriangleNormal( size_t iTr, MbVector3D & normal ) const; /// \ru Посчитать aspect ratio треугольного фасета. \en Calculate aspect ratio for the triangle facet. @@ -123,8 +131,10 @@ public: bool CalculateLengthEdge( size_t iEd, double & len ) const; /// \ru Посчитать квадрат длины ребра. \en Calculate the square of the edge's length. bool CalculateLengthEdge2( size_t iEd, double & len2 ) const; - // \ru Рассчитать габарит в локальной системы координат. \en Calculate the bounding box int the given coordinate system. + // \ru Рассчитать габарит в локальной системе координат. \en Calculate the bounding box int the given coordinate system. void CalculateLocalGabarit( const MbMatrix3D & matrInto, MbCube & localCube ) const; + // \ru Рассчитать габарит фасета в локальной системе координат. \en Calculate the facet's bounding box int the given coordinate system. + void CalculateFacetLocalGabarit( const MbMatrix3D & matrInto, size_t iF, MbCube & localCube ) const; // \ru Рассчитать уравнение плоскости треугольного фасета. \en Calculate the plane where the given triangle facet is located. bool GetTrianglePlaneEquation( size_t iTr, bool bNormalize, std::array & plane ) const; // \ru Рассчитать нормаль в вершине усреднением нормалей соседних треугольных фасетов. \en Calculate the normal at a vertex as the average normal of all triangle facets around it. @@ -192,6 +202,8 @@ public: bool CalculateLengthEdge2( size_t iEd, double & len2 ) const; /// \ru Получить параметры для последовательности ребер. \en Get 2D parameters for all vertices in the edges chain. bool GetEdgePathVertices( const c3d::IndicesVector & edges, c3d::ParamPointsVector & points ) const; + /// \ru Получить параметры для последовательности ребер. \en Get 2D parameters for all vertices in the edges chain. + bool GetEdgePathVertices( const c3d::IndicesPairsVector & edges, c3d::ParamPointsVector & points ) const; /// \ru Рассчитать габаритный прямоугольник. \en Calculate the bounding rect. void CalculateRect( MbRect & rect ) const; diff --git a/C3d/Include/mesh_halfedge_attr_base.h b/C3d/Include/mesh_halfedge_attr_base.h index b2d673e..5acb4f4 100644 --- a/C3d/Include/mesh_halfedge_attr_base.h +++ b/C3d/Include/mesh_halfedge_attr_base.h @@ -121,6 +121,8 @@ public: void SetId( size_t id ) { _id = id; } /// \ru Получить индекс. \en Get identifier. size_t GetId() const { return _id; } + /// \ru Получить топологию. \en GetTopology. + const MbHalfedge & GetTopo() const { return *_topo; } /// \ru Принять посетителя. \en Accept Visitor virtual void Accept( HalfedgeVisitor & visitor ) = 0; @@ -179,7 +181,7 @@ const T * CastHalfedgeAttribute( const MbHalfedgeAttrBase * pObj ) \ingroup Data_Structures */ // --- -template +template class MbHalfedgeAttrSimpleValueBase : public MbHalfedgeAttrBase { protected: @@ -192,7 +194,7 @@ public: virtual ~MbHalfedgeAttrSimpleValueBase() {} /// \ru Получить значение по умолчанию. \en Get default value. - virtual Value DefaultValue() const = 0; + virtual const Value & DefaultValue() const = 0; /// \ru Установить размер массива величин, заполнить его значением по умолчанию. \en Set size of the values array filled with default values. void SetSize( size_t size ) { _values.assign( size, DefaultValue() ); } /// \ru Получить размер массива величин. \en Get size of the values array. @@ -200,7 +202,11 @@ public: /// \ru Определено ли значение элемента. \en Check if value is undefined (default). virtual bool IsUndefined( size_t i ) const { return _values[i] == DefaultValue(); } /// \ru Получить значение элемента. \en Get value by identifier. + template::value >::type> Value GetValue( size_t i ) const { return _values[i]; } + /// \ru Получить значение элемента. \en Get value by identifier. + template::value >::type> + const Value & GetValue( size_t i ) const { return _values[i]; } /// \ru Установить значение элемента в указанную величину. \en Set value to the element given by identifier. void SetValue( size_t i, Value val ) { _values[i] = val; } /// \ru Установить значение набора элементов в указанную величину. \en Set value to the set of elements. diff --git a/C3d/Include/mesh_provider.h b/C3d/Include/mesh_provider.h new file mode 100644 index 0000000..b0b3f50 --- /dev/null +++ b/C3d/Include/mesh_provider.h @@ -0,0 +1,121 @@ +//////////////////////////////////////////////////////////////////////////////// +/** + \file + \brief Вспомогательный интерфейс для полигональной топологии. + +*/ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef __MESH_PROVIDER_H +#define __MESH_PROVIDER_H + +#include + +class MbAttributeContainer; +class MbPolymeshTopo; +class MbPolymesh; +class MbMesh; + +//------------------------------------------------------------------------------ +/** \brief \ru Абстрактный контейнер данных полигонального объекта. + \en An abstract container for polygonal object data. \~ + \details \ru Абстрактный контейнер данных полигонального объекта. + \en An abstract container for polygonal object data. \~ + \warning \ru В разработке. + \en Under development. \~ +*/ +// --- +class MATH_CLASS IMeshProvider +{ +protected: + /// \ru Конструктор. \en Constructor. + IMeshProvider() = default; + +public: + /// \ru Деструктор. \en Destructor. + virtual ~IMeshProvider() = default; + /** \brief \ru Создать экземпляр класса на основе MbMesh. + \en Create an object by MbMesh. \~ + \param[in] mesh - \ru Полигональный геометрический объект. + \en A polygonal geometric object. \~ + \return \ru Возвращает указатель на созданный объект. + \en Returns pointer to created object. \~ + */ + static IMeshProvider * Create( const MbMesh & mesh ); + + /// \ru Валидны ли данные. \en Returns true if the object is ready to be used. + virtual bool IsReady() const = 0; + /// \ru Получить количество точек \en Get the number of points. + virtual size_t GetPointsCount() const = 0; + /// \ru Получить количество нормалей \en Get the number of normals. + virtual size_t GetNormalsCount() const = 0; + /// \ru Получить точку с индексом index \en Get the point with given index. + virtual void GetPoint( size_t index, MbCartPoint3D & point ) const = 0; + /// \ru Получить нормаль с индексом index \en Get the normal with given index. + virtual void GetNormal( size_t index, MbVector3D & normal ) const = 0; + /// \ru Получить количество вершин \en Get the number of normals. + virtual size_t GetVerticesCount() const { return GetPointsCount(); } + /// \ru Получить количество граней \en Get the number of facets. + virtual size_t GetFacetsCount() const = 0; + /// \ru Получить индекс точки для вершины с индексом index \en Get point index for the vertex with the given index. + virtual size_t GetVertexPointIndex( size_t index ) const = 0; + /// \ru Получить количество вершин на грани с индексом index \en Get the number of vertices for the face with the given index. + virtual size_t GetFacetVerticesCount( size_t index ) const = 0; + /// \ru Получить индекс для вершины с порядковым номером number на грани с индексом index. \en Get the vertex index for the vertex on the facet with the given index with the given position number. + virtual size_t GetFacetVertexIndex( size_t index, size_t number ) const = 0; + /// \ru Получить флаг наличия нормалей граней. \en Returns true if facets normals exist. + virtual bool HasFacetNormals() const { return false; } + /// \ru Получить индекс нормали для грани с индексом index \en Get normal index for the facet with the given index. + virtual size_t GetFacetNormalIndex( size_t index ) const { return index; } + /// \ru Получить флаг наличия нормалей вершин граней \en Returns true if vertices normals exist. + virtual bool HasFacetVertexNormals() const { return false; } + /// \ru Получить индекс нормали для вершины с порядковым номером number на грани с индексом index. \en Get the vertex normal index for the vertex on the facet with the given index with the given position number. + virtual size_t GetFacetVertexNormalIndex( size_t index, size_t number ) const = 0; + /// \ru Получить количество групп граней \en Get the number of facet groups. + virtual size_t GetFacetGroupsCount() const { return 1; } + /// \ru Получить индекс группы для грани с индексом index. \en Get the facet group index for the facet with the given index. + virtual size_t GetFacetGroup( size_t /*index*/ ) const { return 0; } + /// \ru Получить флаг наличия атрибутов групп граней. \en Returns true if facets groups attributes exist. + virtual bool HasFacetGroupAttributes() const { return false; } + /// \ru Получить атрибуты для группы граней с индексом index \en Get facets group attributes. + virtual void GetFacetGroupAttributes( size_t /*index*/, std::unique_ptr & /*cont*/ ) const {} + /** \brief \ru Установить атрибуты топологии. + \en Set mesh topology attributes. \~ + \details \ru Предполагается, что объект polymesh содержит аттрибут маппинга от ребер сетки к порядковому номеру вершины на грани MbHalfedgeAttrSizetEdge + и атрибут для пометок перевернутых в процессе алгоритма фасетов MbHalfedgeAttrBoolFacet. + Среди всех атрибутов данная функция устанавливает только атрибуты нормалей вида MbHalfedgeAttrNormalsVertex. + Для установки других атрибутов следует создать наследника этого класса. + \en It's assumed that the polymesh object contains MbHalfedgeAttrSizetEdge attribute with edge mapping to the vertex facet position number + and MbHalfedgeAttrBoolFacet attribute with bool marks if facets were inverted during topology creation. + Among all attributes this function sets up only normals through MbHalfedgeAttrNormalsVertex attribute. + To add more attributes an inherited class should be created. + \param[in] bNormalsAveraging - \ru Флаг усреднения нормалей по веерам объединенных вершин. + \en A flag for normal vectors averaging around merged vertices fans. \~ + \param[in,out] polymesh - \ru Полигональный геометрический объект. + \en A polygonal geometric object. \~ + */ + virtual void SetMeshAttributes( bool bNormalsAveraging, MbPolymeshTopo & polymesh ) const; + /** \brief \ru Установить атрибуты сегментации. + \en Set attributes mesh segmentation attributes. \~ + \details \ru Данная функция сохраняет аттрибуты C3D оригинальных групп фасетов. + Для установки других атрибутов следует создать наследника этого класса. + \en This function saves original C3D attributes from original facet groups. + To add more attributes an inherited class should be created. + */ + virtual void SetSegmAttributes( MbPolymeshTopo & polymesh ) const; + /** \brief \ru Установить атрибуты полигонального объекта. + \en Set the polygonal object attributes. \~ + */ + virtual void SetPolymeshAttributes( MbPolymesh & /*polymesh*/ ) const {} + +protected: + /** \brief \ru Установить нормали сетки без усреднения в вершинах. + \en Set mesh normal vectors without averaging. \~ + */ + void InitFacetVertexNormals( MbPolymeshTopo & polymesh ) const; + /** \brief \ru Установить нормали сетки с усреднением в вершинах. + \en Set mesh normal vectors with averaging. \~ + */ + void InitFacetVertexNormalsWithAveraging( MbPolymeshTopo & polymesh ) const; +}; +#endif // __MESH_PROVIDER_H \ No newline at end of file diff --git a/C3d/Include/op_curve_parameter.h b/C3d/Include/op_curve_parameter.h index 74d643a..7fe82de 100644 --- a/C3d/Include/op_curve_parameter.h +++ b/C3d/Include/op_curve_parameter.h @@ -161,12 +161,12 @@ public: const MbVector3D & dir ) : _uv1beg ( uv1beg ) , _uv1end ( uv1end ) - , _ext1 ( ext1 ) , _uv2beg ( uv2beg ) , _uv2end ( uv2end ) - , _ext2 ( ext2 ) , _direction ( dir ) , _guideCurve ( nullptr ) + , _ext1 ( ext1 ) + , _ext2 ( ext2 ) , _useRedetermination ( false ) , _checkPoles ( false ) {} @@ -205,11 +205,11 @@ public: bool checkPoles ) : _uv1beg ( uv1beg ) , _uv1end ( uv1end ) - , _ext1 ( ext1 ) , _uv2beg ( uv2beg ) , _uv2end ( uv2end ) - , _ext2 ( ext2 ) , _guideCurve ( guideCurve ) + , _ext1 ( ext1 ) + , _ext2 ( ext2 ) , _useRedetermination ( useRedetermination ) , _checkPoles ( checkPoles ) {} @@ -287,8 +287,8 @@ public: MbIntCurveParams( const MbSNameMaker & snMaker ) : mergeCurves( true ) , cutCurves ( false ) - , _snMaker ( &snMaker.Duplicate() ) , _type ( ict_General ) + , _snMaker ( &snMaker.Duplicate() ) { if ( snMaker.GetMathVersion() > MATH_19_VERSION ) // KOMPAS-39273 + KOMPAS-40408 cutCurves = true; @@ -305,8 +305,8 @@ public: MbIntCurveParams( bool _cutCurves, const MbSNameMaker & snMaker ) : mergeCurves( true ) , cutCurves ( _cutCurves ) - , _snMaker ( &snMaker.Duplicate() ) , _type ( ict_General ) + , _snMaker ( &snMaker.Duplicate() ) {} /** \brief \ru Конструктор. \en Constructor. \~ @@ -322,8 +322,8 @@ public: MbIntCurveParams( bool _mergeCurves, bool _cutCurves, const MbSNameMaker & snMaker ) : mergeCurves( _mergeCurves ) , cutCurves ( _cutCurves ) - , _snMaker ( &snMaker.Duplicate() ) , _type ( ict_General ) + , _snMaker ( &snMaker.Duplicate() ) {} /** \brief \ru Конструктор. @@ -349,12 +349,12 @@ public: const MbCartPoint & uvInitOnSurface2, const MbVector3D & initDirection, const MbSNameMaker & nameMaker ) - : _values ( new MbIntCurveOnePointValues( - surface1Domain, surface2Domain, uvInitOnSurface1, uvInitOnSurface2, initDirection) ) - , _type ( ict_OnePoint ) - , mergeCurves( true ) + : mergeCurves( true ) , cutCurves ( true ) + , _type ( ict_OnePoint ) , _snMaker ( &nameMaker.Duplicate() ) + , _values ( new MbIntCurveOnePointValues( + surface1Domain, surface2Domain, uvInitOnSurface1, uvInitOnSurface2, initDirection) ) {} /** \brief \ru Конструктор. @@ -386,11 +386,11 @@ public: bool ext2, const MbVector3D & dir, const MbSNameMaker & nameMaker ) - : _values ( new MbIntCurveLimitPointsValues(uv1beg, uv1end, ext1, uv2beg, uv2end, ext2, dir) ) - , _type ( ict_TwoPoints ) - , mergeCurves( true ) + : mergeCurves( true ) , cutCurves ( true ) + , _type ( ict_TwoPoints ) , _snMaker ( &nameMaker.Duplicate() ) + , _values ( new MbIntCurveLimitPointsValues(uv1beg, uv1end, ext1, uv2beg, uv2end, ext2, dir) ) {} @@ -429,12 +429,12 @@ public: bool useRedetermination, bool checkPoles, const MbSNameMaker & nameMaker ) - : _values ( new MbIntCurveLimitPointsValues( - uv1beg, uv1end, ext1, uv2beg, uv2end, ext2, guideCurve, useRedetermination, checkPoles) ) - , _type ( ict_TwoPointsGuide ) - , mergeCurves( true ) + : mergeCurves( true ) , cutCurves ( true ) + , _type ( ict_TwoPointsGuide ) , _snMaker ( &nameMaker.Duplicate() ) + , _values ( new MbIntCurveLimitPointsValues( + uv1beg, uv1end, ext1, uv2beg, uv2end, ext2, guideCurve, useRedetermination, checkPoles) ) {} /// \ru Получить параметры создания кривой по начальной точке. \en Get the parameters for the curve creation by the initial point. @@ -490,8 +490,8 @@ public: const MbSNameMaker & snMaker ) : MbIntCurveParams( mergeCrvs, cutCrvs, snMaker ) , _faces1 ( faceIndices1 ) - , _same1 ( same1 ) , _faces2 ( faceIndices2 ) + , _same1 ( same1 ) , _same2 ( same2 ) , _useCreators( true ) {} @@ -515,8 +515,8 @@ public: const MbSNameMaker & snMaker ) : MbIntCurveParams( snMaker ) , _faces1 ( faceIndices1 ) - , _same1 ( same1 ) , _faces2 ( faceIndices2 ) + , _same1 ( same1 ) , _same2 ( same2 ) , _useCreators( true ) {} @@ -541,8 +541,8 @@ public: const MbSNameMaker & snMaker ) : MbIntCurveParams( mergeCrvs, cutCrvs, snMaker ) , _faces1 ( faceIndices1 ) - , _same1 ( false ) , _faces2 ( faceIndices2 ) + , _same1 ( false ) , _same2 ( false ) , _useCreators( false ) {} @@ -562,8 +562,8 @@ public: const MbSNameMaker & snMaker ) : MbIntCurveParams( snMaker ) , _faces1 ( faceIndices1 ) - , _same1 ( false ) , _faces2 ( faceIndices2 ) + , _same1 ( false ) , _same2 ( false ) , _useCreators( false ) {} @@ -639,21 +639,48 @@ public: protected: bool useSurfaceNormal; ///< \ru Эквидистанта согласована с нормалью к поверхности. \en Offset point is moved according to surface normal. c3d::ConstSurfaceSPtr surface; ///< \ru Поверхность кривой или подобная ей. \en Curve's surface or similar to such surface. - const MbSNameMaker & snMaker; ///< \ru Именователь кривых каркаса. \en An object defining the frame curves names. + c3d::SNameMakerSPtr snMaker; ///< \ru Именователь кривых каркаса. \en An object defining the frame curves names. public: /// \ru Конструктор по параметрам. \en Constructor by parameters. MbSpatialOffsetCurveParams( const MbVector3D & v, const MbSNameMaker & nm ) - : offsetVect ( v ) - , useFillet ( false ) - , keepRadius ( false ) - , bluntAngle ( false ) - , fromBeg ( true ) - , useSurfaceNormal( false ) - , surface ( nullptr ) - , snMaker ( nm ) + : offsetVect ( v ) + , useFillet ( false ) + , keepRadius ( false ) + , bluntAngle ( false ) + , fromBeg ( true ) + , useSurfaceNormal( false ) + , surface ( nullptr ) + , snMaker ( &nm.Duplicate() ) {} + /// \ru Конструктор по параметрам. \en Constructor by parameters. + MbSpatialOffsetCurveParams( const MbVector3D & offset, bool useFllt, bool keepRds, bool bluntAngl, bool beg, bool useNrm, c3d::ConstSurfaceSPtr surf, const MbSNameMaker & nm ) + : offsetVect ( offset ) + , useFillet ( useFllt ) + , keepRadius ( keepRds ) + , bluntAngle ( bluntAngl ) + , fromBeg ( beg ) + , useSurfaceNormal( useNrm ) + , surface ( nullptr ) + , snMaker ( &nm.Duplicate() ) + { + if ( surface != nullptr ) + SetBySurfaceNormal( useSurfaceNormal, &surface ); + } + /// \ru Конструктор копирования. \en Copy constructor. + MbSpatialOffsetCurveParams( const MbSpatialOffsetCurveParams & other ); + /// \ru Конструктор для чтения. \en Constructor for reading. + MbSpatialOffsetCurveParams( TapeInit tapeInit ); + public: + /// \ru Преобразовать элемент согласно матрице. \en Transform element by matrix. + void Transform( const MbMatrix3D & matrix ); + /// \ru поворот точкек вокруг произвольной оси \en rotate points around an arbitrary axis. + void Rotate( const MbAxis3D & axis, double angle ); + /// \ru Сдвиг точкек на произвольный вектор \en Move points on arbitrary vector. + void Move( const MbVector3D & to ); + /// \ru Проверка на равенство. \en Check if *this == other. + bool IsEqual( const MbSpatialOffsetCurveParams & other, double accuracy ) const; /// \ru Установка режима по поверхности, переносится ли эквидистантная точка согласованно с нормалью к поверхности. \en Setting the mode whether offset point is moved according to surface normal or not. void SetBySurfaceNormal( bool set, c3d::ConstSurfaceSPtr * s = nullptr ) { @@ -667,14 +694,19 @@ public: surface = nullptr; } } - /// \ru Получить поверхность. \en Get surface. + /// \ru Получить флаг согласованности с нормалью к поверхности. \en Get the surface normal according flag. bool BySurfaceNormal() const { return useSurfaceNormal; } - /// \ru Получить поверхность. \en Get surface. + /// \ru Получить поверхность. \en Get surface. const c3d::ConstSurfaceSPtr & GetSurface() const { return surface; } - /// \ru Получить ссылку на именователь. \en Get names maker reference. - const MbSNameMaker & GetNameMaker() const { return snMaker; } + /// \ru Получить ссылку на именователь. \en Get names maker reference. + const MbSNameMaker & GetNameMaker() const { return *snMaker; } + /// \ru Задать именователь. \en Set names maker. + void SetNameMaker( const MbSNameMaker & newName ) const { snMaker->SetNameMaker( newName, true ); } -OBVIOUS_PRIVATE_COPY( MbSpatialOffsetCurveParams ) + /// \ru Оператор присваивания. \en Assignment operator. + MbSpatialOffsetCurveParams & operator=( const MbSpatialOffsetCurveParams & ); + + KNOWN_OBJECTS_RW_REF_OPERATORS( MbSpatialOffsetCurveParams ) // \ru Для работы со ссылками и объектами класса. \en For working with references and objects of the class. \~ }; @@ -687,11 +719,11 @@ OBVIOUS_PRIVATE_COPY( MbSpatialOffsetCurveParams ) */ // --- struct MATH_CLASS MbSurfaceOffsetCurveParams { public: - c3d::ConstFaceSPtr face; ///< \ru Грань, на которой строится эквидистанта. \en The face on which to build the offset curve. - MbAxis3D dirAxis; ///< \ru Направление смещения с точкой приложения. \en The offset direction with a reference point. - double dist; ///< \ru Величина смещения. \en The offset distance. + c3d::ConstFaceSPtr face; ///< \ru Грань, на которой строится эквидистанта. \en The face on which to build the offset curve. + MbAxis3D dirAxis; ///< \ru Направление смещения с точкой приложения. \en The offset direction with a reference point. + double dist; ///< \ru Величина смещения. \en The offset distance. protected: - const MbSNameMaker & snMaker; ///< \ru Именователь кривых каркаса. \en An object defining the frame curves names. + c3d::SNameMakerSPtr snMaker; ///< \ru Именователь кривых каркаса. \en An object defining the frame curves names. public: /// \ru Конструктор по параметрам. \en Constructor by parameters. @@ -699,13 +731,37 @@ public: : face ( &f ) , dirAxis( a ) , dist ( d ) - , snMaker( nm ) + , snMaker( &nm.Duplicate() ) {} -public: - /// \ru Получить ссылку на именователь. \en Get names maker reference. - const MbSNameMaker & GetNameMaker() const { return snMaker; } + /// \ru Конструктор копирования. \en Copy constructor. + MbSurfaceOffsetCurveParams( const MbSurfaceOffsetCurveParams & other ); + /// \ru Конструктор для чтения. \en Constructor for reading. + MbSurfaceOffsetCurveParams( TapeInit tapeInit ); -OBVIOUS_PRIVATE_COPY( MbSurfaceOffsetCurveParams ) +public: + /// \ru Преобразовать элемент согласно матрице. \en Transform element by matrix. + void Transform( const MbMatrix3D & matrix ); + /// \ru Поворот точкек вокруг произвольной оси \en Rotate points around an arbitrary axis. + void Rotate( const MbAxis3D & axis, double angle ); + /// \ru Сдвиг точкек на произвольный вектор \en Move points on arbitrary vector. + void Move( const MbVector3D & to ); + /// \ru Проверка на равенство. \en Check if *this == other. + bool IsEqual( const MbSurfaceOffsetCurveParams & other, double accuracy ) const; + /// \ru Установка поверхности. \en Setting the surface. + void SetFace( c3d::ConstFaceSPtr * f = nullptr ) + { + if ( f != nullptr ) + face = *f; + } + /// \ru Получить ссылку на именователь. \en Get names maker reference. + const MbSNameMaker & GetNameMaker() const { return *snMaker; } + /// \ru Задать именователь. \en Set names maker. + void SetNameMaker( const MbSNameMaker & newName ) const { snMaker->SetNameMaker( newName, true ); } + + /// \ru Оператор присваивания. \en Assignment operator. + MbSurfaceOffsetCurveParams & operator=( const MbSurfaceOffsetCurveParams & ); + + KNOWN_OBJECTS_RW_REF_OPERATORS( MbSurfaceOffsetCurveParams ) // \ru Для работы со ссылками и объектами класса. \en For working with references and objects of the class. \~ }; @@ -1096,23 +1152,23 @@ public: /// \ru Конструктор по параметрам. \en Constructor by parameters. MbCornerChamferParams( size_t _index, double _distance, double _distAngle, bool _type = false ) - : index ( _index ) - , distance ( _distance ) + : distance ( _distance ) , distAngle( _distAngle ) + , index ( _index ) , type ( _type ) {} /// \ru Конструктор по умолчанию. \en Default constructor. MbCornerChamferParams() - : index ( -1 ) - , distance ( 0 ) + : distance ( 0 ) , distAngle( 0 ) + , index ( -1 ) , type ( false ) {} /// \ru Конструктор копирования. \en Copy constructor. MbCornerChamferParams(const MbCornerChamferParams & other) - : index ( other.index ) - , distance ( other.distance ) + : distance ( other.distance ) , distAngle( other.distAngle ) + , index ( other.index ) , type ( other.type ) {} /// \ru Оператор присваивания. \en Assignment operator. \~ @@ -1197,41 +1253,219 @@ public: OBVIOUS_PRIVATE_COPY( MbContourChamferParams ) }; +//------------------------------------------------------------------------------ +/** \brief \ru Параметры, определяющие положение объектов внутри поверхности и плоскости в операциях + сворачивание/разворачивание кривых. + \en Parameters determining the objects position in the surface and the plane in curve + wrap/unwrap operation. \~ + \details \ru Точка _xy плоскости XY локальной системы координат должна совпадать с точкой _uv + параметрической области UV поверхности. \n + При параметрах _angle = 0 и _sense = true наложение плоскости на поверхность + делается таким образом, что оси 'x' и 'y' плоскости соответственно совпадают с осями 'u' и 'v' поверхности. + При параметрах _angle = 0 и _sense = false наложение плоскости на поверхность делается таким образом, + что оси 'y' плоскости и 'v' поверхности совпадают, оси 'x' и 'u' направлены противоположно. + Далее, значение угла _angle показывает, насколько нужно повернуть систему координат XY плоскости + относительно её оси Z. \n + \en The point _xy of the XY plane of the local coordinate system must coincide with the point _uv of the + parametric region UV of the surface. + With parameters _angle = 0 and _sense = true the overlay of the plane on the surface matches 'x' and 'y' plane axes + to the 'u' and 'v' surface axes correspondingly. + With parameters angle = 0 and sense = false the overlay of the plane on the surface matches 'y' plane axis + to the 'v' surface axis, with 'x' and 'u' axes directed oppositely. + Then the value of 'angle' shows how much the plane coordinate system XY is turned in respect to its Z axis. \n + \ingroup Curve3D_Building_Parameters +*/ +// --- +class MATH_CLASS MbWrapValues { +private: + MbPlacement3D _place; ///< \ru Локальная система координат (ЛСК). \en The local coordinate system (LCS) of the curves. \~ + c3d::SurfaceSPtr _surface; ///< \ru Поверхность. Всегда не nullptr. \en The surface. It is always not nullptr. \~ + + MbCartPoint _xy; ///< \ru Точка привязки на плоскости XY локальной системы координат. \en The anchor point on the "XY" plane of the LCS that will be aligned with the uv point on the parametric plane of the surface. \~ + MbCartPoint _uv; ///< \ru Точка привязки в параметрической плоскости "UV" параметров поверхности. \en The anchor point in the parametric plane "UV" of the surface parameters. \~ + double _angle; ///< \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ + bool _sense; ///< \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности? \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ + bool _keepLength; ///< \ru Должны ли длины кривых на другом носителе соответствовать оригиналам? \en Should the lengths of the curves on another carrier match the originals? \~ + +public: + /** \brief \ru Конструктор по параметрам. + \en Constructor by parameters. \~ + \details \ru Конструктор по параметрам. + \en Constructor by parameters. \~ + \param[in] place - \ru Локальная система координат (ЛСК) плоскости. + \en The local coordinate system (LCS) of the plane. \~ + \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. + \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ + \param[in] surf - \ru Поверхность для разворачивания. + \en The surface to unwrap. \~ + \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. + \en The anchor UV point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ + \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. + \en Whether to save the surface copy in this parameter class. \~ + \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. + \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ + \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. + \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ + \param[in] keepLength - \ru Должны ли длины кривых на другом носителе соответствовать оригиналам. + \en Should the lengths of the curves on another carrier match the originals? \~ + */ + MbWrapValues( const MbPlacement3D & place, + const MbCartPoint & xy, + const MbSurface & surf, + const MbCartPoint & uv, + bool copySurface, + double angle, + bool sense, + bool keepLength ); + + // Конструктор копирования. + MbWrapValues( const MbWrapValues & other, bool copySurface, MbRegDuplicate * iReg ); + + /// \ru Конструктор для чтения. \en Constructor for reading. + MbWrapValues( TapeInit tapeInit ); + +private: + // Конструктор по умолчанию. Не реализован. + MbWrapValues(); + + // Конструктор копирования. Не реализован. + MbWrapValues( const MbWrapValues & other ); + +public: + /** \brief \ru Инициализация параметров. + \en Initialize parameters. \~ + \details \ru Инициализация параметров. + \en Initialize parameters. \~ + \param[in] place - \ru Локальная система координат (ЛСК) плоскости. + \en The local coordinate system (LCS) of the plane. \~ + \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. + \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ + \param[in] surf - \ru Поверхность для разворачивания. + \en The surface to unwrap. \~ + \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. + \en The anchor UV point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ + \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. + \en Whether to save the surface copy in this parameter class. \~ + \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. + \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ + \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. + \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ + \param[in] keepLength - \ru Должны ли длины кривых на другом носителе соответствовать оригиналам. + \en Should the lengths of the curves on another carrier match the originals? \~ + */ + void Init( const MbPlacement3D & place, + const MbCartPoint & xy, + const MbSurface & surf, + const MbCartPoint & uv, + bool copySurface, + double angle, + bool sense, + bool keepLength ); + + /// \ru Преобразовать поверхность согласно матрице. \en Transform the surface according to the matrix. \~ + void TransformSurface( const MbMatrix3D & matr, MbRegTransform * iReg = nullptr ); + + /// \ru Преобразовать плоскость согласно матрице. \en Transform the plane according to the matrix. \~ + void TransformPlane( const MbMatrix3D & matr ); + + /// \ru Сдвинуть поверхность вдоль вектора. \en Move the surface along a vector. \~ + void MoveSurface( const MbVector3D & to, MbRegTransform * iReg = nullptr ); + + /// \ru Сдвинуть плоскость вдоль вектора. \en Move the plane along a vector. \~ + void MovePlane( const MbVector3D & to ); + + /// \ru Повернуть поверхность вокруг оси на заданный угол. \en Rotate the surface around an axis at a given angle. \~ + void RotateSurface( const MbAxis3D & axis, double angle, MbRegTransform * iReg = nullptr ); + + /// \ru Повернуть плоскость вокруг оси на заданный угол. \en Rotate the plane around an axis at a given angle. \~ + void RotatePlane( const MbAxis3D & axis, double angle ); + + /// \ru Дать локальную систему координат. \en Get the local coordinate system. \~ + const MbPlacement3D & GetPlacement() const { return _place; } + + /// \ru Дать поверхность. \en Get the surface. \~ + const MbSurface & GetSurface( bool base = false ) const { return base? _surface->GetSurface() : *_surface; } + + /// \ru Дать точку на плоскости XY локальной системы координат. \en Get a point on the XY plane of the local coordinate system. \~ + const MbCartPoint & GetPlacePoint() const { return _xy; } + + /// \ru Дать точку в области параметров UV поверхности. \en Get a point on the parametric region UV of the surface. \~ + const MbCartPoint & GetSurfacePoint() const { return _uv; } + + /// \ru Дать угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. \en Get the angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ + double GetAngle() const { return _angle; } + + /// \ru Совпадают ли ориентации осей "X-Y" ЛСК и осей "U-V" поверхности. \en Whether the orientations of LCS "X-Y" axes and the surface "U-V" axes are same. \~ + bool IsSense() const { return _sense; } + + /// \ru Должна ли совпадать длина итоговых кривых оригинальным. \en Should the result curve length be equal to the original curve length? \~ + bool IsLengthKept() const { return _keepLength; } + + /// \ru Сравнение параметров. \en The comparison with other parameters. \~ + bool IsSame( const MbWrapValues & other, double eps ) const; + +private: + /** \brief \ru Установить поверхность. + \en Set the surface. \~ + \details \ru Установить поверхность. + \en Set the surface. \~ + \param[in] surf - \ru Устанавливаемая поверхность (заменяющая исходную). + \en The surface for set (replacing the source one). \~ + \param[in] copy - \ru Если true, будет установлена копия заданной поверхности. + \en If it is true the copy of surf will be set. \~ + \param[in] iReg - \ru Регистратор. + \en Registrator. \~ + */ + void SetSurface( MbSurface & surf, bool copy, MbRegDuplicate * iReg = nullptr ) { _surface.assign( copy ? &( static_cast( surf.Duplicate( iReg ) ) ) : &surf ); } + + KNOWN_OBJECTS_RW_REF_OPERATORS( MbWrapValues ) // \ru Для работы со ссылками и объектами класса. \en For working with references and objects of the class. \~ +}; + //------------------------------------------------------------------------------ /** \brief \ru Параметры для переноса копий двумерных кривых и точек на другой носитель. - \en Parameters for transferring copies of two-dimensional curves and points on another medium. \~ - \details \ru Точка xy плоскости XY локальной системы координат должна совпадать с точкой uv - параметрической области UV поверхности. - При параметрах angle = 0 и sense = true наложение плоскости на поверхность - делается таким образом, что оси 'xy' плоскости и 'uv' поверхности соответственно сопадают. - При параметрах angle = 0 и sense = false наложение плоскости на поверхность делается таким образом, - что оси 'y' плоскости и 'v' поверхности сопадают, оси 'x' и 'u' направлены протиположно. - Далее, значение угла angle показывает, насколько нужно повернуть систему координат XY плоскости - относительно её оси Z. \n - \en The point xy of the XY plane of the local coordinate system must coincide with the point uv of the - parametric region UV of the surface. - With parameters angle = 0 and sense = true the overlay of the plane on the surface matches 'x' and 'y' plane axes - to the 'u' and 'v' surface axes. - With parameters angle = 0 and sense = false the overlay of the plane on the surface matches 'y' plane axis - to the 'v' surface axis, with 'x' and 'u' axes directed oppositely. - Then the value of 'angle' shows how much the plane coordinate system XY is turned in respect to its Z axis. \n \~ + \en Parameters for transferring copies of two-dimensional curves and points on another carrier. \~ + \details \ru Параметры для переноса копий двумерных кривых и точек на другой носитель. + В случае периодических поверхностей необходимо указать значение _surfBreakParam. Для корректной + работы алгоритма (на данный момент это касается только операции разворачивания) необходимо разомкнуть + замкнутую поверхность. Место размыкания определяется данным параметром. Задается в долях [0, 1] от + диапазона поверхности, соответствующего параметрическому направлению (U или V, совпадает с + периодическим направлением). В случае U: + _surfBreakParam = ( U - Umin )/( Umax - Umin ), + где U - фактический U-параметр поверхности, соответствующий месту размыкания. Umin и Umax - границы + диапазона задания U-параметра поверхности. Для V-параметра аналогично. + Если значение параметра не принадлежит указанному диапазону, оно будет искусственно в него вписано + (к минимальной или максимальной границе). + Если значение этого параметра равно UNDEFINED_DBL, он не учитывается. + Для непериодических поверхностей данный параметр не играет никакой роли и может принимать любое значение. + Если поверхность периодическая одновременно по U- и V-направлению, то она будет неразворачиваемой. + В этом случае значение данного параметра так же не играет никакой роли. \n + \en Parameters for transferring copies of two-dimensional curves and points on another carrier. \~ + The parameter _surfBreakParam is necessary to be determined for periodic surfaces. In order to for the algorithm + (at the moment it touches unwrap operation only) work properly, the closed surface should be made unclosed. + The breaking place is determined by this parameter. It is set in the ratio [0, 1] of the surface range for + correspond parametric direction (either U or V, which matches the periodic direction). For U: + _surfBreakParam = ( U - Umin )/( Umax - Umin ), + where U is an actual U-parameter of the surface, correspond to the breaking place. Umin and Umax are bounds + of the surface U-range. Analogically for V-parameter. + If the parameter value is out of this range it will be automatically adjusted to it (to min or max boundary). + If this parameter is equal to UNDEFINED_DBL it is not take into account at all. + In case of non-periodic surfaces, the parameter does not play any role and can take any value. + In case of the surface is periodic both U- and V-direction, it is undevelopable. The parameter does not + play any role, too. \n \~ \ingroup Curve3D_Building_Parameters */ // --- class MATH_CLASS MbCurvesWrappingParams : public MbPrecision { private: - c3d::ConstPlaneCurvesSPtrVector _curves; ///< \ru Двумерные кривые, копии которых будут перенесены на другой носитель. \en 2d curves, copies of which will be transferred to another medium. \~ - c3d::ParamPointsVector _points; ///< \ru Двумерные точки, копии которых будут перенесены на другой носитель. \en 2d points, copies of which will be transferred to another medium. \~ - c3d::SurfaceSPtr _surface; ///< \ru Поверхность. \en The surface. \~ + c3d::ConstPlaneCurvesSPtrVector _curves; ///< \ru Двумерные кривые, копии которых будут перенесены на другой носитель. \en Two-dimensional curves, copies of which will be transferred to another carrier. \~ + c3d::ParamPointsVector _points; ///< \ru Двумерные точки, копии которых будут перенесены на другой носитель. \en Two-dimensional points, copies of which will be transferred to another carrier. \~ + MbWrapValues _wrpValues; ///< \ru Параметры операции сворачивания/разворачивания. \en The parameters of wrap/unwrap operation. c3d::SNameMakerSPtr _snMaker; ///< \ru Именователь с версией операции. Всегда не nullptr. \en Names maker with operation version. It cannot be nullptr. - MbPlacement3D _place; ///< \ru Локальная система координат (ЛСК). \en The local coordinate system (LCS) of the curves. \~ - MbCartPoint _xy; ///< \ru Точка привязки на плоскости XY локальной системы координат. \en The anchor point on the "XY" plane of the LCS that will be aligned with the uv point on the parametric plane of the surface. \~ - MbCartPoint _uv; ///< \ru Точка привязки в параметрической плоскости "UV" параметров поверхности. \en The anchor point in the parametric plane "UV" of the surface parameters. \~ - double _angle; ///< \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ - bool _sense; ///< \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности? \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ - bool _keepLength; ///< \ru Должны ли длины кривых на другом носителе соответствовать оригиналам? \en Should the lengths of the curves on another medium match the originals? \~ - bool _uSeamStitch; ///< \ru Нужно ли сдвинуть кривые, попавшие краем на шов umax. \en Whether to shift curves with one end on umax seam. \~ + double _surfBreakParam; ///< \ru Задает место резки периодической поверхности. Актуален только для разворачивания. \en It sets the place, where the periodic surface is to be cut. It is used for unwrap algorithm only. \~ + bool _cutByBounds; ///< \ru Нужно ли обрезать полученные кривые по границам поверхности? Актуален только для сворачивания. \en Whether the result curves to be cut with the surface bounds? It is used for wrap algorithm only. \~ + bool _isWrap; ///< \ru Тип операции: сворачивание (true), разворачивание (false). \en Operation type: wrap (true), unwrap (false). \~ + bool _uSeamStitch; ///< \ru Нужно ли сдвинуть кривые, попавшие краем на шов umax. \en Whether to shift curves with one end on umax seam.\~ private: /** \brief \ru Конструктор по-умолчанию. Не реализован. @@ -1245,67 +1479,50 @@ private: \en Constructor with no curves.\~ \details \ru Конструктор без кривых. \en Constructor with no curves.\~ - \param[in] place - \ru Локальная система координат (ЛСК) плоскости. - \en The local coordinate system (LCS) of the plane. \~ - \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. - \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ - \param[in] surface - \ru Поверхность для сворачивания/разворачивания. - \en The surface to wrap to/unwrap from. \~ - \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. - \en The anchor uv point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ - \param[in] operNames - \ru Именователь с версией операции. - \en Names maker with operation version. \~ - \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. - \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ - \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. - \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ - \param[in] keepLength - \ru Должны ли длины кривых на другом носителе соответствовать оригиналам. - \en Should the lengths of the curves on another medium match the originals?\~ - \param[in] accuracy - \ru Точность построения. - \en The accuracy. \~ - \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. - \en Whether to save the surface copy in this parameter class. \~ + \param[in] vals - \ru Параметры операции сворачивания/разворачивания. + \en The parameters of wrap/unwrap operation.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] accuracy - \ru Точность построения. + \en The accuracy. \~ */ - MbCurvesWrappingParams( const MbPlacement3D & place, - const MbCartPoint & xy, - const MbSurface & surface, - const MbCartPoint & uv, - const MbSNameMaker & operNames, - double angle, - bool sense, - bool keepLength, - double accuracy, - bool copySurface ); + MbCurvesWrappingParams( const MbWrapValues & vals, + const MbSNameMaker & operNames, + double surfBreakParam, + bool cutByBounds ); + public: /** \brief \ru Конструктор по двумерным кривым. \en Constructor by two-dimension curves.\~ \details \ru Конструктор по двумерным кривым. \en Constructor by two-dimension curves.\~ - \param[in] curves - \ru 2d кривые, копии которых будут свёрнуты/развёрнуты. - \en 2d curves, copies of which will be wrapped/unwrapped. \~ - \param[in] place - \ru Локальная система координат (ЛСК) плоскости. - \en The local coordinate system (LCS) of the plane. \~ - \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. - \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ - \param[in] surface - \ru Поверхность для сворачивания/разворачивания. - \en The surface to wrap to/unwrap from. \~ - \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. - \en The anchor uv point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ - \param[in] operNames - \ru Именователь с версией операции. - \en Names maker with operation version. \~ - \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. - \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ - \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. - \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ - \param[in] keepLength - \ru Должны ли длины кривых на другом носителе соответствовать оригиналам. - \en Should the lengths of the curves on another medium match the originals?\~ - \param[in] accuracy - \ru Точность построения. - \en The accuracy. \~ - \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. - \en Whether to save the curves copies in this parameter class. \~ - \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. - \en Whether to save the surface copy in this parameter class. \~ + \param[in] curves - \ru Двумерные кривые, копии которых будут свёрнуты/развёрнуты. + \en Two-dimensional curves, copies of which will be wrapped/unwrapped. \~ + \param[in] place - \ru Локальная система координат (ЛСК) плоскости. + \en The local coordinate system (LCS) of the plane. \~ + \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. + \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ + \param[in] surface - \ru Поверхность для сворачивания/разворачивания. + \en The surface to wrap to/unwrap from. \~ + \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. + \en The anchor uv point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. + \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ + \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. + \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ + \param[in] keepLength - \ru Должны ли длины кривых на другом носителе соответствовать оригиналам. + \en Should the lengths of the curves on another carrier match the originals?\~ + \param[in] accuracy - \ru Точность построения. + \en The accuracy. \~ + \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. + \en Whether to save the curves copies in this parameter class. \~ + \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. + \en Whether to save the surface copy in this parameter class. \~ + \deprecated Внимание! Инициализируется всегда для разворачивания. Не будет работать для сворачивания. */ + DEPRECATE_DECLARE_REPLACE( with MbWrapValues ) MbCurvesWrappingParams( const c3d::ConstPlaneCurvesSPtrVector & curves, const MbPlacement3D & place, const MbCartPoint & xy, @@ -1323,31 +1540,33 @@ public: \en Constructor by spatial curves.\~ \details \ru Конструктор по пространственным кривым. \en Constructor by spatial curves.\~ - \param[in] curves - \ru 3д кривые, копии которых будут свёрнуты/развёрнуты. Ожидается, что внутри -- 2д кривые на поверхности или плоскости. - \en 3d curves, copies of which will be wrapped/unwrapped. It is expected that there are 2d curves on a surface or a plane inside.\~ - \param[in] place - \ru Локальная система координат (ЛСК) плоскости. - \en The local coordinate system (LCS) of the plane. \~ - \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. - \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ - \param[in] surface - \ru Поверхность для сворачивания/разворачивания. - \en The surface to wrap to/unwrap from. \~ - \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. - \en The anchor uv point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ - \param[in] operNames - \ru Именователь с версией операции. - \en Names maker with operation version. \~ - \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. - \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ - \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. - \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ - \param[in] keepLength - \ru Должны ли длины кривых на другом носителе соответствовать оригиналам. - \en Should the lengths of the curves on another medium match the originals?\~ - \param[in] accuracy - \ru Точность построения. - \en The accuracy. \~ - \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. - \en Whether to save the curves copies in this parameter class. \~ - \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. - \en Whether to save the surface copy in this parameter class. \~ + \param[in] curves - \ru Трёхмерные кривые, копии которых будут свёрнуты/развёрнуты. Ожидается, что внутри -- двумерные кривые на поверхности или плоскости. + \en Three-dimension curves, copies of which will be wrapped/unwrapped. It is expected that there are two-dimension curves on a surface or a plane inside.\~ + \param[in] place - \ru Локальная система координат (ЛСК) плоскости. + \en The local coordinate system (LCS) of the plane. \~ + \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. + \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ + \param[in] surface - \ru Поверхность для сворачивания/разворачивания. + \en The surface to wrap to/unwrap from. \~ + \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. + \en The anchor uv point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. + \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ + \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. + \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ + \param[in] keepLength - \ru Должны ли длины кривых на другом носителе соответствовать оригиналам. + \en Should the lengths of the curves on another carrier match the originals?\~ + \param[in] accuracy - \ru Точность построения. + \en The accuracy. \~ + \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. + \en Whether to save the curves copies in this parameter class. \~ + \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. + \en Whether to save the surface copy in this parameter class. \~ + \deprecated Внимание! Инициализируется всегда для разворачивания. Не будет работать для сворачивания. */ + DEPRECATE_DECLARE_REPLACE( with MbWrapValues ) MbCurvesWrappingParams( const c3d::ConstSpaceCurvesSPtrVector & curves, const MbPlacement3D & place, const MbCartPoint & xy, @@ -1365,27 +1584,29 @@ public: \en Constructor by points.\~ \details \ru Конструктор по точкам. \en Constructor by points.\~ - \param[in] points - \ru Двумерные точки, которые будут перенесены на новый носитель. - \en 2d-points to be translated to a new medium. \~ - \param[in] place - \ru Локальная система координат (ЛСК) плоскости. - \en The local coordinate system (LCS) of the plane. \~ - \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. - \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ - \param[in] surface - \ru Поверхность для сворачивания/разворачивания. - \en The surface to wrap to/unwrap from. \~ - \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. - \en The anchor uv point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ - \param[in] operNames - \ru Именователь с версией операции. - \en Names maker with operation version. \~ - \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. - \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ - \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. - \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ - \param[in] accuracy - \ru Точность построения. - \en The accuracy. \~ - \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. + \param[in] points - \ru Двумерные точки, которые будут перенесены на новый носитель. + \en Two-dimension points to be translated to a new carrier. \~ + \param[in] place - \ru Локальная система координат (ЛСК) плоскости. + \en The local coordinate system (LCS) of the plane. \~ + \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. + \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ + \param[in] surface - \ru Поверхность для сворачивания/разворачивания. + \en The surface to wrap to/unwrap from. \~ + \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. + \en The anchor uv point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. + \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ + \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. + \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ + \param[in] accuracy - \ru Точность построения. + \en The accuracy. \~ + \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. \en Whether to save the surface copy in this parameter class. \~ + \deprecated Внимание! Инициализируется всегда для разворачивания. Не будет работать для сворачивания. */ + DEPRECATE_DECLARE_REPLACE( with MbWrapValues ) MbCurvesWrappingParams( const c3d::ParamPointsVector & points, const MbPlacement3D & place, const MbCartPoint & xy, @@ -1401,33 +1622,35 @@ public: \en Constructor by two-dimension curves and points.\~ \details \ru Конструктор по двумерным кривым и точкам. \en Constructor by two-dimension curves and points.\~ - \param[in] curves - \ru 2d кривые, копии которых будут свёрнуты/развёрнуты. - \en 2d curves, copies of which will be wrapped/unwrapped. \~ - \param[in] points - \ru Двумерные точки, которые будут перенесены на новый носитель. - \en 2d-points to be translated to a new medium. \~ - \param[in] place - \ru Локальная система координат (ЛСК) плоскости. - \en The local coordinate system (LCS) of the plane. \~ - \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. - \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ - \param[in] surface - \ru Поверхность для сворачивания/разворачивания. - \en The surface to wrap to/unwrap from. \~ - \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. - \en The anchor uv point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ - \param[in] operNames - \ru Именователь с версией операции. - \en Names maker with operation version. \~ - \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. - \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ - \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. - \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ - \param[in] keepLength - \ru Должны ли длины кривых на другом носителе соответствовать оригиналам. - \en Should the lengths of the curves on another medium match the originals?\~ - \param[in] accuracy - \ru Точность построения. - \en The accuracy. \~ - \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. - \en Whether to save the curves copies in this parameter class. \~ - \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. + \param[in] curves - \ru Двумерные кривые, копии которых будут свёрнуты/развёрнуты. + \en Two-dimensional curves, copies of which will be wrapped/unwrapped. \~ + \param[in] points - \ru Двумерные точки, которые будут перенесены на новый носитель. + \en Two-dimension points to be translated to a new carrier. \~ + \param[in] place - \ru Локальная система координат (ЛСК) плоскости. + \en The local coordinate system (LCS) of the plane. \~ + \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. + \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ + \param[in] surface - \ru Поверхность для сворачивания/разворачивания. + \en The surface to wrap to/unwrap from. \~ + \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. + \en The anchor uv point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. + \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ + \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. + \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ + \param[in] keepLength - \ru Должны ли длины кривых на другом носителе соответствовать оригиналам. + \en Should the lengths of the curves on another carrier match the originals?\~ + \param[in] accuracy - \ru Точность построения. + \en The accuracy. \~ + \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. + \en Whether to save the curves copies in this parameter class. \~ + \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. \en Whether to save the surface copy in this parameter class. \~ + \deprecated Внимание! Инициализируется всегда для разворачивания. Не будет работать для сворачивания. */ + DEPRECATE_DECLARE_REPLACE( with MbWrapValues ) MbCurvesWrappingParams( const c3d::ConstPlaneCurvesSPtrVector & curves, const c3d::ParamPointsVector & points, const MbPlacement3D & place, @@ -1442,37 +1665,39 @@ public: bool copyCurves, bool copySurface ); - /** \brief \ru Конструктор по пространственным кривым и (2d) точкам. - \en Constructor by spatial curves and (2d) points.\~ - \details \ru Конструктор по пространственным кривым и (2d) точкам. - \en Constructor by spatial curves and (2d) points.\~ - \param[in] curves - \ru 3д кривые, копии которых будут свёрнуты/развёрнуты. - \en 3d curves, copies of which will be wrapped/unwrapped.\~ - \param[in] points - \ru Двумерные точки, которые будут перенесены на новый носитель. - \en 2d-points to be translated to a new medium. \~ - \param[in] place - \ru Локальная система координат (ЛСК) плоскости. - \en The local coordinate system (LCS) of the plane. \~ - \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. - \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ - \param[in] surface - \ru Поверхность для сворачивания/разворачивания. - \en The surface to wrap to/unwrap from. \~ - \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. - \en The anchor uv point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ - \param[in] operNames - \ru Именователь с версией операции. - \en Names maker with operation version. \~ - \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. - \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ - \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. - \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ - \param[in] keepLength - \ru Должны ли длины кривых на другом носителе соответствовать оригиналам. - \en Should the lengths of the curves on another medium match the originals?\~ - \param[in] accuracy - \ru Точность построения. - \en The accuracy. \~ - \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. - \en Whether to save the curves copies in this parameter class. \~ - \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. + /** \brief \ru Конструктор по пространственным кривым и (двумерным) точкам. + \en Constructor by spatial curves and (two-dimension) points.\~ + \details \ru Конструктор по пространственным кривым и (двумерным) точкам. + \en Constructor by spatial curves and (two-dimension) points.\~ + \param[in] curves - \ru Пространственные кривые, копии которых будут свёрнуты/развёрнуты. + \en Spatial curves, copies of which will be wrapped/unwrapped.\~ + \param[in] points - \ru Двумерные точки, которые будут перенесены на новый носитель. + \en Two-dimension points to be translated to a new carrier. \~ + \param[in] place - \ru Локальная система координат (ЛСК) плоскости. + \en The local coordinate system (LCS) of the plane. \~ + \param[in] xy - \ru Точка привязки на плоскости, которая будет привязана к uv-точке на поверхности. + \en The anchor point on the plane that will be aligned with the uv point on the parametric plane of the surface. \~ + \param[in] surface - \ru Поверхность для сворачивания/разворачивания. + \en The surface to wrap to/unwrap from. \~ + \param[in] uv - \ru Точка привязки на поверхности в параметрической плоскости "UV". Будет привязана к xy-точке на плоскости. + \en The anchor uv point on the parametric plane of the surface that will be aligned with the xy point on the plane.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] angle - \ru Угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. + \en The angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ + \param[in] sense - \ru Совпадают ли направления оси "X" ЛСК и оси "U" поверхности. + \en Whether the directions of the "X" axis of the LSC and the "U" axis of the surface coincide? \~ + \param[in] keepLength - \ru Должны ли длины кривых на другом носителе соответствовать оригиналам. + \en Should the lengths of the curves on another carrier match the originals?\~ + \param[in] accuracy - \ru Точность построения. + \en The accuracy. \~ + \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. + \en Whether to save the curves copies in this parameter class. \~ + \param[in] copySurface - \ru Сохранить ли в классе параметров копию поверхности. \en Whether to save the surface copy in this parameter class. \~ + \deprecated Внимание! Инициализируется всегда для разворачивания. Не будет работать для сворачивания. */ + DEPRECATE_DECLARE_REPLACE( with MbWrapValues ) MbCurvesWrappingParams( const c3d::ConstSpaceCurvesSPtrVector & curves, const c3d::ParamPointsVector & points, const MbPlacement3D & place, @@ -1487,10 +1712,106 @@ public: bool copyCurves, bool copySurface ); + /** \brief \ru Конструктор по параметрам для сворачивания. + \en Constructor by parameters for wrapping. \~ + \details \ru Конструктор по параметрам для сворачивания. + \en Constructor by parameters for wrapping. \~ + \param[in] curves - \ru Двумерные кривые, копии которых будут свёрнуты. + \en Two-dimensional curves, copies of which will be wrapped. \~ + \param[in] points - \ru Двумерные точки, которые будут свёрнуты. + \en Two-dimension points to be wrapped. \~ + \param[in] vals - \ru Параметры операции сворачивания. + \en The parameters of wrap operation.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] cutByBounds - \ru Нужно ли обрезать полученные кривые по границам поверхности? + \en Whether the result curves to be cut with the surface bounds? \~ + \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. + \en Whether to save the curves copies in this parameter class. \~ + */ + MbCurvesWrappingParams( const c3d::ConstPlaneCurvesSPtrVector & curves, + const c3d::ParamPointsVector & points, + const MbWrapValues & vals, + const MbSNameMaker & operNames, + bool cutByBounds, + bool copyCurves ); + + /** \brief \ru Конструктор по параметрам для сворачивания. + \en Constructor by parameters for wrapping. \~ + \details \ru Конструктор по параметрам для сворачивания. + \en Constructor by parameters for wrapping. \~ + \param[in] curves - \ru Трёхмерные кривые, копии которых будут свёрнуты. Ожидается, что внутри -- двумерные кривые на поверхности или плоскости. + \en Three-dimension curves, copies of which will be wrapped. It is expected that there are two-dimension curves on a surface or a plane inside.\~ + \param[in] points - \ru Двумерные точки, которые будут свёрнуты. + \en Two-dimension points to be wrapped. \~ + \param[in] vals - \ru Параметры операции сворачивания. + \en The parameters of wrap operation.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] cutByBounds - \ru Нужно ли обрезать полученные кривые по границам поверхности? + \en Whether the result curves to be cut with the surface bounds? \~ + \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. + \en Whether to save the curves copies in this parameter class. \~ + */ + MbCurvesWrappingParams( const c3d::ConstSpaceCurvesSPtrVector & curves, + const c3d::ParamPointsVector & points, + const MbWrapValues & vals, + const MbSNameMaker & operNames, + bool cutByBounds, + bool copyCurves ); + + /** \brief \ru Конструктор по параметрам для разворачивания. + \en Constructor by parameters for unwrapping. \~ + \details \ru Конструктор по параметрам для разворачивания. + \en Constructor by parameters for unwrapping. \~ + \param[in] curves - \ru Двумерные кривые, копии которых будут развёрнуты. + \en Two-dimensional curves, copies of which will be unwrapped. \~ + \param[in] points - \ru Двумерные точки, которые будут перенесены на новый носитель. + \en Two-dimension points to be translated to a new carrier. \~ + \param[in] vals - \ru Параметры операции разворачивания. + \en The parameters of unwrap operation.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] surfBreakParam - \ru Место резки периодической поверхности. + \en The place, where the periodic surface is to be cut. \~ + \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. + \en Whether to save the curves copies in this parameter class. \~ + */ + MbCurvesWrappingParams( const c3d::ConstPlaneCurvesSPtrVector & curves, + const c3d::ParamPointsVector & points, + const MbWrapValues & vals, + const MbSNameMaker & operNames, + double surfBreakParam, + bool copyCurves ); + + /** \brief \ru Конструктор по параметрам для разворачивания. + \en Constructor by parameters for unwrapping. \~ + \details \ru Конструктор по параметрам для разворачивания. + \en Constructor by parameters for unwrapping. \~ + \param[in] curves - \ru Трёхмерные кривые, копии которых будут развёрнуты. Ожидается, что внутри -- двумерные кривые на поверхности или плоскости. + \en Three-dimension curves, copies of which will be unwrapped. It is expected that there are two-dimension curves on a surface or a plane inside.\~ + \param[in] points - \ru Двумерные точки, которые будут перенесены на новый носитель. + \en Two-dimension points to be translated to a new carrier. \~ + \param[in] vals - \ru Параметры операции разворачивания. + \en The parameters of unwrap operation.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] surfBreakParam - \ru Место резки периодической поверхности. + \en The place, where the periodic surface is to be cut. \~ + \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. + \en Whether to save the curves copies in this parameter class. \~ + */ + MbCurvesWrappingParams( const c3d::ConstSpaceCurvesSPtrVector & curves, + const c3d::ParamPointsVector & points, + const MbWrapValues & vals, + const MbSNameMaker & operNames, + double surfBreakParam, + bool copyCurves ); + /** \brief \ru Конструктор копирования. \en Copy constructor.\~ - \details \ru Конструктор копирования. - \en Copy constructor.\~ + \details \ru Конструктор копирования. Старые кривые и точки не выбрасываются (новые добавляются поверх). + \en Copy constructor. Previous curves and points are not eliminated. New ones are added on top of existing. \~ \param[in] copyCurves - \ru Создать копии кривых. \en Create copies of the curves. \~ \param[in] copySurface - \ru Создать копию поверхности. @@ -1503,6 +1824,56 @@ public: ~MbCurvesWrappingParams() {} public: + /** \brief \ru Инициализация параметров для алгоритма сворачивания. + \en Initialize parameters for wrapping algorithm. \~ + \details \ru Инициализация параметров для алгоритма сворачивания. + \en Initialize parameters for wrapping algorithm. \~ + \param[in] curves - \ru Кривые, копии которых будут свёрнуты. + \en Curves, copies of which will be wrapped. \~ + \param[in] points - \ru Двумерные точки, которые будут свёрнуты. + \en Two-dimension points to be wrapped. \~ + \param[in] vals - \ru Параметры операции сворачивания. + \en The parameters of wrap operation.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] cutByBounds - \ru Нужно ли обрезать полученные кривые по границам поверхности? + \en Whether the result curves to be cut with the surface bounds? \~ + \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. + \en Whether to save the curves copies in this parameter class. \~ + */ + template // c3d::ConstPlaneCurvesSPtrVector, c3d::ConstSpaceCurvesSPtrVector + void InitWrap( const CurvesVector & curves, + const c3d::ParamPointsVector & points, + const MbWrapValues & vals, + const MbSNameMaker & operNames, + bool cutByBounds, + bool copyCurves ); + + /** \brief \ru Инициализация параметров для алгоритма разворачивания. + \en Initialize parameters for unwrapping algorithm. \~ + \details \ru Инициализация параметров для алгоритма разворачивания. + \en Initialize parameters for unwrapping algorithm. \~ + \param[in] curves - \ru Кривые, копии которых будут развёрнуты. + \en Curves, copies of which will be unwrapped. \~ + \param[in] points - \ru Двумерные точки, которые будут развёрнуты. + \en Two-dimension points to be unwrapped. \~ + \param[in] vals - \ru Параметры операции разворачивания. + \en The parameters of unwrap operation.\~ + \param[in] operNames - \ru Именователь с версией операции. + \en Names maker with operation version. \~ + \param[in] surfBreakParam - \ru Место резки периодической поверхности. + \en The place, where the periodic surface is to be cut. \~ + \param[in] copyCurves - \ru Сохранить ли в этом классе параметров копии кривых. + \en Whether to save the curves copies in this parameter class. \~ + */ + template // c3d::ConstPlaneCurvesSPtrVector, c3d::ConstSpaceCurvesSPtrVector + void InitUnwrap( const CurvesVector & curves, + const c3d::ParamPointsVector & points, + const MbWrapValues & vals, + const MbSNameMaker & operNames, + double surfBreakParam, + bool copyCurves ); + /// \ru Дать двумерные кривые. \en Get two-dimensional curves. \~ const c3d::ConstPlaneCurvesSPtrVector & GetCurves() const { return _curves; } /// \ru Дать количество кривых. \en Get two-dimensional curves count. \~ @@ -1513,112 +1884,37 @@ public: /// \ru Дать количество точек. \en Get points count. \~ size_t GetPointsCount() const { return _points.size(); } - /// \ru Заменить двумерную кривую. \en Set two-dimensional curve by index. \~ - void SetCurve( size_t i, const MbCurve & c, bool copy ); - /// \ru Заменить двумерную кривую. \en Set two-dimensional curve by index. \~ - void SetCurve( size_t i, MbCurve * c, bool copy ); - /// \ru Дать локальную систему координат. \en Get the local coordinate system. \~ - const MbPlacement3D & GetPlacement() const { return _place; } - /// \ru Установить локальную систему координат. \en Set the local coordinate system. \~ - void SetPlacement( const MbPlacement3D & p ) { _place = p; } - /// \ru Дать локальную систему координат. \en Get the local coordinate system. \~ - MbPlacement3D & SetPlacement() { return _place; } - /// \ru Дать точку на плоскости XY локальной системы координат. \en Get a point on the "XY" plane of the LCS that will be aligned with the uv point on the parametric plane of the surface. \~ - const MbCartPoint & GetPlacePoint() const { return _xy; } - /// \ru Установить точку на плоскости XY локальной системы координат. \en Set a point on the "XY" plane of the LCS that will be aligned with the uv point on the parametric plane of the surface. \~ - void SetPlacePoint( const MbCartPoint & p ) { _xy = p; } + /// \ru Получить параметры операции. \en Get an operation parameters. \~ + const MbWrapValues & GetParamValues() const { return _wrpValues; } - /** \brief \ru Дать поверхность. - \en Get the surface. \~ - \details \ru Дать поверхность. - \en Get the surface. \~ - \param[in] base - \ru Если true, будет выдаваться базовая поверхность. - \en If it is true the base surface will be returned. \~ - */ - const MbSurface & GetSurface( bool base = false ) const; + /// \ru Изменить параметры операции. \en Modify an operation parameters. \~ + MbWrapValues & SetParamValues() { return _wrpValues; } - /** \brief \ru Установить поверхность. - \en Set the surface. \~ - \details \ru Установить поверхность. - \en Set the surface. \~ - \param[in] surf - \ru Устанавливаемая поверхность (заменяющая исходную). - \en The surface for set (replacing the source one). \~ - \param[in] copy - \ru Если true, будет установлена копия заданной поверхности. - \en If it is true the copy of surf will be set. \~ - \param[in] iReg - \ru Регистратор. - \en Registrator. \~ - */ - void SetSurface( MbSurface & surf, bool copy, MbRegDuplicate * iReg = nullptr ) { _surface.assign( copy? &(static_cast(surf.Duplicate(iReg))) : &surf ); } - /// \ru Дать поверхность. \en Get the surface. \~ - MbSurface & SetSurface() { return *_surface; } - /// \ru Установить поверхность. \en Set the surface. \~ - DEPRECATE_DECLARE_REPLACE( SetSurface ) - void SetSurfacePtr( const c3d::ConstSurfaceSPtr & surf ); + /// \ru Вернуть тип операции: сворачивание (true), разворачивание (false)? \en Return the operation type: wrap (true), unwrap (false). \~ + bool IsWrap() const { return _isWrap; } - /// \ru Дать точку в области параметров поверхности. \en Get a point on the parametric plane "UV" of the surface corresponding to the point xy on the plane. \~ - const MbCartPoint & GetSurfacePoint() const { return _uv; } - /// \ru Установить точку в области параметров поверхности. \en Set a point on the parametric plane "UV" of the surface corresponding to the point xy on the plane. \~ - void SetSurfacePoint( const MbCartPoint & p ) { _uv = p; } - - /// \ru Дать угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. \en Get the angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ - double GetAngle() const { return _angle; } - /// \ru Установить угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. \en Set the angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ - void SetAngle( double a ) { _angle = a; } - /// \ru Совпадают ли ориентации осей "X-Y" ЛСК и осей "U-V" поверхности. \en Whether the orientations of LCS "X-Y" axes and the surface "U-V" axes are same. \~ - bool IsSense() const { return _sense; } - /// \ru Установить флаг совпадения направления оси "X" ЛСК и оси "U" поверхности. \en Set the coincidence of the directions of the "X" axis of the LSC and the "U" axis of the surface. \~ - void SetSense( bool s ) { _sense = s; } - /// \ru Должна ли совпадать длина итоговых кривых оригинальным. \en Should the result curve length be equal to the original curve length? \~ - bool IsEquals() const { return _keepLength; } - /// \ru Установить требование совпадения длины кривых в плоскости и на поверхности? \en Set the curves length correspondence to the originals on the surface? \~ - void SetEquals( bool e ) { _keepLength = e; } - /// \ru Дать точность построения. \en Get an accuracy. \~ - double GetAccuracy() const { return GetPrecision(); } - /// \ru Установить точность построения. \en Set an accuracy. \~ - void SetAccuracy( double acc ) { SetPrecision( acc ); } - /// \ru Версия алгоритма. \en The version. \~ - VERSION GetVersion() const { return _snMaker->GetMathVersion(); } - /// \ru Установить версию алгоритма. \en Set the algorithm version. \~ - void SetVersion( VERSION ver ) { _snMaker->SetMathVersion( ver ); } + /// \ru Нужно ли обрезать полученные кривые по границам поверхности? \en Whether the result curves to be cut with the surface bounds?. \~ + bool IsBoundsCut() const { return _cutByBounds; } /// \ru Получить именователь. \en Get names maker. const MbSNameMaker & GetNameMaker() const { return *_snMaker; } - /// \ru Задать именователь. \en Set names maker. - void SetNameMaker( const MbSNameMaker & newOperName ) { _snMaker->SetNameMaker( newOperName, true ); } - - /// \ru Проверка на валидность: например поверхность не null и часть кривых не null. \en The validity check: e.g. whether surface is not null and some of the curves are not null. \~ - bool IsValid () const; + /// \ru Дать параметр (в долях [0, 1]) поверхности, соответствующий ее месту резки. \en Return the parameter (in ratio) of the surface, where the periodic surface is to be cut. \~ + double GetSurfaceBreakingParam() const { return _surfBreakParam; } /// \ru Сравнение параметров. \en The comparison with other parameters. \~ bool IsSame ( const MbCurvesWrappingParams & other, double accuracy ) const; /// \ru Сравнение параметров. \en The comparison with other parameters. \~ bool IsSimilar( const MbCurvesWrappingParams & other ) const; - /** \brief \ru Нужно ли сдвинуть кривые, попавшие одним краем на шов Umax. - \en Whether to shift curves with one end on Umax seam.\~ - \details \ru Нужно ли сдвинуть кривые, попавшие краем на шов Umax. Если кривая попадает одним краем на шов Umax, - а другим не попадает ни на Umax, ни на Umin, то сдвинуть эту кривую на Umax-Umin. Это упрощённая - стыковка кривых, которые в 3д соединяются краями на шве, но в 2д разнесены на период. При включении - этого флага на развёртке они также будут стыковаться. - \en Whether to shift curves with one end on Umax seam. If one curve end is on the Umax seam and the other - is neither on Umax nor Umin, then shift the curve for Umax-Umin. This is a simplified stitching of - curves which have connected edges in 3d on the seam, but in 2d are spaced apart on a period. - If this flag is enabled, those unwrapped curves are alse connected. \~ - */ - bool GetUSeamStitch() const { return _uSeamStitch; } - /** \brief \ru Нужно ли сдвинуть кривые, попавшие одним краем на шов Umax. - \en Whether to shift curves with one end on Umax seam.\~ - \details \ru Нужно ли сдвинуть кривые, попавшие краем на шов Umax. Если кривая попадает одним краем на шов Umax, - а другим не попадает ни на Umax, ни на Umin, то сдвинуть эту кривую на Umax-Umin. Это упрощённая - стыковка кривых, которые в 3д соединяются краями на шве, но в 2д разнесены на период. При включении - этого флага на развёртке они также будут стыковаться. - \en Whether to shift curves with one end on Umax seam. If one curve end is on the Umax seam and the other - is neither on Umax nor Umin, then shift the curve for Umax-Umin. This is a simplified stitching of - curves which have connected edges in 3d on the seam, but in 2d are spaced apart on a period. - If this flag is enabled, those unwrapped curves are alse connected. \~ - */ - void SetUSeamStitch( bool s ) { _uSeamStitch = s; } + /// \ru Преобразовать объект согласно матрице. \en Transform an object according to the matrix. \~ + void Transform( const MbMatrix3D & matr, MbRegTransform * iReg = nullptr ); + + /// \ru Сдвинуть объект вдоль вектора. \en Move an object along a vector. \~ + void Move( const MbVector3D & to, MbRegTransform * iReg = nullptr ); + + /// \ru Повернуть объект вокруг оси на заданный угол. \en Rotate an object around an axis at a given angle. \~ + void Rotate( const MbAxis3D & axis, double angle, MbRegTransform * iReg = nullptr ); /** \brief \ru Создать копию текущих параметров. \en Make a copy of current parameters.\~ @@ -1644,19 +1940,134 @@ public: \en Object to be copied. \~ \param[in] copyCurves - \ru Создать копии кривых. \en Create copies of the curves. \~ - \param[in] copySurface - \ru Создать копию поверхности. - \en Create a copy of the surface. \~ \param[in] iReg - \ru Регистратор. \en Registrator. \~ */ void SetEqual( const MbCurvesWrappingParams & other, bool copyCurves, - bool copySurface, MbRegDuplicate * iReg = nullptr ); + /// \ru Дать локальную систему координат. \en Get the local coordinate system. \~ + DEPRECATE_DECLARE_REPLACE( method of the class MbWrapValues ) + const MbPlacement3D & GetPlacement() const { return _wrpValues.GetPlacement(); } + /// \ru Установить локальную систему координат. \en Set the local coordinate system. \~ + DEPRECATE_DECLARE + void SetPlacement( const MbPlacement3D & p ); + /// \ru Дать локальную систему координат. \en Get the local coordinate system. \~ + DEPRECATE_DECLARE + MbPlacement3D & SetPlacement() { return const_cast( _wrpValues.GetPlacement() ); } + /// \ru Дать точку на плоскости XY локальной системы координат. \en Get a point on the "XY" plane of the LCS that will be aligned with the uv point on the parametric plane of the surface. \~ + DEPRECATE_DECLARE_REPLACE( method of the class MbWrapValues ) + const MbCartPoint & GetPlacePoint() const { return _wrpValues.GetPlacePoint(); } + /// \ru Установить точку на плоскости XY локальной системы координат. \en Set a point on the "XY" plane of the LCS that will be aligned with the uv point on the parametric plane of the surface. \~ + DEPRECATE_DECLARE + void SetPlacePoint( const MbCartPoint & p ); + /** \brief \ru Дать поверхность. + \en Get the surface. \~ + \details \ru Дать поверхность. + \en Get the surface. \~ + \param[in] base - \ru Если true, будет выдаваться базовая поверхность. + \en If it is true the base surface will be returned. \~ + */ + DEPRECATE_DECLARE_REPLACE( method of the class MbWrapValues ) + const MbSurface & GetSurface( bool base = false ) const { return _wrpValues.GetSurface( base ); }; + + /** \brief \ru Установить поверхность. + \en Set the surface. \~ + \details \ru Установить поверхность. + \en Set the surface. \~ + \param[in] surf - \ru Устанавливаемая поверхность (заменяющая исходную). + \en The surface for set (replacing the source one). \~ + \param[in] copy - \ru Если true, будет установлена копия заданной поверхности. + \en If it is true the copy of surf will be set. \~ + \param[in] iReg - \ru Регистратор. + \en Registrator. \~ + */ + DEPRECATE_DECLARE + void SetSurface( MbSurface & surf, bool copy, MbRegDuplicate * iReg = nullptr ); + + /// \ru Дать поверхность. \en Get the surface. \~ + DEPRECATE_DECLARE + MbSurface & SetSurface() { return const_cast( _wrpValues.GetSurface() ); } + /// \ru Установить поверхность. \en Set the surface. \~ + DEPRECATE_DECLARE + void SetSurfacePtr( const c3d::ConstSurfaceSPtr & surf ); + + /// \ru Дать точку в области параметров поверхности. \en Get a point on the parametric plane "UV" of the surface corresponding to the point xy on the plane. \~ + DEPRECATE_DECLARE_REPLACE( method of the class MbWrapValues ) + const MbCartPoint & GetSurfacePoint() const { return _wrpValues.GetSurfacePoint(); } + /// \ru Установить точку в области параметров поверхности. \en Set a point on the parametric plane "UV" of the surface corresponding to the point xy on the plane. \~ + DEPRECATE_DECLARE + void SetSurfacePoint( const MbCartPoint & p ); + + /// \ru Дать угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. \en Get the angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ + DEPRECATE_DECLARE_REPLACE( method of the class MbWrapValues ) + double GetAngle() const { return _wrpValues.GetAngle(); } + /// \ru Установить угол поворота плоскости "XY" ЛСК и параметрической плоскости "UV" поверхности. \en Set the angle of rotation of the LSC "XY" plane and the parametric "UV" plane of the surface. \~ + DEPRECATE_DECLARE + void SetAngle( double a ); + /// \ru Совпадают ли ориентации осей "X-Y" ЛСК и осей "U-V" поверхности. \en Whether the orientations of LCS "X-Y" axes and the surface "U-V" axes are same. \~ + DEPRECATE_DECLARE_REPLACE( method of the class MbWrapValues ) + bool IsSense() const { return _wrpValues.IsSense(); } + /// \ru Установить флаг совпадения направления оси "X" ЛСК и оси "U" поверхности. \en Set the coincidence of the directions of the "X" axis of the LSC and the "U" axis of the surface. \~ + DEPRECATE_DECLARE + void SetSense( bool s ); + /// \ru Должна ли совпадать длина итоговых кривых оригинальным. \en Should the result curve length be equal to the original curve length? \~ + DEPRECATE_DECLARE_REPLACE( MbWrapValues::IsLengthKept ) + bool IsEquals() const { return _wrpValues.IsLengthKept(); } + /// \ru Установить требование совпадения длины кривых в плоскости и на поверхности? \en Set the curves length correspondence to the originals on the surface? \~ + DEPRECATE_DECLARE + void SetEquals( bool e ); + + /// \ru Заменить двумерную кривую. \en Set two-dimensional curve by index. \~ + DEPRECATE_DECLARE + void SetCurve( size_t i, const MbCurve & c, bool copy ); + /// \ru Заменить двумерную кривую. \en Set two-dimensional curve by index. \~ + DEPRECATE_DECLARE + void SetCurve( size_t i, MbCurve * c, bool copy ); + + /// \ru Дать точность построения. \en Get an accuracy. \~ + DEPRECATE_DECLARE + double GetAccuracy() const { return GetPrecision(); } + /// \ru Установить точность построения. \en Set an accuracy. \~ + DEPRECATE_DECLARE + void SetAccuracy( double acc ) { SetPrecision( acc ); } + + /// \ru Задать именователь. \en Set names maker. + DEPRECATE_DECLARE + void SetNameMaker( const MbSNameMaker & newOperName ) { _snMaker->SetNameMaker( newOperName, true ); } + + /// \ru Проверка на валидность: например поверхность не null и часть кривых не null. \en The validity check: e.g. whether surface is not null and some of the curves are not null. \~ + DEPRECATE_DECLARE + bool IsValid () const; + + /** \brief \ru Нужно ли сдвинуть кривые, попавшие одним краем на шов Umax. + \en Whether to shift curves with one end on Umax seam.\~ + \details \ru Нужно ли сдвинуть кривые, попавшие краем на шов Umax. Если кривая попадает одним краем на шов Umax, + а другим не попадает ни на Umax, ни на Umin, то сдвинуть эту кривую на Umax-Umin. Это упрощённая + стыковка кривых, которые в 3D соединяются краями на шве, но в 2D разнесены на период. При включении + этого флага на развёртке они также будут стыковаться. + \en Whether to shift curves with one end on Umax seam. If one curve end is on the Umax seam and the other + is neither on Umax nor Umin, then shift the curve for Umax-Umin. This is a simplified stitching of + curves which have connected edges in 3D on the seam, but in 2D are spaced apart on a period. + If this flag is enabled, those unwrapped curves are alse connected. \~ + */ + bool GetUSeamStitch() const { return _uSeamStitch; } + /** \brief \ru Нужно ли сдвинуть кривые, попавшие одним краем на шов Umax. + \en Whether to shift curves with one end on Umax seam.\~ + \details \ru Нужно ли сдвинуть кривые, попавшие краем на шов Umax. Если кривая попадает одним краем на шов Umax, + а другим не попадает ни на Umax, ни на Umin, то сдвинуть эту кривую на Umax-Umin. Это упрощённая + стыковка кривых, которые в 3D соединяются краями на шве, но в 2D разнесены на период. При включении + этого флага на развёртке они также будут стыковаться. + \en Whether to shift curves with one end on Umax seam. If one curve end is on the Umax seam and the other + is neither on Umax nor Umin, then shift the curve for Umax-Umin. This is a simplified stitching of + curves which have connected edges in 3D on the seam, but in 2D are spaced apart on a period. + If this flag is enabled, those unwrapped curves are also connected. \~ + */ + void SetUSeamStitch( bool s ) { _uSeamStitch = s; } private: - /// \ru Добавить 2d или 3d кривые с проверкой на нули. \en 2d or 3d curves with nullptr check. \~ + /// \ru Добавить двумерные или трехмерные кривые с проверкой на нули. \en Add two- or three-dimension curves with nullptr check. \~ template void AddCurves( const CurveVector & curves, bool copyCurves, MbRegDuplicate * iReg ); /// \ru Добавить кривую без копирования с проверкой на nullptr. \en Add curve without copy and with nullptr check. \~ @@ -1680,9 +2091,9 @@ OBVIOUS_PRIVATE_COPY( MbCurvesWrappingParams ) //------------------------------------------------------------------------------ /** \brief \ru Результат операции переноса копий двумерных кривых и точек на другой носитель. - \en Result of operation to transfer copies of two-dimensional curves and points on another medium. \~ + \en Result of operation to transfer copies of two-dimensional curves and points on another carrier. \~ \details \ru Результат операции переноса копий двумерных кривых и точек на другой носитель. - \en Result of operation to transfer copies of two-dimensional curves and points on another medium. \~ + \en Result of operation to transfer copies of two-dimensional curves and points on another carrier. \~ \ingroup Curve3D_Building_Parameters */ // --- @@ -1710,7 +2121,7 @@ public: /// \ru Получить 3D-кривые. \en Get 3D-curves. bool GetCurves( c3d::SpaceCurvesSPtrVector & curves ) const; - /// \ru Получить 2D-кривые. \en Get 2D-curves. + /// \ru Получить двумерные кривые. \en Get two-dimension curves. bool GetCurves( c3d::PlaneCurvesSPtrVector & curves ) const; /// \ru Отцепить кривые из владеющего указателя. \en Detach curves from owning pointer. @@ -1719,10 +2130,10 @@ public: /// \ru Отцепить кривые из владеющего указателя. \en Detach curves from owning pointer. bool DetachCurves( c3d::PlaneCurvesSPtrVector & curves ); - /// \ru Получить 3D-точки. \en Get points. + /// \ru Получить трехмерные точки. \en Get two-dimension points. bool GetPoints( c3d::SpacePointsVector & points ) const; - /// \ru Получить 2D-точки. \en Get points. + /// \ru Получить двумерные точки. \en Get three-dimension points. bool GetPoints( c3d::ParamPointsVector & points ) const; /// \ru Отцепить точки из владеющего указателя. \en Detach points from owning pointer. diff --git a/C3d/Include/op_direct_mod_parameter.h b/C3d/Include/op_direct_mod_parameter.h index b81f906..2d3953d 100644 --- a/C3d/Include/op_direct_mod_parameter.h +++ b/C3d/Include/op_direct_mod_parameter.h @@ -1011,6 +1011,22 @@ public: bool GetOffsetFacesHotPoint( MbCartPoint3D & pnt, MbVector3D & dir ) const; + /** \brief \ru Получить хот-точку и её вектор направления смещения для операции замены группы граней. + \en Get hot point and its displacement direction vector for the replacement faces group operation. \~ + \details \ru В случае успешного выполнения операции хот-точка размещается в центре грани, ближайшей к центру заменяющей группы граней. + В случае неудачного выполнения операции хот-точка располагается в центре заменяющей группы граней плюс смещение. + \en If the operation is successful, the hot point is placed in the center of the face, closest to the replacement group faces center. + If the operation fails, the hot point is located in the center of a replacement group faces, plus the offset is taken relative to this center.\~ + \param[out] pnt - \ru Хот-точка. + \en Hot point. \~ + \param[out] dir - \ru Вектор направления смещения хот-точки. + \en Hot point displacement direction vector.\~ + \return \ru Возвращает "true", если хот-точка была рассчитана. + \en Returns "true" if the hot-point is calculated. \~ + */ + bool GetReplaceFacesGroupHotPoint( MbCartPoint3D & pnt, + MbVector3D & dir ) const; + /** \brief \ru Получить константную ссылку на массив вариантов замены граней. \en Get a constant reference to an array of face replacement options. \~ \details \ru Получить константную ссылку на массив вариантов замены граней. diff --git a/C3d/Include/op_duplication_parameter.h b/C3d/Include/op_duplication_parameter.h index 91757c7..4251de2 100644 --- a/C3d/Include/op_duplication_parameter.h +++ b/C3d/Include/op_duplication_parameter.h @@ -516,7 +516,7 @@ public: /// \ru Получить индексы выбранных граней оболочки. \en Get indices of selected shell faces. void GetFacesIndices( c3d::IndicesVector & selIndices ) const { selIndices = _selIndices; } /// \ru Установить индексы выбранных граней оболочки. \en Set indices of selected shell faces. - void SetFacesIndices( c3d::IndicesVector & selIndices ) { _selIndices = selIndices; } + void SetFacesIndices( const c3d::IndicesVector & selIndices ) { _selIndices = selIndices; } /// \ru Режим адаптации открытых оболочек. \en Open shell instances adaptation mode. bool IsAdaptMode() const { return _adaptMode; } /// \ru Режим адаптации открытых оболочек. \en Open shell instances adaptation mode. diff --git a/C3d/Include/op_mesh_parameter.h b/C3d/Include/op_mesh_parameter.h index c1406a3..8533f90 100644 --- a/C3d/Include/op_mesh_parameter.h +++ b/C3d/Include/op_mesh_parameter.h @@ -140,18 +140,18 @@ private: public: /// \ru Конструктор.. \en Constructor. \~ MbConvexHullParams( const c3d::ParamPointsVector & points, double tolerance, bool makeContour, bool makeGrid, bool makeDelaunay ) - : _points ( points ) - , _tolerance ( tolerance ) - , _makeContour ( makeContour ) - , _makeGrid ( makeGrid ) + : _makeGrid ( makeGrid ) , _makeDelaunay( makeDelaunay ) + , _makeContour ( makeContour ) + , _tolerance ( tolerance ) + , _points ( points ) {} /// \ru Конструктор.. \en Constructor. \~ MbConvexHullParams( const std::vector & points, double tolerance, bool makeContour, bool makeGrid, bool makeDelaunay ) - : _tolerance ( tolerance ) - , _makeContour ( makeContour ) - , _makeGrid ( makeGrid ) + : _makeGrid ( makeGrid ) , _makeDelaunay( makeDelaunay ) + , _makeContour ( makeContour ) + , _tolerance ( tolerance ) { _points.clear(); _points.reserve( points.size() ); @@ -160,10 +160,10 @@ public: } /// \ru Конструктор.. \en Constructor. \~ MbConvexHullParams( const SArray & points, double tolerance, bool makeContour, bool makeGrid, bool makeDelaunay ) - : _tolerance ( tolerance ) - , _makeContour ( makeContour ) - , _makeGrid ( makeGrid ) + : _makeGrid ( makeGrid ) , _makeDelaunay( makeDelaunay ) + , _makeContour ( makeContour ) + , _tolerance ( tolerance ) { _points.clear(); _points.reserve( points.size() ); @@ -172,10 +172,10 @@ public: } /// \ru Конструктор.. \en Constructor. \~ MbConvexHullParams( const SArray & points, double tolerance, bool makeContour, bool makeGrid, bool makeDelaunay ) - : _tolerance ( tolerance ) - , _makeContour ( makeContour ) - , _makeGrid ( makeGrid ) + : _makeGrid ( makeGrid ) , _makeDelaunay( makeDelaunay ) + , _makeContour ( makeContour ) + , _tolerance ( tolerance ) { _points.clear(); _points.reserve( points.size() ); @@ -248,8 +248,9 @@ private: public: /// \ru Конструктор.. \en Constructor. \~ MbConvexHullParams3D( const c3d::SpacePointsVector & points, double tolerance ) - : _points ( points ) - , _tolerance( tolerance ) + : _tolerance( tolerance ) + , _points ( points ) + {} /// \ru Конструктор.. \en Constructor. \~ MbConvexHullParams3D( const std::vector & points, double tolerance ) @@ -303,28 +304,45 @@ public: \ingroup Polygonal_Objects */ // --- -class MATH_CLASS MbRepairInconsistentMeshParams +class MATH_CLASS MbRepairInconsistentMeshParams { private: /// \ru Ориентировать нормали вовне, если это возможно. \en Orient normals outward if possible.\~ - bool _orientOutward; + bool _orientOutward; + /// \ru Точность объединения вершин (не используется, если отрицательная). \en A tolerance for vertices merging (not used if negative).\~ + double _tolerance; + /// \ru Двуграный угол для расчета нормалей (не используется, если отрицательный). \en A dihedral angle for normal vectors calculation (not used if negative).\~ + double _angleSharp; + /// \ru Флаг усреднения нормалей по веерам объединенных вершин. \en A flag for normal vectors averaging around merged vertices fans.\~ + bool _bNormalAveraging; public: /// \ru Конструктор по-умолчанию. \en Default constructor.\~ MbRepairInconsistentMeshParams() - : _orientOutward( false ) - {} - /// \ru Конструктор. \en Constructor. \~ - MbRepairInconsistentMeshParams( bool orientOutward ) - : _orientOutward( orientOutward ) + : _orientOutward ( false ) + , _tolerance ( METRIC_EPSILON ) + , _angleSharp ( -1. ) + , _bNormalAveraging( true ) {} + /// \ru Конструктор. \en Constructor. \~; + MbRepairInconsistentMeshParams( bool orientOutward ); + /// \ru Конструктор. \en Constructor. \~; + MbRepairInconsistentMeshParams( double tolerance, bool orientOutward, double sharpAngle, bool normalAveraging ); /// \ru Деструктор. \en Destructor. \~ ~MbRepairInconsistentMeshParams() {} /// \ru Переключатель между абсолютной и относительной точностью. \en Switch between absolute and relative accuracy. \~ - void SetOrientOutward( bool orient ) { _orientOutward = orient; } - /// \ru Ориентировать ли нормали вовне \en Whether the accuracy is set to absolute or relative. \~ - bool IsOrientOutward() const { return _orientOutward; } + void SetOrientOutward( bool orient ) { _orientOutward = orient; } + /// \ru Ориентировать ли нормали вовне. \en Whether the accuracy is set to absolute or relative. \~ + bool IsOrientOutward() const { return _orientOutward; } + /// \ru Установить точность. \en Set tolerance. \~ + void SetTolerance( double tolerance ) { _tolerance = tolerance; } + /// \ru Получить точность. \en Get tolerance. \~ + double GetTolerance() const { return _tolerance; } + /// \ru Получить угол. \en Get angle. \~ + double GetSharpAngle() const { return _angleSharp; } + /// \ru Усреднять ли нормали. \en Whether normal vectors is to be averaged. \~ + bool NeedNormalsAveraging() const { return _bNormalAveraging; } OBVIOUS_PRIVATE_COPY( MbRepairInconsistentMeshParams ); }; @@ -1362,12 +1380,12 @@ private: , _pointsFittingMax ( 10000 ) , _withRefinement ( false ) , _closed ( false ) - , _order ( c3d::NURBS_DEGREE ) - , _countCpMax ( c3d::NURBS_POINTS_MAX_COUNT ) - , _smoothCoef ( METRIC_ACCURACY ) , _angleConeMin ( 1. ) , _angleConeMax ( 89. ) , _radiusAnalyticShapeMax( 1500. ) + , _order ( c3d::NURBS_DEGREE ) + , _countCpMax ( c3d::NURBS_POINTS_MAX_COUNT ) + , _smoothCoef ( METRIC_ACCURACY ) {} public: @@ -1383,12 +1401,12 @@ public: , _pointsFittingMax ( 10000 ) , _withRefinement ( false ) , _closed ( false ) - , _order ( c3d::NURBS_DEGREE ) - , _countCpMax ( c3d::NURBS_POINTS_MAX_COUNT ) - , _smoothCoef ( METRIC_ACCURACY ) , _angleConeMin ( 1. ) , _angleConeMax ( 89. ) , _radiusAnalyticShapeMax( 1500. ) + , _order ( c3d::NURBS_DEGREE ) + , _countCpMax ( c3d::NURBS_POINTS_MAX_COUNT ) + , _smoothCoef ( METRIC_ACCURACY ) {} /// \ru Конструктор по параметрам. \en Constructor by parameters. explicit MbSurfaceFitToGridParameters( MbeSpaceType surfaceType, @@ -1404,12 +1422,12 @@ public: , _pointsFittingMax ( 10000 ) , _withRefinement ( false ) , _closed ( false ) - , _order ( c3d::NURBS_DEGREE ) - , _countCpMax ( c3d::NURBS_POINTS_MAX_COUNT ) - , _smoothCoef ( METRIC_ACCURACY ) , _angleConeMin ( 1. ) , _angleConeMax ( 89. ) , _radiusAnalyticShapeMax( 1500. ) + , _order ( c3d::NURBS_DEGREE ) + , _countCpMax ( c3d::NURBS_POINTS_MAX_COUNT ) + , _smoothCoef ( METRIC_ACCURACY ) {} /// \ru Конструктор по параметрам для вписывания аналитических поверхностей. \en Constructor by parameters for analytic surfaces fitting. explicit MbSurfaceFitToGridParameters( MbeSpaceType surfaceType, @@ -1428,12 +1446,12 @@ public: , _pointsFittingMax ( 10000 ) , _withRefinement ( false ) , _closed ( false ) - , _order ( c3d::NURBS_DEGREE ) - , _countCpMax ( c3d::NURBS_POINTS_MAX_COUNT ) - , _smoothCoef ( METRIC_ACCURACY ) , _angleConeMin ( angleConeMin ) , _angleConeMax ( angleConeMax ) , _radiusAnalyticShapeMax( radiusAnalyticShapeMax ) + , _order ( c3d::NURBS_DEGREE ) + , _countCpMax ( c3d::NURBS_POINTS_MAX_COUNT ) + , _smoothCoef ( METRIC_ACCURACY ) {} /// \ru Конструктор по параметрам для вписывания нурбс поверхности. \en Constructor by parameters for NURBs surface fitting. explicit MbSurfaceFitToGridParameters( MbeSpaceType surfaceType, @@ -1450,12 +1468,12 @@ public: , _pointsFittingMax ( 10000 ) , _withRefinement ( false ) , _closed ( false ) - , _order ( order ) - , _countCpMax ( countCpMax ) - , _smoothCoef ( smoothCoef ) , _angleConeMin ( 1. ) , _angleConeMax ( 89. ) , _radiusAnalyticShapeMax( 1500. ) + , _order ( order ) + , _countCpMax ( countCpMax ) + , _smoothCoef ( smoothCoef ) {} /// \ru Выдать тип поверхности. \en Get surface type. diff --git a/C3d/Include/op_polymesh_parameter.h b/C3d/Include/op_polymesh_parameter.h index 78c5b8e..299f4de 100644 --- a/C3d/Include/op_polymesh_parameter.h +++ b/C3d/Include/op_polymesh_parameter.h @@ -22,6 +22,7 @@ class MbFaceShell; class MbHalfedgeAttrSizetEdge; class MbHalfedgeAttrDoubleEdge; class MbHalfedgeAttrBoolVertex; +class MbPolyline3D; //------------------------------------------------------------------------------ /** \brief \ru Параметры ремешинга. @@ -335,7 +336,8 @@ private: std::vector _weft; ///< \ru Полилинии для нулевой нити утка. \en Weft polylines. \~ MbHalfedgeAttrSizetEdge * _pAttrId; ///< \ru Атрибут индексов сторон ячеек. \en An attribute for cell sides indices. \~ MbHalfedgeAttrDoubleEdge * _pAttrAng; ///< \ru Атрибут углов сторон ячеек. \en An attribute for cell sides angles. \~ - MbHalfedgeAttrBoolVertex * _pAttrNode; ///< \ru Атрибут флагов узлов ткани. \en An attribute for the fiber nodes. \~ + MbHalfedgeAttrBoolVertex * _pAttrNode; ///< \ru Атрибут флагов узлов ткани. \en An attribute for fiber nodes flags. \~ + MbHalfedgeAttrSizetEdge * _pAttrDir; ///< \ru Атрибут направлений сторон ячеек ткани. \en An attribute for cell sides directions. \~ public: /// \ru Конструктор. \en Constructor. @@ -420,6 +422,16 @@ public: \en Polylines represented a line mapping to the shell. \~ */ void GetSplitPolylines( const MbCartPoint & uv, const MbVector & dir, std::vector & polys ) const; + /** \brief \ru Получить атрибут направлений сторон ячеек. + \en Get an attribute for cell sides directions. \~ + \details \ru Получить атрибут направлений сторон ячеек. + Возможные значения: + 0 - вдоль основы, 1 - вдоль утка, 2 - против основы, 3 - против утка, SYS_MAX_T - не определено. + \en Get an attribute for cell sides directions. + Possible values are: + 0 - along warp, 1 - along weft, 2 - against warp, 3 - against weft, SYS_MAX_T - undefined. + */ + const MbHalfedgeAttrSizetEdge * GetDirectionalAttribute() const { return _pAttrDir; } // \ru Инициализировать атрибуты сетки. \en Initialize the mesh attributes. \~ void InitAttributes(); @@ -465,4 +477,170 @@ public: OBVIOUS_PRIVATE_COPY( MbMergePolymeshParams ); }; // MbMergePolymeshParams + +//------------------------------------------------------------------------------ +/** \brief \ru Параметры сглаживания полигональных объектов. + \en Parameters for the polymesh smoothing. \~ + \details \ru Параметры сглаживания полигональных объектов. \n + Параметры содержат информацию о коэффициентах сглаживания, методе сглаживания, максимальном числе итераций, + наборе индексов фасетов для сглаживания. + \en Parameters for the polymesh smoothing. \n + The parameters contain information about the smoothing coefficients, the smoothing method, the maximum number of iterations + and the set of facet indices for smoothing. \~ + \ingroup Polygonal_Objects + \warning \ru В разработке. + \en Under development. \~ +*/ +// --- +class MATH_CLASS MbMeshSmoothingParams +{ +public: + //------------------------------------------------------------------------------ + /** \brief \ru Перечисление методов сглаживания. + \en Enumeration for smoothing methods. \~ + */ + // --- + enum class MethodSmoothMesh + { + smoothTaubin, ///< \ru Метод Таубина. \en Taubin's method. + smoothLaplas ///< \ru Метод Лапласа. \en Laplace method. + }; + +private: + MethodSmoothMesh _method; ///< \ru Метод сглаживания сетки. \en Mesh smoothing method. + double _lambda; ///< \ru Коэффициент сжатия, используемый на нечетных шагах в "taubin smoothing". \en The compression factor used in odd steps in "taubin smoothing". + double _mu; ///< \ru Коэффициент расширения, используемый на четных шагах в "taubin smoothing". \en The expansion factor used in even steps in "taubin smoothing". + size_t _maxIter; ///< \ru Максимальное число итераций. \en Maximum iteration number. + bool _bFixBorders; ///< \ru Сохранять границы. \en Save borders. + c3d::IndicesVector _facets; ///< \ru Индексы фасетов. Если набор фасетов пустой, то сглаживается вся сетка. \en Facet indices to smooth. If the facet set is empty, the entire mesh is smoothed. + c3d::IndicesVector _fixVertices; ///< \ru Индексы фиксированных вершин. \en Fixed vertex indices. + +public: + /// \ru Конструктор. \en Constructor. + MbMeshSmoothingParams() + : _method ( MethodSmoothMesh::smoothTaubin ) + , _lambda ( 0.33 ) + , _mu ( -0.34 ) + , _maxIter ( 100 ) + , _bFixBorders ( true ) + , _facets ( ) + , _fixVertices ( ) + {} + /// \ru Конструктор по параметрам. \en Constructor by parameters. + MbMeshSmoothingParams( MethodSmoothMesh method, + double lambda, + double mu, + size_t maxIter, + bool bFixBorders, + const c3d::IndicesVector & facets, + const c3d::IndicesVector & fixVertices ) + : _method ( method ) + , _lambda ( lambda ) + , _mu ( mu ) + , _maxIter ( maxIter ) + , _bFixBorders ( bFixBorders ) + , _facets ( facets ) + , _fixVertices ( fixVertices ) + {} + /// \ru Деструктор. \en Destructor. + ~MbMeshSmoothingParams() {} + +public: + // \ru Установить метод сглаживания. \en Set the smoothing method. \~ + void SetMethod( MethodSmoothMesh method ) { _method = method; } + // \ru Установить коэффициент сжатия. \en Set the compression factor. \~ + void SetLambda( double lambda ) { _lambda = lambda; } + // \ru Установить коэффициент расширения. \en Set the expansion factor. \~ + void SetMu( double mu ) { _mu = mu; } + // \ru Установить максимальное число итераций. \en Set the maximum iteration number. \~ + void SetMaxIter( size_t maxIter ) { _maxIter = maxIter; } + // \ru Установить флаг сохранения границ. \en Set the save borders flag. \~ + void SetFixBorders( bool bFixBorders ) { _bFixBorders = bFixBorders; } + // \ru Установить набор индексов фасетов для сглаживания. \en Set facet indices to smooth. \~ + void SetFacets( const c3d::IndicesVector & facets ) { _facets = facets; } + // \ru Установить набор фиксированных вершин. \en Set the fixed vertex indices. \~ + void SetFixVertices( const c3d::IndicesVector & fixVertices ) { _fixVertices = fixVertices; } + // \ru Получить метод сглаживания. \en Get the the smoothing method. \~ + MethodSmoothMesh GetMethod() const { return _method; } + // \ru Получить коэффициент сжатия. \en Get the the compression factor. \~ + double GetLambda() const { return _lambda; } + // \ru Получить коэффициент расширения. \en Get the expansion factor. \~ + double GetMu() const { return _mu; } + // \ru Получить максимальное число итераций. \en Get the maximum iteration number. \~ + size_t GetMaxIter() const { return _maxIter; } + // \ru Получить флаг сохранения границ. \en Get the save borders flags. \~ + bool GetFixBorders() const { return _bFixBorders; } + // \ru Получить набор индексов фасетов для сглаживания. \en Get facet indices to smooth. \~ + const c3d::IndicesVector & GetFacets() const { return _facets; } + // \ru Получить набор фиксированных вершин. \en Get the fixed vertex indices. \~ + const c3d::IndicesVector & GetFixVertices() const { return _fixVertices; } + + OBVIOUS_PRIVATE_COPY( MbMeshSmoothingParams ); +}; + + +//------------------------------------------------------------------------------ +/** \brief \ru Параметры проецирования полилинии на полигональный объект. + \en Parameters for projecting a polyline on a polymesh. \~ + \details \ru Параметры проецирования полилинии на полигональный объект. \n + Параметры содержат проецируемую полилинию. + \en Parameters for projecting a polyline on a polymesh. \n + Parameters contain a polyline to be projected. \~ + \warning \ru В разработке. + \en Under development. \~ +*/ +// --- +class MATH_CLASS MbPolylinePolymeshProjectParams : public MbPrecision +{ +private: + const MbPolyline3D & _polyline; ///< \ru Полилиния. \en Polyline. \~ + +public: + /// \ru Конструктор по параметрам. \en Constructor by parameters. + MbPolylinePolymeshProjectParams( const MbPolyline3D & polyline ) + : MbPrecision( ) + , _polyline ( polyline ) + {} + /// \ru Деструктор. \en Destructor. + ~MbPolylinePolymeshProjectParams() {} + +public: + // \ru Получить полилинию. \en Get the polyline. \~ + const MbPolyline3D & GetPolyline() const { return _polyline; } + + OBVIOUS_PRIVATE_COPY( MbPolylinePolymeshProjectParams ); +}; + + +//------------------------------------------------------------------------------ +/** \brief \ru Результаты проецирования полилинии на полигональный объект. + \en Results of projecting a polyline on a polymesh. \~ + \details \ru Результаты проецирования полилинии на полигональный объект. \n + Результаты содержат массив цепочек пар рёбер вдоль проекции. + \en Results of projecting a polyline on a polymesh. \n + Results contain paths of edge pairs along the projection. \~ + \warning \ru В разработке. + \en Under development. \~ +*/ +// --- +class MATH_CLASS MbPolylinePolymeshProjectResults +{ +private: + std::vector _paths; ///< \ru Цепочки пар рёбер. \en Paths of edge pairs. \~ + +public: + /// \ru Конструктор. \en Constructor. + MbPolylinePolymeshProjectResults() : _paths() {} + /// \ru Деструктор. \en Destructor. + ~MbPolylinePolymeshProjectResults() {} + +public: + // \ru Получить полилинию. \en Get the polyline. \~ + const std::vector & GetEdgePairPaths() const { return _paths; } + // \ru Получить полилинию. \en Get the polyline. \~ + std::vector & GetEdgePairPaths() { return _paths; } + + OBVIOUS_PRIVATE_COPY( MbPolylinePolymeshProjectResults ); +}; + #endif // __OP_POLYMESH_PARAMETERS_H diff --git a/C3d/Include/op_shell_parameter.h b/C3d/Include/op_shell_parameter.h index cb7d864..11cd532 100644 --- a/C3d/Include/op_shell_parameter.h +++ b/C3d/Include/op_shell_parameter.h @@ -689,7 +689,7 @@ KNOWN_OBJECTS_RW_REF_OPERATORS( PocketValues ) // \ru Для работы со // --- class MATH_CLASS SlotValues : public HoleValues { public: - // \ru Вид паза сверху. \en View of slot from above. \~ + /* \ru Вид паза сверху. \en View of slot from above. \~ // -- // / \ // | | @@ -698,6 +698,7 @@ public: // | | // \ / // -- + */ enum SlotType { // ________ * // | | * @@ -2834,6 +2835,10 @@ public: const MbFaceShell * GetShell() const { return shell; } /// \ru Номер грани в оболочке. \en The index of face in the shell. const MbItemIndex & GetFaceIndex() const { return faceIndex; } + /// \ru Номер грани в оболочке. \en The index of face in the shell. + void SetFaceIndex( const MbItemIndex & index ) { faceIndex.Init( index ); } + /// \ru Номер грани в оболочке. \en The index of face in the shell. + void SetFaceIndex( size_t index ) { faceIndex.Init( index ); } /// \ru Получить режим обработки оболочки-препятствия. \en Get obstacle shell processing mode. ShellObstacleType GetObstacleType() const { return toShellType; } /// \ru Получить вариант представления результирующего тела. \en Get options for representing the resulting body. @@ -4263,9 +4268,9 @@ public: \en An object for naming the new objects. \~ */ MbShellChamferParams( const c3d::EdgesSPtrVector & initCurves, const SmoothValues & params, const MbSNameMaker & names ) - : _params( params ) + : _initCurves( initCurves ) , _nameMaker( &names.Duplicate() ) - , _initCurves( initCurves ) {} + , _params( params ) {} public: /// \ru Получить именователь операции. \en Get the object defining names generation in the operation. @@ -4436,8 +4441,8 @@ public: MbShellFilletValues( const std::vector & initFunctions, c3d::FacesSPtrVector & initBounds, const MbSNameMaker & names, const SmoothValues & params ) : MbShellChamferParams( c3d::EdgesSPtrVector(), params, names ) - , _initBounds ( initBounds ) - , _initFunctions( initFunctions ) {} + , _initFunctions( initFunctions ) + , _initBounds ( initBounds ) {} public: /// \ru Получить набор скругляемых ребер тела с функциями изменения радиуса. \en Get the edges to fillet together with the radius laws. @@ -5544,8 +5549,8 @@ public: : _initFaces ( initFaces ) , _initFacesLeft ( initFacesLeft ) , _initFacesRight( initFacesRight ) - , _params ( params ) - , _nameMaker ( &names.Duplicate() ) {} + , _nameMaker ( &names.Duplicate() ) + , _params ( params ) {} public: /// \ru Получить набор граней для скругления. \en Get faces to fillet. @@ -6179,15 +6184,15 @@ public: public: /// \ru Конструктор. \en Constructor. MbShellPartResults() - : _solid() - , _partIndices() + : _partIndices() + , _solid() { } /// \ru Конструктор по индексам частей тела. \en Constructor by the indices of the parts of the solid. MbShellPartResults( const MbPartSolidIndices & partIndices ) - : _solid() - , _partIndices( partIndices ) + : _partIndices( partIndices ) + , _solid() { } diff --git a/C3d/Include/op_swept_parameter.h b/C3d/Include/op_swept_parameter.h index 6210131..a3feb08 100644 --- a/C3d/Include/op_swept_parameter.h +++ b/C3d/Include/op_swept_parameter.h @@ -1603,9 +1603,9 @@ protected: protected: /// \ru Конструктор. \en Constructor. - MbSweptLayout( const MbSurface & surf, Direction dir ) : surface( &surf ), direction( dir ), skipUnion( false ) {} + MbSweptLayout( const MbSurface & surf, Direction dir ) : direction( dir ), skipUnion( false ), surface( &surf ) {} /// \ru Конструктор копирования. \en Copy-constructor. - MbSweptLayout( const MbSweptLayout & other ) : surface( other.surface ), direction( other.direction ), skipUnion( other.skipUnion ) {} + MbSweptLayout( const MbSweptLayout & other ) : direction( other.direction ), skipUnion( other.skipUnion ), surface( other.surface ) {} /// \ru Деструктор. \en Destructor. virtual ~MbSweptLayout(); public: diff --git a/C3d/Include/op_wireframe_parameter.h b/C3d/Include/op_wireframe_parameter.h index d8260d2..4aac35d 100644 --- a/C3d/Include/op_wireframe_parameter.h +++ b/C3d/Include/op_wireframe_parameter.h @@ -12,7 +12,7 @@ #include -#include +#include #include @@ -433,4 +433,114 @@ public: }; +//------------------------------------------------------------------------------- +/** \brief \ru Параметры эквидистантного каркаса. + \en Parameters of an offset wire frame. \~ + \details \ru Параметры эквидистантного каркаса. + \en Parameters of an offset wire frame. \~ + \ingroup WireFrame_Parameters +*/ +// --- +class MATH_CLASS MbOffsetWireFrameParams : public MbPrecision { +private: + std::unique_ptr _spatialParameters; ///< \ru Параметры для смещения пространственной кривой. \en Parameters for offsetting a spatial curve. \~ + std::unique_ptr _surfaceParameters; ///< \ru Параметры для смещения кривой вдоль поверхности. \en Parameters for offsetting a curve along a surface. \~ + MbVector3D _offset; ///< \ru Вспомогательный вектор смещения. \en The auxiliary offset vector. + +public: + /** \brief \ru Конструктор по параметрам. + \en Constructor by parameters. \~ + \details \ru Конструктор для смещения пространственной кривой. + \en Constructor for offsetting a spatial curve. \~ + \param[in] offsetVect - \ru Вектор, задающий смещение в точке кривой. + \en The displacement vector at a point of the curve. \~ + \param[in] useFillet - \ru Если true, то разрывы заполнять скруглением, иначе продолженными кривыми. + \en If 'true', the gaps are to be filled with fillet, otherwise with the extended curves. \~ + \param[in] keepRadius - \ru Если true, то в существующих скруглениях сохранять радиусы. + \en If 'true', the existent fillet radii are to be kept. \~ + \param[in] bluntAngle - \ru Если true, то в притуплять острые углы. + \en If 'true', sharp corners are to be blunt. \~ + \param[in] fromBeg - \ru Вектор смещения привязан к началу (если true). + \en The translation vector is associated with the beginning (if true). \~ + \param[in] nameMaker - \ru Именователь кривых каркаса. + \en An object defining the frame curves names. \~ + \param[in] useSurfaceNormal - \ru Эквидистанта согласована с нормалью к поверхности. + \en Offset point is moved according to surface normal. \~ + \param[in] surface - \ru Поверхность кривой или подобная ей. + \en Curve's surface or similar to such surface. \~ + */ + explicit MbOffsetWireFrameParams( const MbVector3D & offsetVect, + bool useFillet, + bool keepRadius, + bool bluntAngle, + bool fromBeg, + const MbSNameMaker & nameMaker, + bool useSurfaceNormal, + c3d::ConstSurfaceSPtr surface = nullptr ); + + /** \brief \ru Конструктор по параметрам. + \en Constructor by parameters. \~ + \details \ru Конструктор для смещения пространственной кривой. + \en Constructor for offsetting a spatial curve. \~ + \param[in] offsetVect - \ru Вектор, задающий смещение в точке кривой. + \en The displacement vector at a point of the curve. \~ + \param[in] nameMaker - \ru Именователь кривых каркаса. + \en An object defining the frame curves names. \~ + */ + explicit MbOffsetWireFrameParams( const MbVector3D & offsetVect, + const MbSNameMaker & nameMaker ); + + /** \brief \ru Конструктор по параметрам. + \en Constructor by parameters. \~ + \details \ru Конструктор для смещения кривой вдоль поверхности. + \en Constructor for offsetting a curve along a surface. \~ + \param[in] face - \ru Грань, на которой строится эквидистанта. + \en The face on which to build the offset curve. \~ + \param[in] axis - \ru Направление смещения с точкой приложения. + \en The offset direction with a reference point. \~ + \param[in] dist - \ru Величина смещения. + \en The offset distance. \~ + \param[in] nameMaker - \ru Именователь кривых каркаса. + \en An object defining the frame curves names. \~ + */ + explicit MbOffsetWireFrameParams( const MbFace & face, const MbAxis3D & axis, double dist, const MbSNameMaker & nameMaker ); + /// \ru Конструктор копирования. \en Copy constructor. + MbOffsetWireFrameParams( const MbOffsetWireFrameParams & other ); + /// \ru Конструктор для чтения. \en Constructor for reading. + MbOffsetWireFrameParams( TapeInit ti ); + /// \ru Деструктор. \en Destructor. + virtual ~MbOffsetWireFrameParams() {} + +public: + /// \ru Получить параметры. \en Get parameters. + const MbSpatialOffsetCurveParams * GetSpatialParams() const { return _spatialParameters.get(); } + /// \ru Получить параметры. \en Get parameters. + const MbSurfaceOffsetCurveParams * GetSurfaceParams() const { return _surfaceParameters.get(); } + /// \ru Выдать вектор смещения. \en Get offset vector. + const MbVector3D & GetOffsetVector() const; + /// \ru Установить вектор смещения. \en Set offset vector. + MbVector3D & SetOffsetVector(); + /// \ru Установить параметры по вектору смещения. \en Set parameters by offset vector. + void SetOffsetParams( const MbVector3D & offset ); + /// \ru Являются ли параметры параметрами для смещением кривой вдоль вектора. \en Are the parameters for a shift of the curve along the vector. + bool IsParamsForSpatialCurve() const; + /// \ru Преобразовать элемент согласно матрице. \en Transform element by matrix. + void Transform( const MbMatrix3D & matrix ); + /// \ru поворот точек вокруг произвольной оси \en rotate points around an arbitrary axis. + void Rotate( const MbAxis3D & axis, double angle ); + /// \ru Сдвиг точек на произвольный вектор \en Move points on arbitrary vector. + void Move( const MbVector3D & to ); + /// \ru Проверка на равенство. \en Check if *this == other. + bool IsEqual( const MbOffsetWireFrameParams & other, double accuracy ) const; + /// \ru Получить именователь операции. \en Get names maker. + const MbSNameMaker & GetNameMaker() const; + + /// \ru Оператор присваивания. \en An assignment operator. + const MbOffsetWireFrameParams & operator=( const MbOffsetWireFrameParams & other ); + + KNOWN_OBJECTS_RW_REF_OPERATORS( MbOffsetWireFrameParams ) // \ru Для работы со ссылками и объектами класса. \en For working with references and objects of the class. \~ + +}; + + #endif // __OP_WIREFRAME_PARAMETERS_H diff --git a/C3d/Include/pars_equation_tree.h b/C3d/Include/pars_equation_tree.h index 7044d08..8c650aa 100644 --- a/C3d/Include/pars_equation_tree.h +++ b/C3d/Include/pars_equation_tree.h @@ -691,7 +691,8 @@ public: \en Object to copy. \~ */ IntervalConstNode( const IntervalConstNode & other ) - : m_firstValue ( other.m_firstValue->Duplicate() ) // ( other.m_firstValue ) + : TreeIntervalNode {} + , m_firstValue ( other.m_firstValue->Duplicate() ) // ( other.m_firstValue ) , m_secondValue( other.m_secondValue->Duplicate() ) // ( other.m_secondValue ) {} /** \brief \ru Деструктор. @@ -1529,7 +1530,8 @@ class MATH_CLASS BTreeUserFunc : public BTreeNode public: // Конструктор копирования BTreeUserFunc( const BTreeUserFunc & other ) - : func( &other.func->Duplicate() ) + : BTreeNode {} + , func( &other.func->Duplicate() ) { for ( size_t i = 0, c = other.pars.size(); i < c; ++i ) { pars.Add( other.pars[i]->Duplicate() ); diff --git a/C3d/Include/polymesh.h b/C3d/Include/polymesh.h index 7c8335a..f776ff0 100644 --- a/C3d/Include/polymesh.h +++ b/C3d/Include/polymesh.h @@ -14,6 +14,8 @@ class MbPolymeshTopo; class MbFaceShell; +class IMeshProvider; +class MbRepairInconsistentMeshParams; //------------------------------------------------------------------------------ /** \brief \ru Полигональный объект модели - представление топологии в виде halfedge объекта. @@ -39,6 +41,8 @@ public: explicit MbPolymesh(); /// \ru Конструктор по топологии. \en Constructor by topology. explicit MbPolymesh( MbPolymeshTopo * pTopo ); + /// \ru Конструктор. \en Constructor. + explicit MbPolymesh( const IMeshProvider & provider, const MbRepairInconsistentMeshParams & params ); /// \ru Деструктор. \en Destructor. virtual ~MbPolymesh(); diff --git a/C3d/Include/polymesh_topo.h b/C3d/Include/polymesh_topo.h index 4f2fb23..59eb04a 100644 --- a/C3d/Include/polymesh_topo.h +++ b/C3d/Include/polymesh_topo.h @@ -13,10 +13,12 @@ #include #include -class MbMesh; -class MbFaceShell; -class MbCube; -class MbAttributeContainer; +class MbMesh; +class MbFaceShell; +class MbCube; +class MbAttributeContainer; +class IMeshProvider; +class MbRepairInconsistentMeshParams; //------------------------------------------------------------------------------ /** \brief \ru Представление топологии полигональной модели в виде halfedge. @@ -74,8 +76,20 @@ public: \en A polygonal geometric object. \~ \param[in] toleranceSew - \ru Метрическая погрешность совпадения точек. \en Metric tolerance of points coincidence. \~. + \return \ru Возвращает указатель на созданный объект. + \en Returns pointer to created object. \~ */ static MbPolymeshTopo * Create( const MbMesh & mesh, double toleranceSew ); + /** \brief \ru Создать экземпляр класса на основе контейнера данных и параметров лечения. + \en Create an object by mesh provider and repairing parameters. \~ + \param[in] provider - \ru Контейнер данных полигонального объекта. + \en A container for polygonal object data. \~ + \param[in] params - \ru Параметры лечения. + \en Repairing parameters. \~. + \return \ru Возвращает указатель на созданный объект. + \en Returns pointer to created object. \~ + */ + static MbPolymeshTopo * Create( const IMeshProvider & provider, const MbRepairInconsistentMeshParams & params ); /// \ru Деструктор. \en Destructor. virtual ~MbPolymeshTopo() {} @@ -367,6 +381,22 @@ public: \en Keep old regions (i.e. do not make separate regions from new subregions). \~ */ virtual void SplitByEdgesTopo( const c3d::IndicesVector & splitSet, bool bKeepRegions ) = 0; + /** \brief \ru Удалить ребра сетки из ребер сегментации. + \en Remove mesh edges from segmentation edges. \~ + \param[in] edgesToDel - \ru Удаляемые ребра сетки. + \en Mesh edges to remove. \~ + */ + virtual void RemoveTopoEdgesFromSegm( const c3d::IndicesVector & edgesToDel ) = 0; + /** \brief \ru Удалить ребра сегментации. + * После удаления ребер общие регионы объединяются и + * сохраняется регион, у которого наибольшая площадь. + \en Segmentation edges to remove. + * Merges all regions connected through removed edges into one. + This region has the ID of the original region with the largest area. \~ + \param[in] edgesToDel - \ru Удаляемые ребра сегментации. + \en Remove segmentation edges. \~ + */ + virtual bool RemoveSegmEdges( const c3d::IndicesVector & edgesToDel ) = 0; /** \brief \ru Объединить несколько регионов в один. \en Merge several regions into one. \~ \param[in] regions - \ru Регионы. diff --git a/C3d/Include/se_curve.h b/C3d/Include/se_curve.h index dbde98c..fd82d0f 100644 --- a/C3d/Include/se_curve.h +++ b/C3d/Include/se_curve.h @@ -46,7 +46,7 @@ namespace c3d //------------------------------------------------------------------------------ /** \brief \ru Форма ограничения кривой STEP. - \en . \~ + \en . Trimming form of STEP curve\~ \note \ru ЭКСПЕРИМЕНТАЛЬНАЯ. \en EXPEREIMENTAL. \~ */ @@ -184,6 +184,8 @@ namespace c3d std::vector m_knotMultiplicities; ///< \ru Множители узлов. \en Knots multiplicities. std::vector m_knots; ///< \ru Узлы. \en Knots. SeBKnotsType m_knotsType; ///< \ru Тип вектора. \en Type of knots vector. + bool m_weightsDefined; ///< \ru Заданы ли веса точек. \en Wether the weights of points are defined. + std::vector m_weights; ///< \ru Веса точек. \en Weights of points. public: @@ -220,7 +222,13 @@ namespace c3d /// \ru Получить тип вектора. \en Get type of vector. SeBKnotsType GetKnotsType() const; - /// \ru . \en . + /// \ru Заданы ли веса. \en Wether the weights defined. + bool AreWeightsDefined() const; + + /// \ru Получить вес точки. \en Get weightf of a point. + double GetWeight( size_t index ); + + /// \ru Создать сплайн. \en Create a spline. static std::shared_ptr Create( size_t const thisId, ptrdiff_t const degree, @@ -233,6 +241,21 @@ namespace c3d SeBKnotsType const knotsType ); + + /// \ru Создать сплайн. \en Create a spline. + static std::shared_ptr Create( + size_t const thisId, + ptrdiff_t const degree, + std::vector && controlPointsList, + SeBCurveForm const curveForm, + bool const isClosed, + bool const isSelfIntersected, + std::vector && knotMultiplicities, + std::vector && knots, + std::vector && weights, + SeBKnotsType const knotsType + ); + VISITING_CLASS( SeBSplineWithKnotsCurve ) void Accept( Visitor & visitor ) const override @@ -255,6 +278,20 @@ namespace c3d std::vector && knots, SeBKnotsType const knotsType ); + + /// \ru Конструктор. \en Constructor. + SeBSplineWithKnotsCurve( + size_t const thisId, + ptrdiff_t const degree, + std::vector && controlPointsList, + SeBCurveForm const curveForm, + bool const isClosed, + bool const isSelfIntersected, + std::vector && knotMultiplicities, + std::vector && knots, + std::vector && weights, + SeBKnotsType const knotsType + ); }; //------------------------------------------------------------------------------ diff --git a/C3d/Include/se_surface.h b/C3d/Include/se_surface.h index e2e8be1..dde336c 100644 --- a/C3d/Include/se_surface.h +++ b/C3d/Include/se_surface.h @@ -13,6 +13,20 @@ namespace c3d { namespace converter { + + //------------------------------------------------------------------------------ + /** \brief \ru Форма тора STEP. + \en STEP Torus form. \~ + \note \ru ЭКСПЕРИМЕНТАЛЬНАЯ. + \en EXPEREIMENTAL. \~ + */ + enum class SeTorusForm { + Donut, ///< \ru Тор. \en Donut. + Apple, ///< \ru Яблоко. \en Apple. + Lemon, ///< \ru Лимон. \en Lemon. + }; + + //------------------------------------------------------------------------------ /** \brief \ru Плоскость. \en Plane. \~ @@ -151,22 +165,27 @@ namespace c3d */ class CONV_CLASS SeTorusSurface : public SeBase { - size_t m_placement; ///< \ru Локальная система координат. \en Location. - double m_majorRadius, ///< \ru . \en . - m_minorRadius; ///< \ru . \en . + size_t m_placement; ///< \ru Локальная система координат. \en Location. + double m_majorRadius, ///< \ru Радиус. \en Radius. + m_minorRadius; ///< \ru Толщина. \en Thickness. + SeTorusForm m_torusForm; ///< \ru Torus form. \en Form. public: - /// \ru . \en . + + /// \ru Создать поверхность тора. \en Create toroidal surace. static std::shared_ptr Create( size_t thisId, size_t placement, double majorRadius, double minorRadius ); /// \ru . \en . size_t GetPlacement() const; - /// \ru . \en . + /// \ru Получить радиус. \en Get radius. double GetMajorRadius() const; - /// \ru . \en . + /// \ru Получить толщину. \en GetThickness. double GetMinorRadius() const; + /// \ru Получить форму. \en Get form. + SeTorusForm GetTorusForm() const; + VISITING_CLASS( SeTorusSurface ) void Accept( Visitor & visitor ) const override @@ -178,7 +197,7 @@ namespace c3d private: /// \ru Конструктор. \en Constructor. - SeTorusSurface( size_t thisId, size_t placement, double majorRadius, double minorRadius ); + SeTorusSurface( size_t thisId, size_t placement, double majorRadius, double minorRadius, SeTorusForm torusForm ); }; diff --git a/C3d/Include/space_item.h b/C3d/Include/space_item.h index 22f358b..3119800 100644 --- a/C3d/Include/space_item.h +++ b/C3d/Include/space_item.h @@ -150,6 +150,7 @@ enum MbeSpaceType { st_ExplorationSurface = 347, ///< \ru Поверхность заметания с масштабированием и поворотом образующей кривой. \en Swept surface with scaling and winding of generating curve. st_SectionSurface = 348, ///< \ru Поверхность заметания переменного сечения. \en The swept mutable section surface. st_SimplexSpline = 349, ///< \ru Поверхность, моделирующая симплексный сплайн. + st_RuledBendedUnbendedSurface=341, ///< \ru Поверхность, полученная линейчатым сгибом/разгибом. \en Surface constructed by ruled fold / unbending. st_FreeSurface = 400, ///< \ru Тип для поверхностей, созданных пользователем. \en Type for the user-defined surfaces. \n // \ru Типы вспомогательных объектов. \en Helper object types. diff --git a/C3d/Include/surf_channel_surface.h b/C3d/Include/surf_channel_surface.h index 13db358..6d25bee 100644 --- a/C3d/Include/surf_channel_surface.h +++ b/C3d/Include/surf_channel_surface.h @@ -195,6 +195,30 @@ public: static MbChannelSurface * CreateKerbLawFillet( double rad, MbFunction & law, MbSurfaceCurve & curv1, bool sgn1, MbSurfaceCurve & curv2, bool sgn2, bool byFirst, VERSION vers ); + /// \ru Создать поверхность скругления по поверхности и кромке с касанием + /// \en + /** \brief \ru Создать поверхность скругления по двум поверхностям с указанием кромки касания + \en Create a fillet surface by two support surfaces, specifying the kerb-curve of touching \~ + \details \ru В случае успеха создается поверхность скругления с версией >= fsv_Ver1. + \en If successful, a fillet surface is created with version >= fsv_Ver1. \~ + \param[in] curv1 - \ru Опорная кривая в параметрах первой поверхности + \en Support curve at parameters of the first surface \~ + \param[in] sgn1 - \ru Ориентация первой опорной поверхности. + \en The orientation of the first support surface. \~ + \param[in] curv2 - \ru Опорная кривая в параметрах второй поверхности + \en Support curve at parameters of the second surface \~ + \param[in] sgn2 - \ru Ориентация второй опорной поверхности. + \en The orientation of the second support surface. \~ + \param[in] byFirst - \ru true - кривая curve2 является кромкой, false - кривая curve1 является кромкой + \en True - curve2 curve is fillet, false - curve1 curve is fillet. \~ + \param[in] vers - \ru Версия. + \en Version. \~ + \return \ru Возвращает указатель на созданную поверхность скругления в случае успеха, иначе - nullptr. + \en Returns a pointer to the created fillet surface if successful, nullptr otherwise. \~ + */ + static MbChannelSurface * CreateKerbTouchingFillet( double rad, MbFunction & law, MbSurfaceCurve & curv1, bool sgn1, + MbSurfaceCurve & curv2, bool sgn2, bool byFirst, VERSION vers ); + protected: /// \ru Конструктор для наследников обычной поверхности скругления. \en Constructor for inheritors of ordinary fillet surface. MbChannelSurface( MbSurfaceCurve & curv1, double d1, diff --git a/C3d/Include/surf_fillet_surface.h b/C3d/Include/surf_fillet_surface.h index edf0904..60eb0e3 100644 --- a/C3d/Include/surf_fillet_surface.h +++ b/C3d/Include/surf_fillet_surface.h @@ -15,7 +15,7 @@ #include -class MbFunction; +class MATH_CLASS MbFunction; struct MbFilletSurfaceCacheData; //------------------------------------------------------------------------------ @@ -193,7 +193,6 @@ public: MbFilletSurface( MbSurface & surf1, MbCurve & curv1, MbSurface & surf2, MbCurve & curv2, MbCurve3D & curv0, double d1, double d2, MbeSmoothForm fm, double cn, bool ev ); - /** \brief \ru Создать поверхность скругления по двум поверхностям с постоянным радиусом. \en Create a fillet surface by two surfaces with a constant radius. \~ @@ -218,7 +217,6 @@ public: */ static MbFilletSurface * CreateSimpleFillet( double rad, MbSurfaceCurve & curv1, bool sgn1, MbSurfaceCurve & curv2, bool sgn2, double conicFact, VERSION vers ); - /** \brief \ru Создать поверхность скругления по двум поверхностям "дугой эллипса". \en Create a fillet surface by two surfaces by an "arc of an ellipse". \~ \details \ru В случае успеха создается поверхность скругления с версией >= fsv_Ver1. @@ -238,7 +236,6 @@ public: */ static MbFilletSurface * CreateEllipticalFillet( MbSurfaceCurve & curv1, double rad1, MbSurfaceCurve & curv2, double rad2, VERSION vers ); - /** \brief \ru Создать поверхность скругления по двум поверхностям с постоянной хордой. \en Create a fillet surface by two surfaces with a constant chord. \~ \details \ru В случае успеха создается поверхность скругления с версией >= fsv_Ver1. @@ -260,7 +257,6 @@ public: */ static MbFilletSurface * CreateChordFillet( double h, MbSurfaceCurve & curv1, bool sgn1, MbSurfaceCurve & curv2, bool sgn2, VERSION vers ); - /** \brief \ru Создать поверхность скругления по поверхности и кромке с постоянным радиусом \en Create fillet surface a constant radius by support surface and support kerb-curve. \~ \details \ru В случае успеха создается поверхность скругления с версией >= fsv_Ver1. @@ -286,7 +282,6 @@ public: */ static MbFilletSurface * CreateKerbFillet( double rad, MbSurfaceCurve & curv1, bool sgn1, MbSurfaceCurve & curv2, bool sgn2, bool byFirst, double conicFact, VERSION vers ); - /// \ru Создать поверхность скругления по поверхности и кромке с касанием /// \en /** \brief \ru Создать поверхность скругления по двум поверхностям с указанием кромки касания @@ -309,6 +304,7 @@ public: \en Returns a pointer to the created fillet surface if successful, nullptr otherwise. \~ */ static MbFilletSurface * CreateKerbTouchingFillet( MbSurfaceCurve & curv1, bool sgn1, MbSurfaceCurve & curv2, bool sgn2, bool byFirst, VERSION vers ); + protected: /// \ru Конструктор для наследников обычной поверхности скругления. \en Constructor for inheritors of ordinary fillet surface. MbFilletSurface( MbSurfaceCurve & curv1, double d1, diff --git a/C3d/Include/surf_grid_surface.h b/C3d/Include/surf_grid_surface.h index 1b7fe50..1e1e73c 100644 --- a/C3d/Include/surf_grid_surface.h +++ b/C3d/Include/surf_grid_surface.h @@ -36,13 +36,14 @@ protected : size_t index[_C3D_3_]; ///< \ru Номера вершин треугольника в массиве точек. \en The numbers of vertices in points array. size_t neighbour[_C3D_3_]; ///< \ru Номера соседних треугольников. \en The numbers of neighbour triangles. SYS_MAX_T if it is absent. -// points[index[2]] +/* points[index[2]] // + // / \ // neighbour[2] / \ neighbour[1] // / \ // points[index[0]] +---------------+ points[index[1]] // neighbour[0] +*/ public : MbTrigon() { index[0] = SYS_MAX_T; index[1] = SYS_MAX_T; index[2] = SYS_MAX_T; diff --git a/C3d/Include/surf_lofted_surface.h b/C3d/Include/surf_lofted_surface.h index 14cc2b9..b863fff 100644 --- a/C3d/Include/surf_lofted_surface.h +++ b/C3d/Include/surf_lofted_surface.h @@ -445,7 +445,7 @@ public: \return \ru true - Нормаль установлена. \en True - The Normal installed. \~ */ - bool IsSetNormal( bool atStart ) { return atStart ? border1.setNormal : border2.setNormal; } + bool IsSetNormal( bool atStart ) const { return atStart ? border1.setNormal : border2.setNormal; } /** \} */ protected: diff --git a/C3d/Include/surf_section_surface.h b/C3d/Include/surf_section_surface.h index 91af8ab..e838034 100644 --- a/C3d/Include/surf_section_surface.h +++ b/C3d/Include/surf_section_surface.h @@ -252,6 +252,64 @@ public: VERSION vers, MbResultType & resType ); + /** \brief \ru Создание поверхности переменного сечения на заданном участке опорной кривой. + \en The mutable section surface creation on the given section of the reference curve. \~ + \details \ru Создание поверхности переменного сечения по опорной кривой и двум направляющим на заданном участке опорной кривой. + \en The mutable section surface creation by reference curve and guide curves on the given section of the reference curve. \~ + \param[in] rc - \ru Опорная кривая. + \en The reference curve (spine). \~ + \param[in] g1 - \ru Первая направляющая кривая. + \en The first guide curve. \~ + \param[in] g2 - \ru Вторая направляющая кривая (g1==g2 совпадает с первой при cs_Round). + \en The second guide curve (g1==g2 the same first guide for cs_Round). \~ + \param[in] c0 - \ru Дополнительная направляющая кривая (может быть nullptr). + \en The additional guide curve (may be nullptr). \~ + \param[in] f - \ru Форма сечения поверхности. + \en The form of the surface section. \~ + \param[in] sense - \ru Направление нормали поверхности направляющей кривой (для guide1==guide2). + \en The normal direction of guide curve surface (for guide1==guide2). \~ + \param[in] uBeg - \ru Минимальное значение первого параметра поверхности. + \en The minimum value of the first surface parameter. \~ + \param[in] uEnd - \ru Максимальное значение первого параметра поверхности. + \en The maximum value of the first surface parameter. \~ + \param[in] func - \ru Функция управления сечением поверхности. + \en Section control function. \~ + \param[in] patt - \ru Образующая кривая при form==cs_Shape. + \en Forming curve for form==cs_Shape. \~ + \param[in] rcTBeg - \ru Начальный параметр опорной кривой. + \en Start parameter of the reference curve. \~ + \param[in] rcTEnd - \ru Конечный параметр опорной кривой. + \en End parameter of the reference curve. \~ + \param[in] buildSag - \ru Угловое отклонение при движении по кривым и поверхностям. + \en Angular deviation while moving along curves and surfaces. \~ + \param[in] accuracy - \ru Точность построения. + \en The accuracy of building. \~ + \param[in] countBin - \ru Минимальное количество шагов при движении по опорной кривой. + \en Minimum number of steps while moving along the reference curve. \~ + \param[in] vers - \ru Версия поверхности. + \en The surface version. \~ + \param[out] resType - \ru Код ошибки построения. + \en Result code of building. \~ + \result \ru Возвращает построенную поверхность. + \en Returns the constructed surface. \~ + */ + static MbSectionSurface * Create( const MbCurve3D & rc, + const MbFunction * r1, const MbFunction * r2, + const MbCurve3D & g1, const MbCurve3D & g2, + const MbCurve3D * c0, + MbeSectionShape f, MbeSmoothForm sf, + bool sense, + double uBeg, double uEnd, + const MbFunction * func, + const MbCurve * patt, + double rcTBeg, + double rcTEnd, + double buildSag, + double accuracy, + uint32 countBin, + VERSION vers, + MbResultType & resType ); + /** \ru \name Общие функции геометрического объекта \en \name Common functions of a geometric object \{ */ @@ -370,6 +428,7 @@ public: MbCurve3D * CurveU( double v, MbRect1D *pRgn, bool bApprox = true ) const override; // \ru Пространственная копия линии v = const. \en Spatial copy of 'v = const'-line. MbCurve3D * CurveV( double u, MbRect1D *pRgn, bool bApprox = true ) const override; // \ru Пространственная копия линии u = const. \en Spatial copy of 'u = const'-line. + MbeParamDir GetFilletDirection( double accuracy = METRIC_REGION ) const override; // \ru Направление поверхности скругления. \en Direction of fillet surface. // \ru Построить касательные и нормальные плейсменты конструктивных плоскостей. \en Construct tangent and normal placements of constructive planes. bool CreateNormalPlacements ( const MbVector3D & axisZ, double angle, SArray & places, VERSION version = Math::DefaultMathVersion() ) const override; bool CreateTangentPlacements( const MbVector3D & axisZ, SArray & places ) const override; diff --git a/C3d/Include/surf_spine.h b/C3d/Include/surf_spine.h index 83de21f..809bc47 100644 --- a/C3d/Include/surf_spine.h +++ b/C3d/Include/surf_spine.h @@ -68,6 +68,7 @@ private: MbVector3D ort1; ///< \ru Вектор базиса в точке ortParam направляющей. \en A basis vector in the point ortParam of the spine. MbVector3D ort2; ///< \ru Вектор базиса в точке ortParam направляющей. \en A basis vector in the point ortParam of the spine. VERSION version; ///< \ru Версия расчета вектора direction. \en Version of vector "direction" calculation. + bool quadrExt; ///< \ru Флаг параболического продления. \en Flag of parabolic extension. //------------------------------------------------------------------------------ /** \brief \ru Вспомогательные данные. @@ -332,13 +333,13 @@ public: when getting out of the spine curve domain bounds. \{ */ /// \ru Точка на кривой. \en Point on the curve. - void PointOn ( double & t, MbCartPoint3D & p ) const { curve->PointOn(t,p); } + void PointOn ( double & t, MbCartPoint3D & p ) const; /// \ru Первая производная. \en The first derivative. - void FirstDer ( double & t, MbVector3D & p ) const { curve->FirstDer(t,p); } + void FirstDer ( double & t, MbVector3D & p ) const; /// \ru Вторая производная. \en The second derivative. - void SecondDer( double & t, MbVector3D & p ) const { curve->SecondDer(t,p); } + void SecondDer( double & t, MbVector3D & p ) const; /// \ru Третья производная. \en Third derivative. - void ThirdDer ( double & t, MbVector3D & p ) const { curve->ThirdDer(t,p); } + void ThirdDer ( double & t, MbVector3D & p ) const; /** \} */ /** \ru \name Функции для работы внутри и вне области определения направляющей кривой функции _PointOn, _FirstDer... корректируют параметры @@ -348,17 +349,16 @@ public: when getting out of the spine curve domain bounds. \{ */ /// \ru Точка на кривой. \en Point on the curve. - void _PointOn ( double t, MbCartPoint3D & p ) const { curve->_PointOn(t,p); } + void _PointOn ( double t, MbCartPoint3D & p ) const; /// \ru Первая производная. \en The first derivative. - void _FirstDer ( double t, MbVector3D & p ) const { curve->_FirstDer(t,p); } + void _FirstDer ( double t, MbVector3D & p ) const; /// \ru Вторая производная. \en The second derivative. - void _SecondDer( double t, MbVector3D & p ) const { curve->_SecondDer(t,p); } + void _SecondDer( double t, MbVector3D & p ) const; /// \ru Третья производная. \en Third derivative. - void _ThirdDer ( double t, MbVector3D & p ) const { curve->_ThirdDer(t,p); } + void _ThirdDer ( double t, MbVector3D & p ) const; /// \ru Вычислить значения точки и производных для заданного параметра. \en Calculate point and derivatives of object for given parameter. \~ virtual void Explore( double & t, bool ext, - MbCartPoint3D & pnt, MbVector3D & fir, MbVector3D * sec, MbVector3D * thir ) const - { curve->Explore( t, ext,pnt, fir, sec, thir ); } + MbCartPoint3D & pnt, MbVector3D & fir, MbVector3D * sec, MbVector3D * thir ) const; /** \} */ /** \ru \name Функции движения по направляющей кривой \en \name Function of moving by spine curve diff --git a/C3d/Include/templ_multimap.h b/C3d/Include/templ_multimap.h index 852f823..4f16696 100644 --- a/C3d/Include/templ_multimap.h +++ b/C3d/Include/templ_multimap.h @@ -266,7 +266,7 @@ size_t MultiMap::LowerBoundEx( const SArray= 0 && key <= pairs[firstNotLess].m_key ) + if ( firstNotLess <= last && key <= pairs[firstNotLess].m_key ) return firstNotLess; if ( key == pairs[last].m_key ) return last; @@ -330,7 +330,7 @@ size_t MultiMap::UpperBoundEx( const SArray= 0 && key < pairs[firstGreater].m_key ) + if ( firstGreater <= end && key < pairs[firstGreater].m_key ) return firstGreater; if ( key < pairs[last].m_key ) return last; diff --git a/C3d/Include/tool_err_handling.h b/C3d/Include/tool_err_handling.h index 96c30f9..e674329 100644 --- a/C3d/Include/tool_err_handling.h +++ b/C3d/Include/tool_err_handling.h @@ -107,31 +107,44 @@ public: */ static MbResultType SetError( MbResultType ); + /** \brief \ru Достаточно ли памяти для работы. \en Whether is enough memory to work. + \param[in] memRatio - \ru Максимальный процент использования памяти (при memRatio == -1 используются значения по умолчанию). + \en The maximum percentage of memory usage (with memRatio == -1, the default values are used). \~ + */ + static bool IsEnoughMemory( double memRatio = -1 ); + + /** \brief \ru Сбросить все данные. + \en Reset all data. + */ + static void Reset(); + + ///> \ru Следующие методы будут удалены. \en The next methods will be removed. + /** \brief \ru Инициализировать обработчик перед началом мониторинга ошибок. Возвращает true, если обработчик стартовал, или false, если обработчик уже работает. Парная функция Recover() должна вызываться, только если Init() вернул true. \en Initialize handler before starting error monitoring. Returns true if the handler is started or false if the handler is already working. - The paired function Recover() should be called only if Init() returnes true. + The paired function Recover() should be called only if Init() returns true. */ - static bool Init(); + DEPRECATE_DECLARE static bool Init(); /** \brief \ru Восстановиться, если обнаружена фатальная ошибка. \en Recover if a fatal error is detected. */ - static void Recover(); + DEPRECATE_DECLARE static void Recover(); - /** \brief \ru Достаточно ли памяти для работы. \en Whether is enough memory to work. + /** \brief \ru Коэффициент использования памяти [0.0, 1.0]. \en Memory use coefficient [0.0, 1.0]. */ - static bool IsEnoughMemory(); + DEPRECATE_DECLARE static double MemoryUseRatio(); /** \brief \ru Установить допустимый порог памяти для работы (Mb). \en Set an acceptable memory threshold for work (Mb). */ - static void SetMemoryThreshold( double ); + DEPRECATE_DECLARE static void SetMemoryThreshold( double memThreshold ); /** \brief \ru Установить порог памяти по умолчанию. \en Set default memory threshold. */ - static void ResetMemoryThreshold(); + DEPRECATE_DECLARE static void ResetMemoryThreshold(); }; #endif // __TOOL_ERR_HANDLING_H diff --git a/C3d/Include/topology.h b/C3d/Include/topology.h index 1891be1..76d7592 100644 --- a/C3d/Include/topology.h +++ b/C3d/Include/topology.h @@ -962,8 +962,8 @@ public : /// \ru Получить параметры разрезки для периодического ребра. \en Get the cutting parameters for a periodic edge. bool CutPeriodicEdge( const MbVector3D & eye, SSArray & trimParams, double & delT1, double & delT2 ) const; - /// \ru Согласовать тип кроивой пересечения. \en Agree on the type of intersection curve. - void AgreeBuildType( double tCurve ); + /// \ru Согласовать тип кривой пересечения. \en Agree on the type of intersection curve. + DEPRECATE_DECLARE void AgreeBuildType( double tCurve ); // \ru Объявление оператора присваивания без реализации, чтобы не было присваивания по умолчанию. \en The declaration of the assignment operator without implementation to prevent an assignment by default. OBVIOUS_PRIVATE_COPY( MbCurveEdge ) @@ -1504,7 +1504,7 @@ public: { MbFaceTemp * _temporal; ///< \ru Объект сопровождения грани (для скорости вычислений). \en An object for maintenance of a face (to improve calculations speed). MbFaceAuxiliaryData() : AuxiliaryData(), _temporal( nullptr ) {} - MbFaceAuxiliaryData( const MbFaceAuxiliaryData & ) : _temporal( nullptr ) {} + MbFaceAuxiliaryData( const MbFaceAuxiliaryData & ) : AuxiliaryData {}, _temporal( nullptr ) {} virtual ~MbFaceAuxiliaryData(); }; @@ -1526,9 +1526,9 @@ public: template MbFace( const Loops & bnds, const MbSurface & surf, bool sense ) : MbTopologyItem() - , loops ( bnds.size(), 1 ) , surface ( const_cast(&surf) ) , sameSense ( sense ) // признак совпадения нормали + , loops ( bnds.size(), 1 ) , cache ( nullptr ) { surface->AddRef(); diff --git a/C3d/Include/topology_item.h b/C3d/Include/topology_item.h index 09bceaf..c75cef2 100644 --- a/C3d/Include/topology_item.h +++ b/C3d/Include/topology_item.h @@ -158,7 +158,7 @@ public: virtual MbeTopologyType IsA() const = 0; /// \ru Подготовить объект к записи. \en Prepare an object for writing. - void PrepareWrite() const { SetRegistrable( GetUseCount() > 1 ? registrable : noRegistrable ); } + void PrepareWrite() const { SetRegistrable( (GetUseCount() > 1) ? registrable : noRegistrable ); } bool IsAVertex() const { return (IsA() == tt_Vertex); } ///< \ru Это вершина? \en Is it a vertex? bool IsAWireEdge() const { return (IsA() == tt_Edge); } ///< \ru Это ребро каркаса? \en Is it an edge of wireframe? diff --git a/C3d/Lib/x32/Debug/c3d.lib b/C3d/Lib/x32/Debug/c3d.lib index 665b6ad..1b5cc76 100644 Binary files a/C3d/Lib/x32/Debug/c3d.lib and b/C3d/Lib/x32/Debug/c3d.lib differ diff --git a/C3d/Lib/x32/Release/c3d.lib b/C3d/Lib/x32/Release/c3d.lib index 920b71d..1fd0cbe 100644 Binary files a/C3d/Lib/x32/Release/c3d.lib and b/C3d/Lib/x32/Release/c3d.lib differ diff --git a/C3d/Lib/x64/Debug/c3d.lib b/C3d/Lib/x64/Debug/c3d.lib index e45809b..b440091 100644 Binary files a/C3d/Lib/x64/Debug/c3d.lib and b/C3d/Lib/x64/Debug/c3d.lib differ diff --git a/C3d/Lib/x64/Release/c3d.lib b/C3d/Lib/x64/Release/c3d.lib index b0904e2..4d5e460 100644 Binary files a/C3d/Lib/x64/Release/c3d.lib and b/C3d/Lib/x64/Release/c3d.lib differ diff --git a/FreeImage/Include/FreeImage.h b/FreeImage/Include/FreeImage.h index e2d1c5a..12182cd 100644 --- a/FreeImage/Include/FreeImage.h +++ b/FreeImage/Include/FreeImage.h @@ -29,7 +29,7 @@ // Version information ------------------------------------------------------ #define FREEIMAGE_MAJOR_VERSION 3 -#define FREEIMAGE_MINOR_VERSION 17 +#define FREEIMAGE_MINOR_VERSION 18 #define FREEIMAGE_RELEASE_SERIAL 0 // Compiler options --------------------------------------------------------- @@ -75,7 +75,7 @@ // or define any of FREEIMAGE_BIGENDIAN and FREEIMAGE_LITTLEENDIAN directly // to specify the desired endianness. #if (!defined(FREEIMAGE_BIGENDIAN) && !defined(FREEIMAGE_LITTLEENDIAN)) - #if (defined(BYTE_ORDER) && BYTE_ORDER==BIG_ENDIAN) || (defined(__BYTE_ORDER) && __BYTE_ORDER==__BIG_ENDIAN) || defined(__BIG_ENDIAN__) +#if (defined(BYTE_ORDER) && BYTE_ORDER==BIG_ENDIAN) || (defined(__BYTE_ORDER) && __BYTE_ORDER==__BIG_ENDIAN) || (defined(__BYTE_ORDER) && __BYTE_ORDER==__ORDER_BIG_ENDIAN__) || defined(__BIG_ENDIAN__) #define FREEIMAGE_BIGENDIAN #endif // BYTE_ORDER #endif // !FREEIMAGE_[BIG|LITTLE]ENDIAN @@ -731,6 +731,9 @@ typedef void (DLL_CALLCONV *FI_InitProc)(Plugin *plugin, int format_id); #define PSD_DEFAULT 0 #define PSD_CMYK 1 //! reads tags for separated CMYK (default is conversion to RGB) #define PSD_LAB 2 //! reads tags for CIELab (default is conversion to RGB) +#define PSD_NONE 0x0100 //! save without any compression +#define PSD_RLE 0x0200 //! save using RLE compression +#define PSD_PSB 0x2000 //! save using Adobe Large Document Format (use | to combine with other save flags) #define RAS_DEFAULT 0 #define RAW_DEFAULT 0 //! load the file as linear RGB 48-bit #define RAW_PREVIEW 1 //! try to load the embedded JPEG preview with included Exif Data or default to RGB 24-bit @@ -873,13 +876,19 @@ DLL_API void DLL_CALLCONV FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP * DLL_API BOOL DLL_CALLCONV FreeImage_MovePage(FIMULTIBITMAP *bitmap, int target, int source); DLL_API BOOL DLL_CALLCONV FreeImage_GetLockedPageNumbers(FIMULTIBITMAP *bitmap, int *pages, int *count); -// Filetype request routines ------------------------------------------------ +// File type request routines ------------------------------------------------ DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileType(const char *filename, int size FI_DEFAULT(0)); DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeU(const wchar_t *filename, int size FI_DEFAULT(0)); DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeFromHandle(FreeImageIO *io, fi_handle handle, int size FI_DEFAULT(0)); DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeFromMemory(FIMEMORY *stream, int size FI_DEFAULT(0)); +DLL_API BOOL DLL_CALLCONV FreeImage_Validate(FREE_IMAGE_FORMAT fif, const char *filename); +DLL_API BOOL DLL_CALLCONV FreeImage_ValidateU(FREE_IMAGE_FORMAT fif, const wchar_t *filename); +DLL_API BOOL DLL_CALLCONV FreeImage_ValidateFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle); +DLL_API BOOL DLL_CALLCONV FreeImage_ValidateFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream); + + // Image type request routine ----------------------------------------------- DLL_API FREE_IMAGE_TYPE DLL_CALLCONV FreeImage_GetImageType(FIBITMAP *dib); @@ -979,8 +988,11 @@ DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To24_555(BYTE *target, BYTE *so DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To24_565(BYTE *target, BYTE *source, int width_in_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To24(BYTE *target, BYTE *source, int width_in_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To32_555(BYTE *target, BYTE *source, int width_in_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To32_565(BYTE *target, BYTE *source, int width_in_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To32(BYTE *target, BYTE *source, int width_in_pixels); @@ -1092,8 +1104,6 @@ DLL_API BOOL DLL_CALLCONV FreeImage_JPEGTransformCombinedFromMemory(FIMEMORY* sr // -------------------------------------------------------------------------- // rotation and flipping -/// @deprecated see FreeImage_Rotate -DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateClassic(FIBITMAP *dib, double angle); DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Rotate(FIBITMAP *dib, double angle, const void *bkcolor FI_DEFAULT(NULL)); DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateEx(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, BOOL use_mask); DLL_API BOOL DLL_CALLCONV FreeImage_FlipHorizontal(FIBITMAP *dib); diff --git a/FreeImage/Lib/x32/FreeImage.lib b/FreeImage/Lib/x32/FreeImage.lib index 28071aa..433ad8f 100644 Binary files a/FreeImage/Lib/x32/FreeImage.lib and b/FreeImage/Lib/x32/FreeImage.lib differ diff --git a/FreeImage/Lib/x64/FreeImage.lib b/FreeImage/Lib/x64/FreeImage.lib index 59e3d84..8a93d25 100644 Binary files a/FreeImage/Lib/x64/FreeImage.lib and b/FreeImage/Lib/x64/FreeImage.lib differ diff --git a/Lua/Lib/lua54D32.lib b/Lua/Lib/lua54D32.lib index dcf86f5..f27d290 100644 Binary files a/Lua/Lib/lua54D32.lib and b/Lua/Lib/lua54D32.lib differ diff --git a/Lua/Lib/lua54D32.pdb b/Lua/Lib/lua54D32.pdb index 072e6bb..9a3bee1 100644 Binary files a/Lua/Lib/lua54D32.pdb and b/Lua/Lib/lua54D32.pdb differ diff --git a/Lua/Lib/lua54D64.lib b/Lua/Lib/lua54D64.lib index e4b53b2..7a956a1 100644 Binary files a/Lua/Lib/lua54D64.lib and b/Lua/Lib/lua54D64.lib differ diff --git a/Lua/Lib/lua54D64.pdb b/Lua/Lib/lua54D64.pdb index ead5734..80b1b07 100644 Binary files a/Lua/Lib/lua54D64.pdb and b/Lua/Lib/lua54D64.pdb differ diff --git a/Lua/Lib/lua54R32.lib b/Lua/Lib/lua54R32.lib index c9c1300..b9bd056 100644 Binary files a/Lua/Lib/lua54R32.lib and b/Lua/Lib/lua54R32.lib differ diff --git a/Lua/Lib/lua54R64.lib b/Lua/Lib/lua54R64.lib index 54c3bfb..8910a95 100644 Binary files a/Lua/Lib/lua54R64.lib and b/Lua/Lib/lua54R64.lib differ diff --git a/fast_float/fast_float.h b/fast_float/fast_float.h new file mode 100644 index 0000000..f171216 --- /dev/null +++ b/fast_float/fast_float.h @@ -0,0 +1,4025 @@ +// fast_float by Daniel Lemire +// fast_float by João Paulo Magalhaes +// +// +// with contributions from Eugene Golushkov +// with contributions from Maksim Kita +// with contributions from Marcin Wojdyr +// with contributions from Neal Richardson +// with contributions from Tim Paine +// with contributions from Fabio Pellacini +// with contributions from Lénárd Szolnoki +// with contributions from Jan Pharago +// with contributions from Maya Warrier +// with contributions from Taha Khokhar +// with contributions from Anders Dalvander +// +// +// Licensed under the Apache License, Version 2.0, or the +// MIT License or the Boost License. This file may not be copied, +// modified, or distributed except according to those terms. +// +// MIT License Notice +// +// MIT License +// +// Copyright (c) 2021 The fast_float authors +// +// Permission is hereby granted, free of charge, to any +// person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the +// Software without restriction, including without +// limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice +// shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Apache License (Version 2.0) Notice +// +// Copyright 2021 The fast_float authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// +// BOOST License Notice +// +// Boost Software License - Version 1.0 - August 17th, 2003 +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +#ifndef FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H +#define FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H + +#ifdef __has_include +#if __has_include() +#include +#endif +#endif + +// Testing for https://wg21.link/N3652, adopted in C++14 +#if __cpp_constexpr >= 201304 +#define FASTFLOAT_CONSTEXPR14 constexpr +#else +#define FASTFLOAT_CONSTEXPR14 +#endif + +#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L +#define FASTFLOAT_HAS_BIT_CAST 1 +#else +#define FASTFLOAT_HAS_BIT_CAST 0 +#endif + +#if defined(__cpp_lib_is_constant_evaluated) && \ + __cpp_lib_is_constant_evaluated >= 201811L +#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 1 +#else +#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 0 +#endif + +// Testing for relevant C++20 constexpr library features +#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST && \ + __cpp_lib_constexpr_algorithms >= 201806L /*For std::copy and std::fill*/ +#define FASTFLOAT_CONSTEXPR20 constexpr +#define FASTFLOAT_IS_CONSTEXPR 1 +#else +#define FASTFLOAT_CONSTEXPR20 +#define FASTFLOAT_IS_CONSTEXPR 0 +#endif + +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +#define FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE 0 +#else +#define FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE 1 +#endif + +#endif // FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H + +#ifndef FASTFLOAT_FLOAT_COMMON_H +#define FASTFLOAT_FLOAT_COMMON_H + +#include +#include +#include +#include +#include +#include +#ifdef __has_include +#if __has_include() && (__cplusplus > 202002L || _MSVC_LANG > 202002L) +#include +#endif +#endif + +namespace fast_float { + +enum class chars_format : uint64_t; + +namespace detail { +constexpr chars_format basic_json_fmt = chars_format(1 << 5); +constexpr chars_format basic_fortran_fmt = chars_format(1 << 6); +} // namespace detail + +enum class chars_format : uint64_t { + scientific = 1 << 0, + fixed = 1 << 2, + hex = 1 << 3, + no_infnan = 1 << 4, + // RFC 8259: https://datatracker.ietf.org/doc/html/rfc8259#section-6 + json = uint64_t(detail::basic_json_fmt) | fixed | scientific | no_infnan, + // Extension of RFC 8259 where, e.g., "inf" and "nan" are allowed. + json_or_infnan = uint64_t(detail::basic_json_fmt) | fixed | scientific, + fortran = uint64_t(detail::basic_fortran_fmt) | fixed | scientific, + general = fixed | scientific, + allow_leading_plus = 1 << 7, + skip_white_space = 1 << 8, +}; + +template struct from_chars_result_t { + UC const *ptr; + std::errc ec; +}; +using from_chars_result = from_chars_result_t; + +template struct parse_options_t { + constexpr explicit parse_options_t(chars_format fmt = chars_format::general, + UC dot = UC('.'), int b = 10) + : format(fmt), decimal_point(dot), base(b) {} + + /** Which number formats are accepted */ + chars_format format; + /** The character used as decimal point */ + UC decimal_point; + /** The base used for integers */ + int base; +}; +using parse_options = parse_options_t; + +} // namespace fast_float + +#if FASTFLOAT_HAS_BIT_CAST +#include +#endif + +#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ + defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) || \ + defined(__MINGW64__) || defined(__s390x__) || \ + (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \ + defined(__PPC64LE__)) || \ + defined(__loongarch64)) +#define FASTFLOAT_64BIT 1 +#elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__arm__) || defined(_M_ARM) || defined(__ppc__) || \ + defined(__MINGW32__) || defined(__EMSCRIPTEN__)) +#define FASTFLOAT_32BIT 1 +#else + // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow. +// We can never tell the register width, but the SIZE_MAX is a good +// approximation. UINTPTR_MAX and INTPTR_MAX are optional, so avoid them for max +// portability. +#if SIZE_MAX == 0xffff +#error Unknown platform (16-bit, unsupported) +#elif SIZE_MAX == 0xffffffff +#define FASTFLOAT_32BIT 1 +#elif SIZE_MAX == 0xffffffffffffffff +#define FASTFLOAT_64BIT 1 +#else +#error Unknown platform (not 32-bit, not 64-bit?) +#endif +#endif + +#if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__)) || \ + (defined(_M_ARM64) && !defined(__MINGW32__)) +#include +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define FASTFLOAT_VISUAL_STUDIO 1 +#endif + +#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ +#define FASTFLOAT_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#elif defined _WIN32 +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#else +#if defined(__APPLE__) || defined(__FreeBSD__) +#include +#elif defined(sun) || defined(__sun) +#include +#elif defined(__MVS__) +#include +#else +#ifdef __has_include +#if __has_include() +#include +#endif //__has_include() +#endif //__has_include +#endif +# +#ifndef __BYTE_ORDER__ +// safe choice +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#endif +# +#ifndef __ORDER_LITTLE_ENDIAN__ +// safe choice +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#endif +# +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#else +#define FASTFLOAT_IS_BIG_ENDIAN 1 +#endif +#endif + +#if defined(__SSE2__) || (defined(FASTFLOAT_VISUAL_STUDIO) && \ + (defined(_M_AMD64) || defined(_M_X64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP == 2))) +#define FASTFLOAT_SSE2 1 +#endif + +#if defined(__aarch64__) || defined(_M_ARM64) +#define FASTFLOAT_NEON 1 +#endif + +#if defined(FASTFLOAT_SSE2) || defined(FASTFLOAT_NEON) +#define FASTFLOAT_HAS_SIMD 1 +#endif + +#if defined(__GNUC__) +// disable -Wcast-align=strict (GCC only) +#define FASTFLOAT_SIMD_DISABLE_WARNINGS \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wcast-align\"") +#else +#define FASTFLOAT_SIMD_DISABLE_WARNINGS +#endif + +#if defined(__GNUC__) +#define FASTFLOAT_SIMD_RESTORE_WARNINGS _Pragma("GCC diagnostic pop") +#else +#define FASTFLOAT_SIMD_RESTORE_WARNINGS +#endif + +#ifdef FASTFLOAT_VISUAL_STUDIO +#define fastfloat_really_inline __forceinline +#else +#define fastfloat_really_inline inline __attribute__((always_inline)) +#endif + +#ifndef FASTFLOAT_ASSERT +#define FASTFLOAT_ASSERT(x) \ + { ((void)(x)); } +#endif + +#ifndef FASTFLOAT_DEBUG_ASSERT +#define FASTFLOAT_DEBUG_ASSERT(x) \ + { ((void)(x)); } +#endif + +// rust style `try!()` macro, or `?` operator +#define FASTFLOAT_TRY(x) \ + { \ + if (!(x)) \ + return false; \ + } + +#define FASTFLOAT_ENABLE_IF(...) \ + typename std::enable_if<(__VA_ARGS__), int>::type + +namespace fast_float { + +fastfloat_really_inline constexpr bool cpp20_and_in_constexpr() { +#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED + return std::is_constant_evaluated(); +#else + return false; +#endif +} + +template +fastfloat_really_inline constexpr bool is_supported_float_type() { + return std::is_same::value || std::is_same::value +#if __STDCPP_FLOAT32_T__ + || std::is_same::value +#endif +#if __STDCPP_FLOAT64_T__ + || std::is_same::value +#endif + ; +} + +template +fastfloat_really_inline constexpr bool is_supported_char_type() { + return std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value; +} + +// Compares two ASCII strings in a case insensitive manner. +template +inline FASTFLOAT_CONSTEXPR14 bool +fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase, + size_t length) { + for (size_t i = 0; i < length; ++i) { + UC const actual = actual_mixedcase[i]; + if ((actual < 256 ? actual | 32 : actual) != expected_lowercase[i]) { + return false; + } + } + return true; +} + +#ifndef FLT_EVAL_METHOD +#error "FLT_EVAL_METHOD should be defined, please include cfloat." +#endif + +// a pointer and a length to a contiguous block of memory +template struct span { + const T *ptr; + size_t length; + constexpr span(const T *_ptr, size_t _length) : ptr(_ptr), length(_length) {} + constexpr span() : ptr(nullptr), length(0) {} + + constexpr size_t len() const noexcept { return length; } + + FASTFLOAT_CONSTEXPR14 const T &operator[](size_t index) const noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + return ptr[index]; + } +}; + +struct value128 { + uint64_t low; + uint64_t high; + constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {} + constexpr value128() : low(0), high(0) {} +}; + +/* Helper C++14 constexpr generic implementation of leading_zeroes */ +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int +leading_zeroes_generic(uint64_t input_num, int last_bit = 0) { + if (input_num & uint64_t(0xffffffff00000000)) { + input_num >>= 32; + last_bit |= 32; + } + if (input_num & uint64_t(0xffff0000)) { + input_num >>= 16; + last_bit |= 16; + } + if (input_num & uint64_t(0xff00)) { + input_num >>= 8; + last_bit |= 8; + } + if (input_num & uint64_t(0xf0)) { + input_num >>= 4; + last_bit |= 4; + } + if (input_num & uint64_t(0xc)) { + input_num >>= 2; + last_bit |= 2; + } + if (input_num & uint64_t(0x2)) { /* input_num >>= 1; */ + last_bit |= 1; + } + return 63 - last_bit; +} + +/* result might be undefined when input_num is zero */ +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 int +leading_zeroes(uint64_t input_num) { + assert(input_num > 0); + if (cpp20_and_in_constexpr()) { + return leading_zeroes_generic(input_num); + } +#ifdef FASTFLOAT_VISUAL_STUDIO +#if defined(_M_X64) || defined(_M_ARM64) + unsigned long leading_zero = 0; + // Search the mask data from most significant bit (MSB) + // to least significant bit (LSB) for a set bit (1). + _BitScanReverse64(&leading_zero, input_num); + return (int)(63 - leading_zero); +#else + return leading_zeroes_generic(input_num); +#endif +#else + return __builtin_clzll(input_num); +#endif +} + +// slow emulation routine for 32-bit +fastfloat_really_inline constexpr uint64_t emulu(uint32_t x, uint32_t y) { + return x * (uint64_t)y; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t +umul128_generic(uint64_t ab, uint64_t cd, uint64_t *hi) { + uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd); + uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd); + uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32)); + uint64_t adbc_carry = (uint64_t)(adbc < ad); + uint64_t lo = bd + (adbc << 32); + *hi = emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) + + (adbc_carry << 32) + (uint64_t)(lo < bd); + return lo; +} + +#ifdef FASTFLOAT_32BIT + +// slow emulation routine for 32-bit +#if !defined(__MINGW64__) +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t _umul128(uint64_t ab, + uint64_t cd, + uint64_t *hi) { + return umul128_generic(ab, cd, hi); +} +#endif // !__MINGW64__ + +#endif // FASTFLOAT_32BIT + +// compute 64-bit a*b +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128 +full_multiplication(uint64_t a, uint64_t b) { + if (cpp20_and_in_constexpr()) { + value128 answer; + answer.low = umul128_generic(a, b, &answer.high); + return answer; + } + value128 answer; +#if defined(_M_ARM64) && !defined(__MINGW32__) + // ARM64 has native support for 64-bit multiplications, no need to emulate + // But MinGW on ARM64 doesn't have native support for 64-bit multiplications + answer.high = __umulh(a, b); + answer.low = a * b; +#elif defined(FASTFLOAT_32BIT) || \ + (defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64)) + answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64 +#elif defined(FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__) + __uint128_t r = ((__uint128_t)a) * b; + answer.low = uint64_t(r); + answer.high = uint64_t(r >> 64); +#else + answer.low = umul128_generic(a, b, &answer.high); +#endif + return answer; +} + +struct adjusted_mantissa { + uint64_t mantissa{0}; + int32_t power2{0}; // a negative value indicates an invalid result + adjusted_mantissa() = default; + constexpr bool operator==(const adjusted_mantissa &o) const { + return mantissa == o.mantissa && power2 == o.power2; + } + constexpr bool operator!=(const adjusted_mantissa &o) const { + return mantissa != o.mantissa || power2 != o.power2; + } +}; + +// Bias so we can get the real exponent with an invalid adjusted_mantissa. +constexpr static int32_t invalid_am_bias = -0x8000; + +// used for binary_format_lookup_tables::max_mantissa +constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5; + +template struct binary_format_lookup_tables; + +template struct binary_format : binary_format_lookup_tables { + using equiv_uint = + typename std::conditional::type; + + static inline constexpr int mantissa_explicit_bits(); + static inline constexpr int minimum_exponent(); + static inline constexpr int infinite_power(); + static inline constexpr int sign_index(); + static inline constexpr int + min_exponent_fast_path(); // used when fegetround() == FE_TONEAREST + static inline constexpr int max_exponent_fast_path(); + static inline constexpr int max_exponent_round_to_even(); + static inline constexpr int min_exponent_round_to_even(); + static inline constexpr uint64_t max_mantissa_fast_path(int64_t power); + static inline constexpr uint64_t + max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST + static inline constexpr int largest_power_of_ten(); + static inline constexpr int smallest_power_of_ten(); + static inline constexpr T exact_power_of_ten(int64_t power); + static inline constexpr size_t max_digits(); + static inline constexpr equiv_uint exponent_mask(); + static inline constexpr equiv_uint mantissa_mask(); + static inline constexpr equiv_uint hidden_bit_mask(); +}; + +template struct binary_format_lookup_tables { + static constexpr double powers_of_ten[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, + 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; + + // Largest integer value v so that (5**index * v) <= 1<<53. + // 0x20000000000000 == 1 << 53 + static constexpr uint64_t max_mantissa[] = { + 0x20000000000000, + 0x20000000000000 / 5, + 0x20000000000000 / (5 * 5), + 0x20000000000000 / (5 * 5 * 5), + 0x20000000000000 / (5 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555), + 0x20000000000000 / (constant_55555 * 5), + 0x20000000000000 / (constant_55555 * 5 * 5), + 0x20000000000000 / (constant_55555 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * 5 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555), + 0x20000000000000 / (constant_55555 * constant_55555 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * 5 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * constant_55555), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5 * 5 * 5 * 5)}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template +constexpr double binary_format_lookup_tables::powers_of_ten[]; + +template +constexpr uint64_t binary_format_lookup_tables::max_mantissa[]; + +#endif + +template struct binary_format_lookup_tables { + static constexpr float powers_of_ten[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, + 1e6f, 1e7f, 1e8f, 1e9f, 1e10f}; + + // Largest integer value v so that (5**index * v) <= 1<<24. + // 0x1000000 == 1<<24 + static constexpr uint64_t max_mantissa[] = { + 0x1000000, + 0x1000000 / 5, + 0x1000000 / (5 * 5), + 0x1000000 / (5 * 5 * 5), + 0x1000000 / (5 * 5 * 5 * 5), + 0x1000000 / (constant_55555), + 0x1000000 / (constant_55555 * 5), + 0x1000000 / (constant_55555 * 5 * 5), + 0x1000000 / (constant_55555 * 5 * 5 * 5), + 0x1000000 / (constant_55555 * 5 * 5 * 5 * 5), + 0x1000000 / (constant_55555 * constant_55555), + 0x1000000 / (constant_55555 * constant_55555 * 5)}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template +constexpr float binary_format_lookup_tables::powers_of_ten[]; + +template +constexpr uint64_t binary_format_lookup_tables::max_mantissa[]; + +#endif + +template <> +inline constexpr int binary_format::min_exponent_fast_path() { +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return 0; +#else + return -22; +#endif +} + +template <> +inline constexpr int binary_format::min_exponent_fast_path() { +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return 0; +#else + return -10; +#endif +} + +template <> +inline constexpr int binary_format::mantissa_explicit_bits() { + return 52; +} +template <> +inline constexpr int binary_format::mantissa_explicit_bits() { + return 23; +} + +template <> +inline constexpr int binary_format::max_exponent_round_to_even() { + return 23; +} + +template <> +inline constexpr int binary_format::max_exponent_round_to_even() { + return 10; +} + +template <> +inline constexpr int binary_format::min_exponent_round_to_even() { + return -4; +} + +template <> +inline constexpr int binary_format::min_exponent_round_to_even() { + return -17; +} + +template <> inline constexpr int binary_format::minimum_exponent() { + return -1023; +} +template <> inline constexpr int binary_format::minimum_exponent() { + return -127; +} + +template <> inline constexpr int binary_format::infinite_power() { + return 0x7FF; +} +template <> inline constexpr int binary_format::infinite_power() { + return 0xFF; +} + +template <> inline constexpr int binary_format::sign_index() { + return 63; +} +template <> inline constexpr int binary_format::sign_index() { + return 31; +} + +template <> +inline constexpr int binary_format::max_exponent_fast_path() { + return 22; +} +template <> +inline constexpr int binary_format::max_exponent_fast_path() { + return 10; +} + +template <> +inline constexpr uint64_t binary_format::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} +template <> +inline constexpr uint64_t +binary_format::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 22 + // + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)max_mantissa[0], max_mantissa[power]; +} +template <> +inline constexpr uint64_t binary_format::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} +template <> +inline constexpr uint64_t +binary_format::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 10 + // + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)max_mantissa[0], max_mantissa[power]; +} + +template <> +inline constexpr double +binary_format::exact_power_of_ten(int64_t power) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)powers_of_ten[0], powers_of_ten[power]; +} +template <> +inline constexpr float binary_format::exact_power_of_ten(int64_t power) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)powers_of_ten[0], powers_of_ten[power]; +} + +template <> inline constexpr int binary_format::largest_power_of_ten() { + return 308; +} +template <> inline constexpr int binary_format::largest_power_of_ten() { + return 38; +} + +template <> +inline constexpr int binary_format::smallest_power_of_ten() { + return -342; +} +template <> inline constexpr int binary_format::smallest_power_of_ten() { + return -64; +} + +template <> inline constexpr size_t binary_format::max_digits() { + return 769; +} +template <> inline constexpr size_t binary_format::max_digits() { + return 114; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::exponent_mask() { + return 0x7F800000; +} +template <> +inline constexpr binary_format::equiv_uint +binary_format::exponent_mask() { + return 0x7FF0000000000000; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::mantissa_mask() { + return 0x007FFFFF; +} +template <> +inline constexpr binary_format::equiv_uint +binary_format::mantissa_mask() { + return 0x000FFFFFFFFFFFFF; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::hidden_bit_mask() { + return 0x00800000; +} +template <> +inline constexpr binary_format::equiv_uint +binary_format::hidden_bit_mask() { + return 0x0010000000000000; +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +to_float(bool negative, adjusted_mantissa am, T &value) { + using fastfloat_uint = typename binary_format::equiv_uint; + fastfloat_uint word = (fastfloat_uint)am.mantissa; + word |= fastfloat_uint(am.power2) + << binary_format::mantissa_explicit_bits(); + word |= fastfloat_uint(negative) << binary_format::sign_index(); +#if FASTFLOAT_HAS_BIT_CAST + value = std::bit_cast(word); +#else + ::memcpy(&value, &word, sizeof(T)); +#endif +} + +template struct space_lut { + static constexpr bool value[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template constexpr bool space_lut::value[]; + +#endif + +template constexpr bool is_space(UC c) { + return c < 256 && space_lut<>::value[uint8_t(c)]; +} + +template static constexpr uint64_t int_cmp_zeros() { + static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4), + "Unsupported character size"); + return (sizeof(UC) == 1) ? 0x3030303030303030 + : (sizeof(UC) == 2) + ? (uint64_t(UC('0')) << 48 | uint64_t(UC('0')) << 32 | + uint64_t(UC('0')) << 16 | UC('0')) + : (uint64_t(UC('0')) << 32 | UC('0')); +} +template static constexpr int int_cmp_len() { + return sizeof(uint64_t) / sizeof(UC); +} +template static constexpr UC const *str_const_nan() { + return nullptr; +} +template <> constexpr char const *str_const_nan() { return "nan"; } +template <> constexpr wchar_t const *str_const_nan() { return L"nan"; } +template <> constexpr char16_t const *str_const_nan() { + return u"nan"; +} +template <> constexpr char32_t const *str_const_nan() { + return U"nan"; +} +template static constexpr UC const *str_const_inf() { + return nullptr; +} +template <> constexpr char const *str_const_inf() { return "infinity"; } +template <> constexpr wchar_t const *str_const_inf() { + return L"infinity"; +} +template <> constexpr char16_t const *str_const_inf() { + return u"infinity"; +} +template <> constexpr char32_t const *str_const_inf() { + return U"infinity"; +} + +template struct int_luts { + static constexpr uint8_t chdigit[] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, + 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255}; + + static constexpr size_t maxdigits_u64[] = { + 64, 41, 32, 28, 25, 23, 22, 21, 20, 19, 18, 18, 17, 17, 16, 16, 16, 16, + 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13}; + + static constexpr uint64_t min_safe_u64[] = { + 9223372036854775808ull, 12157665459056928801ull, 4611686018427387904, + 7450580596923828125, 4738381338321616896, 3909821048582988049, + 9223372036854775808ull, 12157665459056928801ull, 10000000000000000000ull, + 5559917313492231481, 2218611106740436992, 8650415919381337933, + 2177953337809371136, 6568408355712890625, 1152921504606846976, + 2862423051509815793, 6746640616477458432, 15181127029874798299ull, + 1638400000000000000, 3243919932521508681, 6221821273427820544, + 11592836324538749809ull, 876488338465357824, 1490116119384765625, + 2481152873203736576, 4052555153018976267, 6502111422497947648, + 10260628712958602189ull, 15943230000000000000ull, 787662783788549761, + 1152921504606846976, 1667889514952984961, 2386420683693101056, + 3379220508056640625, 4738381338321616896}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template constexpr uint8_t int_luts::chdigit[]; + +template constexpr size_t int_luts::maxdigits_u64[]; + +template constexpr uint64_t int_luts::min_safe_u64[]; + +#endif + +template +fastfloat_really_inline constexpr uint8_t ch_to_digit(UC c) { + return int_luts<>::chdigit[static_cast(c)]; +} + +fastfloat_really_inline constexpr size_t max_digits_u64(int base) { + return int_luts<>::maxdigits_u64[base - 2]; +} + +// If a u64 is exactly max_digits_u64() in length, this is +// the value below which it has definitely overflowed. +fastfloat_really_inline constexpr uint64_t min_safe_u64(int base) { + return int_luts<>::min_safe_u64[base - 2]; +} + +constexpr chars_format operator~(chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(~static_cast(rhs)); +} + +constexpr chars_format operator&(chars_format lhs, chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(static_cast(lhs) & + static_cast(rhs)); +} + +constexpr chars_format operator|(chars_format lhs, chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(static_cast(lhs) | + static_cast(rhs)); +} + +constexpr chars_format operator^(chars_format lhs, chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(static_cast(lhs) ^ + static_cast(rhs)); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format & +operator&=(chars_format &lhs, chars_format rhs) noexcept { + return lhs = (lhs & rhs); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format & +operator|=(chars_format &lhs, chars_format rhs) noexcept { + return lhs = (lhs | rhs); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format & +operator^=(chars_format &lhs, chars_format rhs) noexcept { + return lhs = (lhs ^ rhs); +} + +namespace detail { +// adjust for deprecated feature macros +constexpr chars_format adjust_for_feature_macros(chars_format fmt) { + return fmt +#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS + | chars_format::allow_leading_plus +#endif +#ifdef FASTFLOAT_SKIP_WHITE_SPACE + | chars_format::skip_white_space +#endif + ; +} +} // namespace detail + +} // namespace fast_float + +#endif + + +#ifndef FASTFLOAT_FAST_FLOAT_H +#define FASTFLOAT_FAST_FLOAT_H + + +namespace fast_float { +/** + * This function parses the character sequence [first,last) for a number. It + * parses floating-point numbers expecting a locale-indepent format equivalent + * to what is used by std::strtod in the default ("C") locale. The resulting + * floating-point value is the closest floating-point values (using either float + * or double), using the "round to even" convention for values that would + * otherwise fall right in-between two values. That is, we provide exact parsing + * according to the IEEE standard. + * + * Given a successful parse, the pointer (`ptr`) in the returned value is set to + * point right after the parsed number, and the `value` referenced is set to the + * parsed value. In case of error, the returned `ec` contains a representative + * error, otherwise the default (`std::errc()`) value is stored. + * + * The implementation does not throw and does not allocate memory (e.g., with + * `new` or `malloc`). + * + * Like the C++17 standard, the `fast_float::from_chars` functions take an + * optional last argument of the type `fast_float::chars_format`. It is a bitset + * value: we check whether `fmt & fast_float::chars_format::fixed` and `fmt & + * fast_float::chars_format::scientific` are set to determine whether we allow + * the fixed point and scientific notation respectively. The default is + * `fast_float::chars_format::general` which allows both `fixed` and + * `scientific`. + */ +template ())> +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, + chars_format fmt = chars_format::general) noexcept; + +/** + * Like from_chars, but accepts an `options` argument to govern number parsing. + * Both for floating-point types and integer types. + */ +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept; + +/** + * from_chars for integer types. + */ +template ())> +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, int base = 10) noexcept; + +} // namespace fast_float +#endif // FASTFLOAT_FAST_FLOAT_H + +#ifndef FASTFLOAT_ASCII_NUMBER_H +#define FASTFLOAT_ASCII_NUMBER_H + +#include +#include +#include +#include +#include +#include + + +#ifdef FASTFLOAT_SSE2 +#include +#endif + +#ifdef FASTFLOAT_NEON +#include +#endif + +namespace fast_float { + +template fastfloat_really_inline constexpr bool has_simd_opt() { +#ifdef FASTFLOAT_HAS_SIMD + return std::is_same::value; +#else + return false; +#endif +} + +// Next function can be micro-optimized, but compilers are entirely +// able to optimize it well. +template +fastfloat_really_inline constexpr bool is_integer(UC c) noexcept { + return !(c > UC('9') || c < UC('0')); +} + +fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) { + return (val & 0xFF00000000000000) >> 56 | (val & 0x00FF000000000000) >> 40 | + (val & 0x0000FF0000000000) >> 24 | (val & 0x000000FF00000000) >> 8 | + (val & 0x00000000FF000000) << 8 | (val & 0x0000000000FF0000) << 24 | + (val & 0x000000000000FF00) << 40 | (val & 0x00000000000000FF) << 56; +} + +// Read 8 UC into a u64. Truncates UC if not char. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +read8_to_u64(const UC *chars) { + if (cpp20_and_in_constexpr() || !std::is_same::value) { + uint64_t val = 0; + for (int i = 0; i < 8; ++i) { + val |= uint64_t(uint8_t(*chars)) << (i * 8); + ++chars; + } + return val; + } + uint64_t val; + ::memcpy(&val, chars, sizeof(uint64_t)); +#if FASTFLOAT_IS_BIG_ENDIAN == 1 + // Need to read as-if the number was in little-endian order. + val = byteswap(val); +#endif + return val; +} + +#ifdef FASTFLOAT_SSE2 + +fastfloat_really_inline uint64_t simd_read8_to_u64(const __m128i data) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + const __m128i packed = _mm_packus_epi16(data, data); +#ifdef FASTFLOAT_64BIT + return uint64_t(_mm_cvtsi128_si64(packed)); +#else + uint64_t value; + // Visual Studio + older versions of GCC don't support _mm_storeu_si64 + _mm_storel_epi64(reinterpret_cast<__m128i *>(&value), packed); + return value; +#endif + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +fastfloat_really_inline uint64_t simd_read8_to_u64(const char16_t *chars) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + return simd_read8_to_u64( + _mm_loadu_si128(reinterpret_cast(chars))); + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +#elif defined(FASTFLOAT_NEON) + +fastfloat_really_inline uint64_t simd_read8_to_u64(const uint16x8_t data) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + uint8x8_t utf8_packed = vmovn_u16(data); + return vget_lane_u64(vreinterpret_u64_u8(utf8_packed), 0); + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +fastfloat_really_inline uint64_t simd_read8_to_u64(const char16_t *chars) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + return simd_read8_to_u64( + vld1q_u16(reinterpret_cast(chars))); + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +#endif // FASTFLOAT_SSE2 + +// MSVC SFINAE is broken pre-VS2017 +#if defined(_MSC_VER) && _MSC_VER <= 1900 +template +#else +template ()) = 0> +#endif +// dummy for compile +uint64_t simd_read8_to_u64(UC const *) { + return 0; +} + +// credit @aqrit +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t +parse_eight_digits_unrolled(uint64_t val) { + const uint64_t mask = 0x000000FF000000FF; + const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32) + const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32) + val -= 0x3030303030303030; + val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8; + val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32; + return uint32_t(val); +} + +// Call this if chars are definitely 8 digits. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint32_t +parse_eight_digits_unrolled(UC const *chars) noexcept { + if (cpp20_and_in_constexpr() || !has_simd_opt()) { + return parse_eight_digits_unrolled(read8_to_u64(chars)); // truncation okay + } + return parse_eight_digits_unrolled(simd_read8_to_u64(chars)); +} + +// credit @aqrit +fastfloat_really_inline constexpr bool +is_made_of_eight_digits_fast(uint64_t val) noexcept { + return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) & + 0x8080808080808080)); +} + +#ifdef FASTFLOAT_HAS_SIMD + +// Call this if chars might not be 8 digits. +// Using this style (instead of is_made_of_eight_digits_fast() then +// parse_eight_digits_unrolled()) ensures we don't load SIMD registers twice. +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +simd_parse_if_eight_digits_unrolled(const char16_t *chars, + uint64_t &i) noexcept { + if (cpp20_and_in_constexpr()) { + return false; + } +#ifdef FASTFLOAT_SSE2 + FASTFLOAT_SIMD_DISABLE_WARNINGS + const __m128i data = + _mm_loadu_si128(reinterpret_cast(chars)); + + // (x - '0') <= 9 + // http://0x80.pl/articles/simd-parsing-int-sequences.html + const __m128i t0 = _mm_add_epi16(data, _mm_set1_epi16(32720)); + const __m128i t1 = _mm_cmpgt_epi16(t0, _mm_set1_epi16(-32759)); + + if (_mm_movemask_epi8(t1) == 0) { + i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data)); + return true; + } else + return false; + FASTFLOAT_SIMD_RESTORE_WARNINGS +#elif defined(FASTFLOAT_NEON) + FASTFLOAT_SIMD_DISABLE_WARNINGS + const uint16x8_t data = vld1q_u16(reinterpret_cast(chars)); + + // (x - '0') <= 9 + // http://0x80.pl/articles/simd-parsing-int-sequences.html + const uint16x8_t t0 = vsubq_u16(data, vmovq_n_u16('0')); + const uint16x8_t mask = vcltq_u16(t0, vmovq_n_u16('9' - '0' + 1)); + + if (vminvq_u16(mask) == 0xFFFF) { + i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data)); + return true; + } else + return false; + FASTFLOAT_SIMD_RESTORE_WARNINGS +#else + (void)chars; + (void)i; + return false; +#endif // FASTFLOAT_SSE2 +} + +#endif // FASTFLOAT_HAS_SIMD + +// MSVC SFINAE is broken pre-VS2017 +#if defined(_MSC_VER) && _MSC_VER <= 1900 +template +#else +template ()) = 0> +#endif +// dummy for compile +bool simd_parse_if_eight_digits_unrolled(UC const *, uint64_t &) { + return 0; +} + +template ::value) = 0> +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +loop_parse_if_eight_digits(const UC *&p, const UC *const pend, uint64_t &i) { + if (!has_simd_opt()) { + return; + } + while ((std::distance(p, pend) >= 8) && + simd_parse_if_eight_digits_unrolled( + p, i)) { // in rare cases, this will overflow, but that's ok + p += 8; + } +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +loop_parse_if_eight_digits(const char *&p, const char *const pend, + uint64_t &i) { + // optimizes better than parse_if_eight_digits_unrolled() for UC = char. + while ((std::distance(p, pend) >= 8) && + is_made_of_eight_digits_fast(read8_to_u64(p))) { + i = i * 100000000 + + parse_eight_digits_unrolled(read8_to_u64( + p)); // in rare cases, this will overflow, but that's ok + p += 8; + } +} + +enum class parse_error { + no_error, + // [JSON-only] The minus sign must be followed by an integer. + missing_integer_after_sign, + // A sign must be followed by an integer or dot. + missing_integer_or_dot_after_sign, + // [JSON-only] The integer part must not have leading zeros. + leading_zeros_in_integer_part, + // [JSON-only] The integer part must have at least one digit. + no_digits_in_integer_part, + // [JSON-only] If there is a decimal point, there must be digits in the + // fractional part. + no_digits_in_fractional_part, + // The mantissa must have at least one digit. + no_digits_in_mantissa, + // Scientific notation requires an exponential part. + missing_exponential_part, +}; + +template struct parsed_number_string_t { + int64_t exponent{0}; + uint64_t mantissa{0}; + UC const *lastmatch{nullptr}; + bool negative{false}; + bool valid{false}; + bool too_many_digits{false}; + // contains the range of the significant digits + span integer{}; // non-nullable + span fraction{}; // nullable + parse_error error{parse_error::no_error}; +}; + +using byte_span = span; +using parsed_number_string = parsed_number_string_t; + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t +report_parse_error(UC const *p, parse_error error) { + parsed_number_string_t answer; + answer.valid = false; + answer.lastmatch = p; + answer.error = error; + return answer; +} + +// Assuming that you use no more than 19 digits, this will +// parse an ASCII string. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t +parse_number_string(UC const *p, UC const *pend, + parse_options_t options) noexcept { + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + UC const decimal_point = options.decimal_point; + + parsed_number_string_t answer; + answer.valid = false; + answer.too_many_digits = false; + // assume p < pend, so dereference without checks; + answer.negative = (*p == UC('-')); + // C++17 20.19.3.(7.1) explicitly forbids '+' sign here + if ((*p == UC('-')) || + (uint64_t(fmt & chars_format::allow_leading_plus) && + !uint64_t(fmt & detail::basic_json_fmt) && *p == UC('+'))) { + ++p; + if (p == pend) { + return report_parse_error( + p, parse_error::missing_integer_or_dot_after_sign); + } + if (uint64_t(fmt & detail::basic_json_fmt)) { + if (!is_integer(*p)) { // a sign must be followed by an integer + return report_parse_error(p, + parse_error::missing_integer_after_sign); + } + } else { + if (!is_integer(*p) && + (*p != + decimal_point)) { // a sign must be followed by an integer or the dot + return report_parse_error( + p, parse_error::missing_integer_or_dot_after_sign); + } + } + } + UC const *const start_digits = p; + + uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad) + + while ((p != pend) && is_integer(*p)) { + // a multiplication by 10 is cheaper than an arbitrary integer + // multiplication + i = 10 * i + + uint64_t(*p - + UC('0')); // might overflow, we will handle the overflow later + ++p; + } + UC const *const end_of_integer_part = p; + int64_t digit_count = int64_t(end_of_integer_part - start_digits); + answer.integer = span(start_digits, size_t(digit_count)); + if (uint64_t(fmt & detail::basic_json_fmt)) { + // at least 1 digit in integer part, without leading zeros + if (digit_count == 0) { + return report_parse_error(p, parse_error::no_digits_in_integer_part); + } + if ((start_digits[0] == UC('0') && digit_count > 1)) { + return report_parse_error(start_digits, + parse_error::leading_zeros_in_integer_part); + } + } + + int64_t exponent = 0; + const bool has_decimal_point = (p != pend) && (*p == decimal_point); + if (has_decimal_point) { + ++p; + UC const *before = p; + // can occur at most twice without overflowing, but let it occur more, since + // for integers with many digits, digit parsing is the primary bottleneck. + loop_parse_if_eight_digits(p, pend, i); + + while ((p != pend) && is_integer(*p)) { + uint8_t digit = uint8_t(*p - UC('0')); + ++p; + i = i * 10 + digit; // in rare cases, this will overflow, but that's ok + } + exponent = before - p; + answer.fraction = span(before, size_t(p - before)); + digit_count -= exponent; + } + if (uint64_t(fmt & detail::basic_json_fmt)) { + // at least 1 digit in fractional part + if (has_decimal_point && exponent == 0) { + return report_parse_error(p, + parse_error::no_digits_in_fractional_part); + } + } else if (digit_count == + 0) { // we must have encountered at least one integer! + return report_parse_error(p, parse_error::no_digits_in_mantissa); + } + int64_t exp_number = 0; // explicit exponential part + if ((uint64_t(fmt & chars_format::scientific) && (p != pend) && + ((UC('e') == *p) || (UC('E') == *p))) || + (uint64_t(fmt & detail::basic_fortran_fmt) && (p != pend) && + ((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) || + (UC('D') == *p)))) { + UC const *location_of_e = p; + if ((UC('e') == *p) || (UC('E') == *p) || (UC('d') == *p) || + (UC('D') == *p)) { + ++p; + } + bool neg_exp = false; + if ((p != pend) && (UC('-') == *p)) { + neg_exp = true; + ++p; + } else if ((p != pend) && + (UC('+') == + *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1) + ++p; + } + if ((p == pend) || !is_integer(*p)) { + if (!uint64_t(fmt & chars_format::fixed)) { + // The exponential part is invalid for scientific notation, so it must + // be a trailing token for fixed notation. However, fixed notation is + // disabled, so report a scientific notation error. + return report_parse_error(p, parse_error::missing_exponential_part); + } + // Otherwise, we will be ignoring the 'e'. + p = location_of_e; + } else { + while ((p != pend) && is_integer(*p)) { + uint8_t digit = uint8_t(*p - UC('0')); + if (exp_number < 0x10000000) { + exp_number = 10 * exp_number + digit; + } + ++p; + } + if (neg_exp) { + exp_number = -exp_number; + } + exponent += exp_number; + } + } else { + // If it scientific and not fixed, we have to bail out. + if (uint64_t(fmt & chars_format::scientific) && + !uint64_t(fmt & chars_format::fixed)) { + return report_parse_error(p, parse_error::missing_exponential_part); + } + } + answer.lastmatch = p; + answer.valid = true; + + // If we frequently had to deal with long strings of digits, + // we could extend our code by using a 128-bit integer instead + // of a 64-bit integer. However, this is uncommon. + // + // We can deal with up to 19 digits. + if (digit_count > 19) { // this is uncommon + // It is possible that the integer had an overflow. + // We have to handle the case where we have 0.0000somenumber. + // We need to be mindful of the case where we only have zeroes... + // E.g., 0.000000000...000. + UC const *start = start_digits; + while ((start != pend) && (*start == UC('0') || *start == decimal_point)) { + if (*start == UC('0')) { + digit_count--; + } + start++; + } + + if (digit_count > 19) { + answer.too_many_digits = true; + // Let us start again, this time, avoiding overflows. + // We don't need to check if is_integer, since we use the + // pre-tokenized spans from above. + i = 0; + p = answer.integer.ptr; + UC const *int_end = p + answer.integer.len(); + const uint64_t minimal_nineteen_digit_integer{1000000000000000000}; + while ((i < minimal_nineteen_digit_integer) && (p != int_end)) { + i = i * 10 + uint64_t(*p - UC('0')); + ++p; + } + if (i >= minimal_nineteen_digit_integer) { // We have a big integers + exponent = end_of_integer_part - p + exp_number; + } else { // We have a value with a fractional component. + p = answer.fraction.ptr; + UC const *frac_end = p + answer.fraction.len(); + while ((i < minimal_nineteen_digit_integer) && (p != frac_end)) { + i = i * 10 + uint64_t(*p - UC('0')); + ++p; + } + exponent = answer.fraction.ptr - p + exp_number; + } + // We have now corrected both exponent and i, to a truncated value + } + } + answer.exponent = exponent; + answer.mantissa = i; + return answer; +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t +parse_int_string(UC const *p, UC const *pend, T &value, + parse_options_t options) { + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + int const base = options.base; + + from_chars_result_t answer; + + UC const *const first = p; + + bool const negative = (*p == UC('-')); + if (!std::is_signed::value && negative) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + if ((*p == UC('-')) || + (uint64_t(fmt & chars_format::allow_leading_plus) && (*p == UC('+')))) { + ++p; + } + + UC const *const start_num = p; + + while (p != pend && *p == UC('0')) { + ++p; + } + + const bool has_leading_zeros = p > start_num; + + UC const *const start_digits = p; + + uint64_t i = 0; + if (base == 10) { + loop_parse_if_eight_digits(p, pend, i); // use SIMD if possible + } + while (p != pend) { + uint8_t digit = ch_to_digit(*p); + if (digit >= base) { + break; + } + i = uint64_t(base) * i + digit; // might overflow, check this later + p++; + } + + size_t digit_count = size_t(p - start_digits); + + if (digit_count == 0) { + if (has_leading_zeros) { + value = 0; + answer.ec = std::errc(); + answer.ptr = p; + } else { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + } + return answer; + } + + answer.ptr = p; + + // check u64 overflow + size_t max_digits = max_digits_u64(base); + if (digit_count > max_digits) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + // this check can be eliminated for all other types, but they will all require + // a max_digits(base) equivalent + if (digit_count == max_digits && i < min_safe_u64(base)) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + + // check other types overflow + if (!std::is_same::value) { + if (i > uint64_t(std::numeric_limits::max()) + uint64_t(negative)) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + } + + if (negative) { +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(push) +#pragma warning(disable : 4146) +#endif + // this weird workaround is required because: + // - converting unsigned to signed when its value is greater than signed max + // is UB pre-C++23. + // - reinterpret_casting (~i + 1) would work, but it is not constexpr + // this is always optimized into a neg instruction (note: T is an integer + // type) + value = T(-std::numeric_limits::max() - + T(i - uint64_t(std::numeric_limits::max()))); +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(pop) +#endif + } else { + value = T(i); + } + + answer.ec = std::errc(); + return answer; +} + +} // namespace fast_float + +#endif + +#ifndef FASTFLOAT_FAST_TABLE_H +#define FASTFLOAT_FAST_TABLE_H + +#include + +namespace fast_float { + +/** + * When mapping numbers from decimal to binary, + * we go from w * 10^q to m * 2^p but we have + * 10^q = 5^q * 2^q, so effectively + * we are trying to match + * w * 2^q * 5^q to m * 2^p. Thus the powers of two + * are not a concern since they can be represented + * exactly using the binary notation, only the powers of five + * affect the binary significand. + */ + +/** + * The smallest non-zero float (binary64) is 2^-1074. + * We take as input numbers of the form w x 10^q where w < 2^64. + * We have that w * 10^-343 < 2^(64-344) 5^-343 < 2^-1076. + * However, we have that + * (2^64-1) * 10^-342 = (2^64-1) * 2^-342 * 5^-342 > 2^-1074. + * Thus it is possible for a number of the form w * 10^-342 where + * w is a 64-bit value to be a non-zero floating-point number. + ********* + * Any number of form w * 10^309 where w>= 1 is going to be + * infinite in binary64 so we never need to worry about powers + * of 5 greater than 308. + */ +template struct powers_template { + + constexpr static int smallest_power_of_five = + binary_format::smallest_power_of_ten(); + constexpr static int largest_power_of_five = + binary_format::largest_power_of_ten(); + constexpr static int number_of_entries = + 2 * (largest_power_of_five - smallest_power_of_five + 1); + // Powers of five from 5^-342 all the way to 5^308 rounded toward one. + constexpr static uint64_t power_of_five_128[number_of_entries] = { + 0xeef453d6923bd65a, 0x113faa2906a13b3f, + 0x9558b4661b6565f8, 0x4ac7ca59a424c507, + 0xbaaee17fa23ebf76, 0x5d79bcf00d2df649, + 0xe95a99df8ace6f53, 0xf4d82c2c107973dc, + 0x91d8a02bb6c10594, 0x79071b9b8a4be869, + 0xb64ec836a47146f9, 0x9748e2826cdee284, + 0xe3e27a444d8d98b7, 0xfd1b1b2308169b25, + 0x8e6d8c6ab0787f72, 0xfe30f0f5e50e20f7, + 0xb208ef855c969f4f, 0xbdbd2d335e51a935, + 0xde8b2b66b3bc4723, 0xad2c788035e61382, + 0x8b16fb203055ac76, 0x4c3bcb5021afcc31, + 0xaddcb9e83c6b1793, 0xdf4abe242a1bbf3d, + 0xd953e8624b85dd78, 0xd71d6dad34a2af0d, + 0x87d4713d6f33aa6b, 0x8672648c40e5ad68, + 0xa9c98d8ccb009506, 0x680efdaf511f18c2, + 0xd43bf0effdc0ba48, 0x212bd1b2566def2, + 0x84a57695fe98746d, 0x14bb630f7604b57, + 0xa5ced43b7e3e9188, 0x419ea3bd35385e2d, + 0xcf42894a5dce35ea, 0x52064cac828675b9, + 0x818995ce7aa0e1b2, 0x7343efebd1940993, + 0xa1ebfb4219491a1f, 0x1014ebe6c5f90bf8, + 0xca66fa129f9b60a6, 0xd41a26e077774ef6, + 0xfd00b897478238d0, 0x8920b098955522b4, + 0x9e20735e8cb16382, 0x55b46e5f5d5535b0, + 0xc5a890362fddbc62, 0xeb2189f734aa831d, + 0xf712b443bbd52b7b, 0xa5e9ec7501d523e4, + 0x9a6bb0aa55653b2d, 0x47b233c92125366e, + 0xc1069cd4eabe89f8, 0x999ec0bb696e840a, + 0xf148440a256e2c76, 0xc00670ea43ca250d, + 0x96cd2a865764dbca, 0x380406926a5e5728, + 0xbc807527ed3e12bc, 0xc605083704f5ecf2, + 0xeba09271e88d976b, 0xf7864a44c633682e, + 0x93445b8731587ea3, 0x7ab3ee6afbe0211d, + 0xb8157268fdae9e4c, 0x5960ea05bad82964, + 0xe61acf033d1a45df, 0x6fb92487298e33bd, + 0x8fd0c16206306bab, 0xa5d3b6d479f8e056, + 0xb3c4f1ba87bc8696, 0x8f48a4899877186c, + 0xe0b62e2929aba83c, 0x331acdabfe94de87, + 0x8c71dcd9ba0b4925, 0x9ff0c08b7f1d0b14, + 0xaf8e5410288e1b6f, 0x7ecf0ae5ee44dd9, + 0xdb71e91432b1a24a, 0xc9e82cd9f69d6150, + 0x892731ac9faf056e, 0xbe311c083a225cd2, + 0xab70fe17c79ac6ca, 0x6dbd630a48aaf406, + 0xd64d3d9db981787d, 0x92cbbccdad5b108, + 0x85f0468293f0eb4e, 0x25bbf56008c58ea5, + 0xa76c582338ed2621, 0xaf2af2b80af6f24e, + 0xd1476e2c07286faa, 0x1af5af660db4aee1, + 0x82cca4db847945ca, 0x50d98d9fc890ed4d, + 0xa37fce126597973c, 0xe50ff107bab528a0, + 0xcc5fc196fefd7d0c, 0x1e53ed49a96272c8, + 0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7a, + 0x9faacf3df73609b1, 0x77b191618c54e9ac, + 0xc795830d75038c1d, 0xd59df5b9ef6a2417, + 0xf97ae3d0d2446f25, 0x4b0573286b44ad1d, + 0x9becce62836ac577, 0x4ee367f9430aec32, + 0xc2e801fb244576d5, 0x229c41f793cda73f, + 0xf3a20279ed56d48a, 0x6b43527578c1110f, + 0x9845418c345644d6, 0x830a13896b78aaa9, + 0xbe5691ef416bd60c, 0x23cc986bc656d553, + 0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa8, + 0x94b3a202eb1c3f39, 0x7bf7d71432f3d6a9, + 0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc53, + 0xe858ad248f5c22c9, 0xd1b3400f8f9cff68, + 0x91376c36d99995be, 0x23100809b9c21fa1, + 0xb58547448ffffb2d, 0xabd40a0c2832a78a, + 0xe2e69915b3fff9f9, 0x16c90c8f323f516c, + 0x8dd01fad907ffc3b, 0xae3da7d97f6792e3, + 0xb1442798f49ffb4a, 0x99cd11cfdf41779c, + 0xdd95317f31c7fa1d, 0x40405643d711d583, + 0x8a7d3eef7f1cfc52, 0x482835ea666b2572, + 0xad1c8eab5ee43b66, 0xda3243650005eecf, + 0xd863b256369d4a40, 0x90bed43e40076a82, + 0x873e4f75e2224e68, 0x5a7744a6e804a291, + 0xa90de3535aaae202, 0x711515d0a205cb36, + 0xd3515c2831559a83, 0xd5a5b44ca873e03, + 0x8412d9991ed58091, 0xe858790afe9486c2, + 0xa5178fff668ae0b6, 0x626e974dbe39a872, + 0xce5d73ff402d98e3, 0xfb0a3d212dc8128f, + 0x80fa687f881c7f8e, 0x7ce66634bc9d0b99, + 0xa139029f6a239f72, 0x1c1fffc1ebc44e80, + 0xc987434744ac874e, 0xa327ffb266b56220, + 0xfbe9141915d7a922, 0x4bf1ff9f0062baa8, + 0x9d71ac8fada6c9b5, 0x6f773fc3603db4a9, + 0xc4ce17b399107c22, 0xcb550fb4384d21d3, + 0xf6019da07f549b2b, 0x7e2a53a146606a48, + 0x99c102844f94e0fb, 0x2eda7444cbfc426d, + 0xc0314325637a1939, 0xfa911155fefb5308, + 0xf03d93eebc589f88, 0x793555ab7eba27ca, + 0x96267c7535b763b5, 0x4bc1558b2f3458de, + 0xbbb01b9283253ca2, 0x9eb1aaedfb016f16, + 0xea9c227723ee8bcb, 0x465e15a979c1cadc, + 0x92a1958a7675175f, 0xbfacd89ec191ec9, + 0xb749faed14125d36, 0xcef980ec671f667b, + 0xe51c79a85916f484, 0x82b7e12780e7401a, + 0x8f31cc0937ae58d2, 0xd1b2ecb8b0908810, + 0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa15, + 0xdfbdcece67006ac9, 0x67a791e093e1d49a, + 0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e0, + 0xaecc49914078536d, 0x58fae9f773886e18, + 0xda7f5bf590966848, 0xaf39a475506a899e, + 0x888f99797a5e012d, 0x6d8406c952429603, + 0xaab37fd7d8f58178, 0xc8e5087ba6d33b83, + 0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a64, + 0x855c3be0a17fcd26, 0x5cf2eea09a55067f, + 0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481e, + 0xd0601d8efc57b08b, 0xf13b94daf124da26, + 0x823c12795db6ce57, 0x76c53d08d6b70858, + 0xa2cb1717b52481ed, 0x54768c4b0c64ca6e, + 0xcb7ddcdda26da268, 0xa9942f5dcf7dfd09, + 0xfe5d54150b090b02, 0xd3f93b35435d7c4c, + 0x9efa548d26e5a6e1, 0xc47bc5014a1a6daf, + 0xc6b8e9b0709f109a, 0x359ab6419ca1091b, + 0xf867241c8cc6d4c0, 0xc30163d203c94b62, + 0x9b407691d7fc44f8, 0x79e0de63425dcf1d, + 0xc21094364dfb5636, 0x985915fc12f542e4, + 0xf294b943e17a2bc4, 0x3e6f5b7b17b2939d, + 0x979cf3ca6cec5b5a, 0xa705992ceecf9c42, + 0xbd8430bd08277231, 0x50c6ff782a838353, + 0xece53cec4a314ebd, 0xa4f8bf5635246428, + 0x940f4613ae5ed136, 0x871b7795e136be99, + 0xb913179899f68584, 0x28e2557b59846e3f, + 0xe757dd7ec07426e5, 0x331aeada2fe589cf, + 0x9096ea6f3848984f, 0x3ff0d2c85def7621, + 0xb4bca50b065abe63, 0xfed077a756b53a9, + 0xe1ebce4dc7f16dfb, 0xd3e8495912c62894, + 0x8d3360f09cf6e4bd, 0x64712dd7abbbd95c, + 0xb080392cc4349dec, 0xbd8d794d96aacfb3, + 0xdca04777f541c567, 0xecf0d7a0fc5583a0, + 0x89e42caaf9491b60, 0xf41686c49db57244, + 0xac5d37d5b79b6239, 0x311c2875c522ced5, + 0xd77485cb25823ac7, 0x7d633293366b828b, + 0x86a8d39ef77164bc, 0xae5dff9c02033197, + 0xa8530886b54dbdeb, 0xd9f57f830283fdfc, + 0xd267caa862a12d66, 0xd072df63c324fd7b, + 0x8380dea93da4bc60, 0x4247cb9e59f71e6d, + 0xa46116538d0deb78, 0x52d9be85f074e608, + 0xcd795be870516656, 0x67902e276c921f8b, + 0x806bd9714632dff6, 0xba1cd8a3db53b6, + 0xa086cfcd97bf97f3, 0x80e8a40eccd228a4, + 0xc8a883c0fdaf7df0, 0x6122cd128006b2cd, + 0xfad2a4b13d1b5d6c, 0x796b805720085f81, + 0x9cc3a6eec6311a63, 0xcbe3303674053bb0, + 0xc3f490aa77bd60fc, 0xbedbfc4411068a9c, + 0xf4f1b4d515acb93b, 0xee92fb5515482d44, + 0x991711052d8bf3c5, 0x751bdd152d4d1c4a, + 0xbf5cd54678eef0b6, 0xd262d45a78a0635d, + 0xef340a98172aace4, 0x86fb897116c87c34, + 0x9580869f0e7aac0e, 0xd45d35e6ae3d4da0, + 0xbae0a846d2195712, 0x8974836059cca109, + 0xe998d258869facd7, 0x2bd1a438703fc94b, + 0x91ff83775423cc06, 0x7b6306a34627ddcf, + 0xb67f6455292cbf08, 0x1a3bc84c17b1d542, + 0xe41f3d6a7377eeca, 0x20caba5f1d9e4a93, + 0x8e938662882af53e, 0x547eb47b7282ee9c, + 0xb23867fb2a35b28d, 0xe99e619a4f23aa43, + 0xdec681f9f4c31f31, 0x6405fa00e2ec94d4, + 0x8b3c113c38f9f37e, 0xde83bc408dd3dd04, + 0xae0b158b4738705e, 0x9624ab50b148d445, + 0xd98ddaee19068c76, 0x3badd624dd9b0957, + 0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d6, + 0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4c, + 0xd47487cc8470652b, 0x7647c3200069671f, + 0x84c8d4dfd2c63f3b, 0x29ecd9f40041e073, + 0xa5fb0a17c777cf09, 0xf468107100525890, + 0xcf79cc9db955c2cc, 0x7182148d4066eeb4, + 0x81ac1fe293d599bf, 0xc6f14cd848405530, + 0xa21727db38cb002f, 0xb8ada00e5a506a7c, + 0xca9cf1d206fdc03b, 0xa6d90811f0e4851c, + 0xfd442e4688bd304a, 0x908f4a166d1da663, + 0x9e4a9cec15763e2e, 0x9a598e4e043287fe, + 0xc5dd44271ad3cdba, 0x40eff1e1853f29fd, + 0xf7549530e188c128, 0xd12bee59e68ef47c, + 0x9a94dd3e8cf578b9, 0x82bb74f8301958ce, + 0xc13a148e3032d6e7, 0xe36a52363c1faf01, + 0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac1, + 0x96f5600f15a7b7e5, 0x29ab103a5ef8c0b9, + 0xbcb2b812db11a5de, 0x7415d448f6b6f0e7, + 0xebdf661791d60f56, 0x111b495b3464ad21, + 0x936b9fcebb25c995, 0xcab10dd900beec34, + 0xb84687c269ef3bfb, 0x3d5d514f40eea742, + 0xe65829b3046b0afa, 0xcb4a5a3112a5112, + 0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ab, + 0xb3f4e093db73a093, 0x59ed216765690f56, + 0xe0f218b8d25088b8, 0x306869c13ec3532c, + 0x8c974f7383725573, 0x1e414218c73a13fb, + 0xafbd2350644eeacf, 0xe5d1929ef90898fa, + 0xdbac6c247d62a583, 0xdf45f746b74abf39, + 0x894bc396ce5da772, 0x6b8bba8c328eb783, + 0xab9eb47c81f5114f, 0x66ea92f3f326564, + 0xd686619ba27255a2, 0xc80a537b0efefebd, + 0x8613fd0145877585, 0xbd06742ce95f5f36, + 0xa798fc4196e952e7, 0x2c48113823b73704, + 0xd17f3b51fca3a7a0, 0xf75a15862ca504c5, + 0x82ef85133de648c4, 0x9a984d73dbe722fb, + 0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebba, + 0xcc963fee10b7d1b3, 0x318df905079926a8, + 0xffbbcfe994e5c61f, 0xfdf17746497f7052, + 0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa633, + 0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc0, + 0xf9bd690a1b68637b, 0x3dfdce7aa3c673b0, + 0x9c1661a651213e2d, 0x6bea10ca65c084e, + 0xc31bfa0fe5698db8, 0x486e494fcff30a62, + 0xf3e2f893dec3f126, 0x5a89dba3c3efccfa, + 0x986ddb5c6b3a76b7, 0xf89629465a75e01c, + 0xbe89523386091465, 0xf6bbb397f1135823, + 0xee2ba6c0678b597f, 0x746aa07ded582e2c, + 0x94db483840b717ef, 0xa8c2a44eb4571cdc, + 0xba121a4650e4ddeb, 0x92f34d62616ce413, + 0xe896a0d7e51e1566, 0x77b020baf9c81d17, + 0x915e2486ef32cd60, 0xace1474dc1d122e, + 0xb5b5ada8aaff80b8, 0xd819992132456ba, + 0xe3231912d5bf60e6, 0x10e1fff697ed6c69, + 0x8df5efabc5979c8f, 0xca8d3ffa1ef463c1, + 0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb2, + 0xddd0467c64bce4a0, 0xac7cb3f6d05ddbde, + 0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96b, + 0xad4ab7112eb3929d, 0x86c16c98d2c953c6, + 0xd89d64d57a607744, 0xe871c7bf077ba8b7, + 0x87625f056c7c4a8b, 0x11471cd764ad4972, + 0xa93af6c6c79b5d2d, 0xd598e40d3dd89bcf, + 0xd389b47879823479, 0x4aff1d108d4ec2c3, + 0x843610cb4bf160cb, 0xcedf722a585139ba, + 0xa54394fe1eedb8fe, 0xc2974eb4ee658828, + 0xce947a3da6a9273e, 0x733d226229feea32, + 0x811ccc668829b887, 0x806357d5a3f525f, + 0xa163ff802a3426a8, 0xca07c2dcb0cf26f7, + 0xc9bcff6034c13052, 0xfc89b393dd02f0b5, + 0xfc2c3f3841f17c67, 0xbbac2078d443ace2, + 0x9d9ba7832936edc0, 0xd54b944b84aa4c0d, + 0xc5029163f384a931, 0xa9e795e65d4df11, + 0xf64335bcf065d37d, 0x4d4617b5ff4a16d5, + 0x99ea0196163fa42e, 0x504bced1bf8e4e45, + 0xc06481fb9bcf8d39, 0xe45ec2862f71e1d6, + 0xf07da27a82c37088, 0x5d767327bb4e5a4c, + 0x964e858c91ba2655, 0x3a6a07f8d510f86f, + 0xbbe226efb628afea, 0x890489f70a55368b, + 0xeadab0aba3b2dbe5, 0x2b45ac74ccea842e, + 0x92c8ae6b464fc96f, 0x3b0b8bc90012929d, + 0xb77ada0617e3bbcb, 0x9ce6ebb40173744, + 0xe55990879ddcaabd, 0xcc420a6a101d0515, + 0x8f57fa54c2a9eab6, 0x9fa946824a12232d, + 0xb32df8e9f3546564, 0x47939822dc96abf9, + 0xdff9772470297ebd, 0x59787e2b93bc56f7, + 0x8bfbea76c619ef36, 0x57eb4edb3c55b65a, + 0xaefae51477a06b03, 0xede622920b6b23f1, + 0xdab99e59958885c4, 0xe95fab368e45eced, + 0x88b402f7fd75539b, 0x11dbcb0218ebb414, + 0xaae103b5fcd2a881, 0xd652bdc29f26a119, + 0xd59944a37c0752a2, 0x4be76d3346f0495f, + 0x857fcae62d8493a5, 0x6f70a4400c562ddb, + 0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb952, + 0xd097ad07a71f26b2, 0x7e2000a41346a7a7, + 0x825ecc24c873782f, 0x8ed400668c0c28c8, + 0xa2f67f2dfa90563b, 0x728900802f0f32fa, + 0xcbb41ef979346bca, 0x4f2b40a03ad2ffb9, + 0xfea126b7d78186bc, 0xe2f610c84987bfa8, + 0x9f24b832e6b0f436, 0xdd9ca7d2df4d7c9, + 0xc6ede63fa05d3143, 0x91503d1c79720dbb, + 0xf8a95fcf88747d94, 0x75a44c6397ce912a, + 0x9b69dbe1b548ce7c, 0xc986afbe3ee11aba, + 0xc24452da229b021b, 0xfbe85badce996168, + 0xf2d56790ab41c2a2, 0xfae27299423fb9c3, + 0x97c560ba6b0919a5, 0xdccd879fc967d41a, + 0xbdb6b8e905cb600f, 0x5400e987bbc1c920, + 0xed246723473e3813, 0x290123e9aab23b68, + 0x9436c0760c86e30b, 0xf9a0b6720aaf6521, + 0xb94470938fa89bce, 0xf808e40e8d5b3e69, + 0xe7958cb87392c2c2, 0xb60b1d1230b20e04, + 0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c2, + 0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af3, + 0xe2280b6c20dd5232, 0x25c6da63c38de1b0, + 0x8d590723948a535f, 0x579c487e5a38ad0e, + 0xb0af48ec79ace837, 0x2d835a9df0c6d851, + 0xdcdb1b2798182244, 0xf8e431456cf88e65, + 0x8a08f0f8bf0f156b, 0x1b8e9ecb641b58ff, + 0xac8b2d36eed2dac5, 0xe272467e3d222f3f, + 0xd7adf884aa879177, 0x5b0ed81dcc6abb0f, + 0x86ccbb52ea94baea, 0x98e947129fc2b4e9, + 0xa87fea27a539e9a5, 0x3f2398d747b36224, + 0xd29fe4b18e88640e, 0x8eec7f0d19a03aad, + 0x83a3eeeef9153e89, 0x1953cf68300424ac, + 0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd7, + 0xcdb02555653131b6, 0x3792f412cb06794d, + 0x808e17555f3ebf11, 0xe2bbd88bbee40bd0, + 0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec4, + 0xc8de047564d20a8b, 0xf245825a5a445275, + 0xfb158592be068d2e, 0xeed6e2f0f0d56712, + 0x9ced737bb6c4183d, 0x55464dd69685606b, + 0xc428d05aa4751e4c, 0xaa97e14c3c26b886, + 0xf53304714d9265df, 0xd53dd99f4b3066a8, + 0x993fe2c6d07b7fab, 0xe546a8038efe4029, + 0xbf8fdb78849a5f96, 0xde98520472bdd033, + 0xef73d256a5c0f77c, 0x963e66858f6d4440, + 0x95a8637627989aad, 0xdde7001379a44aa8, + 0xbb127c53b17ec159, 0x5560c018580d5d52, + 0xe9d71b689dde71af, 0xaab8f01e6e10b4a6, + 0x9226712162ab070d, 0xcab3961304ca70e8, + 0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d22, + 0xe45c10c42a2b3b05, 0x8cb89a7db77c506a, + 0x8eb98a7a9a5b04e3, 0x77f3608e92adb242, + 0xb267ed1940f1c61c, 0x55f038b237591ed3, + 0xdf01e85f912e37a3, 0x6b6c46dec52f6688, + 0x8b61313bbabce2c6, 0x2323ac4b3b3da015, + 0xae397d8aa96c1b77, 0xabec975e0a0d081a, + 0xd9c7dced53c72255, 0x96e7bd358c904a21, + 0x881cea14545c7575, 0x7e50d64177da2e54, + 0xaa242499697392d2, 0xdde50bd1d5d0b9e9, + 0xd4ad2dbfc3d07787, 0x955e4ec64b44e864, + 0x84ec3c97da624ab4, 0xbd5af13bef0b113e, + 0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58e, + 0xcfb11ead453994ba, 0x67de18eda5814af2, + 0x81ceb32c4b43fcf4, 0x80eacf948770ced7, + 0xa2425ff75e14fc31, 0xa1258379a94d028d, + 0xcad2f7f5359a3b3e, 0x96ee45813a04330, + 0xfd87b5f28300ca0d, 0x8bca9d6e188853fc, + 0x9e74d1b791e07e48, 0x775ea264cf55347e, + 0xc612062576589dda, 0x95364afe032a819e, + 0xf79687aed3eec551, 0x3a83ddbd83f52205, + 0x9abe14cd44753b52, 0xc4926a9672793543, + 0xc16d9a0095928a27, 0x75b7053c0f178294, + 0xf1c90080baf72cb1, 0x5324c68b12dd6339, + 0x971da05074da7bee, 0xd3f6fc16ebca5e04, + 0xbce5086492111aea, 0x88f4bb1ca6bcf585, + 0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6, + 0x9392ee8e921d5d07, 0x3aff322e62439fd0, + 0xb877aa3236a4b449, 0x9befeb9fad487c3, + 0xe69594bec44de15b, 0x4c2ebe687989a9b4, + 0x901d7cf73ab0acd9, 0xf9d37014bf60a11, + 0xb424dc35095cd80f, 0x538484c19ef38c95, + 0xe12e13424bb40e13, 0x2865a5f206b06fba, + 0x8cbccc096f5088cb, 0xf93f87b7442e45d4, + 0xafebff0bcb24aafe, 0xf78f69a51539d749, + 0xdbe6fecebdedd5be, 0xb573440e5a884d1c, + 0x89705f4136b4a597, 0x31680a88f8953031, + 0xabcc77118461cefc, 0xfdc20d2b36ba7c3e, + 0xd6bf94d5e57a42bc, 0x3d32907604691b4d, + 0x8637bd05af6c69b5, 0xa63f9a49c2c1b110, + 0xa7c5ac471b478423, 0xfcf80dc33721d54, + 0xd1b71758e219652b, 0xd3c36113404ea4a9, + 0x83126e978d4fdf3b, 0x645a1cac083126ea, + 0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4, + 0xcccccccccccccccc, 0xcccccccccccccccd, + 0x8000000000000000, 0x0, + 0xa000000000000000, 0x0, + 0xc800000000000000, 0x0, + 0xfa00000000000000, 0x0, + 0x9c40000000000000, 0x0, + 0xc350000000000000, 0x0, + 0xf424000000000000, 0x0, + 0x9896800000000000, 0x0, + 0xbebc200000000000, 0x0, + 0xee6b280000000000, 0x0, + 0x9502f90000000000, 0x0, + 0xba43b74000000000, 0x0, + 0xe8d4a51000000000, 0x0, + 0x9184e72a00000000, 0x0, + 0xb5e620f480000000, 0x0, + 0xe35fa931a0000000, 0x0, + 0x8e1bc9bf04000000, 0x0, + 0xb1a2bc2ec5000000, 0x0, + 0xde0b6b3a76400000, 0x0, + 0x8ac7230489e80000, 0x0, + 0xad78ebc5ac620000, 0x0, + 0xd8d726b7177a8000, 0x0, + 0x878678326eac9000, 0x0, + 0xa968163f0a57b400, 0x0, + 0xd3c21bcecceda100, 0x0, + 0x84595161401484a0, 0x0, + 0xa56fa5b99019a5c8, 0x0, + 0xcecb8f27f4200f3a, 0x0, + 0x813f3978f8940984, 0x4000000000000000, + 0xa18f07d736b90be5, 0x5000000000000000, + 0xc9f2c9cd04674ede, 0xa400000000000000, + 0xfc6f7c4045812296, 0x4d00000000000000, + 0x9dc5ada82b70b59d, 0xf020000000000000, + 0xc5371912364ce305, 0x6c28000000000000, + 0xf684df56c3e01bc6, 0xc732000000000000, + 0x9a130b963a6c115c, 0x3c7f400000000000, + 0xc097ce7bc90715b3, 0x4b9f100000000000, + 0xf0bdc21abb48db20, 0x1e86d40000000000, + 0x96769950b50d88f4, 0x1314448000000000, + 0xbc143fa4e250eb31, 0x17d955a000000000, + 0xeb194f8e1ae525fd, 0x5dcfab0800000000, + 0x92efd1b8d0cf37be, 0x5aa1cae500000000, + 0xb7abc627050305ad, 0xf14a3d9e40000000, + 0xe596b7b0c643c719, 0x6d9ccd05d0000000, + 0x8f7e32ce7bea5c6f, 0xe4820023a2000000, + 0xb35dbf821ae4f38b, 0xdda2802c8a800000, + 0xe0352f62a19e306e, 0xd50b2037ad200000, + 0x8c213d9da502de45, 0x4526f422cc340000, + 0xaf298d050e4395d6, 0x9670b12b7f410000, + 0xdaf3f04651d47b4c, 0x3c0cdd765f114000, + 0x88d8762bf324cd0f, 0xa5880a69fb6ac800, + 0xab0e93b6efee0053, 0x8eea0d047a457a00, + 0xd5d238a4abe98068, 0x72a4904598d6d880, + 0x85a36366eb71f041, 0x47a6da2b7f864750, + 0xa70c3c40a64e6c51, 0x999090b65f67d924, + 0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d, + 0x82818f1281ed449f, 0xbff8f10e7a8921a4, + 0xa321f2d7226895c7, 0xaff72d52192b6a0d, + 0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490, + 0xfee50b7025c36a08, 0x2f236d04753d5b4, + 0x9f4f2726179a2245, 0x1d762422c946590, + 0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5, + 0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2, + 0x9b934c3b330c8577, 0x63cc55f49f88eb2f, + 0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb, + 0xf316271c7fc3908a, 0x8bef464e3945ef7a, + 0x97edd871cfda3a56, 0x97758bf0e3cbb5ac, + 0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317, + 0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd, + 0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a, + 0xb975d6b6ee39e436, 0xb3e2fd538e122b44, + 0xe7d34c64a9c85d44, 0x60dbbca87196b616, + 0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd, + 0xb51d13aea4a488dd, 0x6babab6398bdbe41, + 0xe264589a4dcdab14, 0xc696963c7eed2dd1, + 0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2, + 0xb0de65388cc8ada8, 0x3b25a55f43294bcb, + 0xdd15fe86affad912, 0x49ef0eb713f39ebe, + 0x8a2dbf142dfcc7ab, 0x6e3569326c784337, + 0xacb92ed9397bf996, 0x49c2c37f07965404, + 0xd7e77a8f87daf7fb, 0xdc33745ec97be906, + 0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3, + 0xa8acd7c0222311bc, 0xc40832ea0d68ce0c, + 0xd2d80db02aabd62b, 0xf50a3fa490c30190, + 0x83c7088e1aab65db, 0x792667c6da79e0fa, + 0xa4b8cab1a1563f52, 0x577001b891185938, + 0xcde6fd5e09abcf26, 0xed4c0226b55e6f86, + 0x80b05e5ac60b6178, 0x544f8158315b05b4, + 0xa0dc75f1778e39d6, 0x696361ae3db1c721, + 0xc913936dd571c84c, 0x3bc3a19cd1e38e9, + 0xfb5878494ace3a5f, 0x4ab48a04065c723, + 0x9d174b2dcec0e47b, 0x62eb0d64283f9c76, + 0xc45d1df942711d9a, 0x3ba5d0bd324f8394, + 0xf5746577930d6500, 0xca8f44ec7ee36479, + 0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb, + 0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e, + 0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e, + 0x95d04aee3b80ece5, 0xbba1f1d158724a12, + 0xbb445da9ca61281f, 0x2a8a6e45ae8edc97, + 0xea1575143cf97226, 0xf52d09d71a3293bd, + 0x924d692ca61be758, 0x593c2626705f9c56, + 0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c, + 0xe498f455c38b997a, 0xb6dfb9c0f956447, + 0x8edf98b59a373fec, 0x4724bd4189bd5eac, + 0xb2977ee300c50fe7, 0x58edec91ec2cb657, + 0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed, + 0x8b865b215899f46c, 0xbd79e0d20082ee74, + 0xae67f1e9aec07187, 0xecd8590680a3aa11, + 0xda01ee641a708de9, 0xe80e6f4820cc9495, + 0x884134fe908658b2, 0x3109058d147fdcdd, + 0xaa51823e34a7eede, 0xbd4b46f0599fd415, + 0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a, + 0x850fadc09923329e, 0x3e2cf6bc604ddb0, + 0xa6539930bf6bff45, 0x84db8346b786151c, + 0xcfe87f7cef46ff16, 0xe612641865679a63, + 0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e, + 0xa26da3999aef7749, 0xe3be5e330f38f09d, + 0xcb090c8001ab551c, 0x5cadf5bfd3072cc5, + 0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6, + 0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa, + 0xc646d63501a1511d, 0xb281e1fd541501b8, + 0xf7d88bc24209a565, 0x1f225a7ca91a4226, + 0x9ae757596946075f, 0x3375788de9b06958, + 0xc1a12d2fc3978937, 0x52d6b1641c83ae, + 0xf209787bb47d6b84, 0xc0678c5dbd23a49a, + 0x9745eb4d50ce6332, 0xf840b7ba963646e0, + 0xbd176620a501fbff, 0xb650e5a93bc3d898, + 0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe, + 0x93ba47c980e98cdf, 0xc66f336c36b10137, + 0xb8a8d9bbe123f017, 0xb80b0047445d4184, + 0xe6d3102ad96cec1d, 0xa60dc059157491e5, + 0x9043ea1ac7e41392, 0x87c89837ad68db2f, + 0xb454e4a179dd1877, 0x29babe4598c311fb, + 0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a, + 0x8ce2529e2734bb1d, 0x1899e4a65f58660c, + 0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f, + 0xdc21a1171d42645d, 0x76707543f4fa1f73, + 0x899504ae72497eba, 0x6a06494a791c53a8, + 0xabfa45da0edbde69, 0x487db9d17636892, + 0xd6f8d7509292d603, 0x45a9d2845d3c42b6, + 0x865b86925b9bc5c2, 0xb8a2392ba45a9b2, + 0xa7f26836f282b732, 0x8e6cac7768d7141e, + 0xd1ef0244af2364ff, 0x3207d795430cd926, + 0x8335616aed761f1f, 0x7f44e6bd49e807b8, + 0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6, + 0xcd036837130890a1, 0x36dba887c37a8c0f, + 0x802221226be55a64, 0xc2494954da2c9789, + 0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c, + 0xc83553c5c8965d3d, 0x6f92829494e5acc7, + 0xfa42a8b73abbf48c, 0xcb772339ba1f17f9, + 0x9c69a97284b578d7, 0xff2a760414536efb, + 0xc38413cf25e2d70d, 0xfef5138519684aba, + 0xf46518c2ef5b8cd1, 0x7eb258665fc25d69, + 0x98bf2f79d5993802, 0xef2f773ffbd97a61, + 0xbeeefb584aff8603, 0xaafb550ffacfd8fa, + 0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38, + 0x952ab45cfa97a0b2, 0xdd945a747bf26183, + 0xba756174393d88df, 0x94f971119aeef9e4, + 0xe912b9d1478ceb17, 0x7a37cd5601aab85d, + 0x91abb422ccb812ee, 0xac62e055c10ab33a, + 0xb616a12b7fe617aa, 0x577b986b314d6009, + 0xe39c49765fdf9d94, 0xed5a7e85fda0b80b, + 0x8e41ade9fbebc27d, 0x14588f13be847307, + 0xb1d219647ae6b31c, 0x596eb2d8ae258fc8, + 0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb, + 0x8aec23d680043bee, 0x25de7bb9480d5854, + 0xada72ccc20054ae9, 0xaf561aa79a10ae6a, + 0xd910f7ff28069da4, 0x1b2ba1518094da04, + 0x87aa9aff79042286, 0x90fb44d2f05d0842, + 0xa99541bf57452b28, 0x353a1607ac744a53, + 0xd3fa922f2d1675f2, 0x42889b8997915ce8, + 0x847c9b5d7c2e09b7, 0x69956135febada11, + 0xa59bc234db398c25, 0x43fab9837e699095, + 0xcf02b2c21207ef2e, 0x94f967e45e03f4bb, + 0x8161afb94b44f57d, 0x1d1be0eebac278f5, + 0xa1ba1ba79e1632dc, 0x6462d92a69731732, + 0xca28a291859bbf93, 0x7d7b8f7503cfdcfe, + 0xfcb2cb35e702af78, 0x5cda735244c3d43e, + 0x9defbf01b061adab, 0x3a0888136afa64a7, + 0xc56baec21c7a1916, 0x88aaa1845b8fdd0, + 0xf6c69a72a3989f5b, 0x8aad549e57273d45, + 0x9a3c2087a63f6399, 0x36ac54e2f678864b, + 0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd, + 0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5, + 0x969eb7c47859e743, 0x9f644ae5a4b1b325, + 0xbc4665b596706114, 0x873d5d9f0dde1fee, + 0xeb57ff22fc0c7959, 0xa90cb506d155a7ea, + 0x9316ff75dd87cbd8, 0x9a7f12442d588f2, + 0xb7dcbf5354e9bece, 0xc11ed6d538aeb2f, + 0xe5d3ef282a242e81, 0x8f1668c8a86da5fa, + 0x8fa475791a569d10, 0xf96e017d694487bc, + 0xb38d92d760ec4455, 0x37c981dcc395a9ac, + 0xe070f78d3927556a, 0x85bbe253f47b1417, + 0x8c469ab843b89562, 0x93956d7478ccec8e, + 0xaf58416654a6babb, 0x387ac8d1970027b2, + 0xdb2e51bfe9d0696a, 0x6997b05fcc0319e, + 0x88fcf317f22241e2, 0x441fece3bdf81f03, + 0xab3c2fddeeaad25a, 0xd527e81cad7626c3, + 0xd60b3bd56a5586f1, 0x8a71e223d8d3b074, + 0x85c7056562757456, 0xf6872d5667844e49, + 0xa738c6bebb12d16c, 0xb428f8ac016561db, + 0xd106f86e69d785c7, 0xe13336d701beba52, + 0x82a45b450226b39c, 0xecc0024661173473, + 0xa34d721642b06084, 0x27f002d7f95d0190, + 0xcc20ce9bd35c78a5, 0x31ec038df7b441f4, + 0xff290242c83396ce, 0x7e67047175a15271, + 0x9f79a169bd203e41, 0xf0062c6e984d386, + 0xc75809c42c684dd1, 0x52c07b78a3e60868, + 0xf92e0c3537826145, 0xa7709a56ccdf8a82, + 0x9bbcc7a142b17ccb, 0x88a66076400bb691, + 0xc2abf989935ddbfe, 0x6acff893d00ea435, + 0xf356f7ebf83552fe, 0x583f6b8c4124d43, + 0x98165af37b2153de, 0xc3727a337a8b704a, + 0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c, + 0xeda2ee1c7064130c, 0x1162def06f79df73, + 0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8, + 0xb9a74a0637ce2ee1, 0x6d953e2bd7173692, + 0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437, + 0x910ab1d4db9914a0, 0x1d9c9892400a22a2, + 0xb54d5e4a127f59c8, 0x2503beb6d00cab4b, + 0xe2a0b5dc971f303a, 0x2e44ae64840fd61d, + 0x8da471a9de737e24, 0x5ceaecfed289e5d2, + 0xb10d8e1456105dad, 0x7425a83e872c5f47, + 0xdd50f1996b947518, 0xd12f124e28f77719, + 0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f, + 0xace73cbfdc0bfb7b, 0x636cc64d1001550b, + 0xd8210befd30efa5a, 0x3c47f7e05401aa4e, + 0x8714a775e3e95c78, 0x65acfaec34810a71, + 0xa8d9d1535ce3b396, 0x7f1839a741a14d0d, + 0xd31045a8341ca07c, 0x1ede48111209a050, + 0x83ea2b892091e44d, 0x934aed0aab460432, + 0xa4e4b66b68b65d60, 0xf81da84d5617853f, + 0xce1de40642e3f4b9, 0x36251260ab9d668e, + 0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019, + 0xa1075a24e4421730, 0xb24cf65b8612f81f, + 0xc94930ae1d529cfc, 0xdee033f26797b627, + 0xfb9b7cd9a4a7443c, 0x169840ef017da3b1, + 0x9d412e0806e88aa5, 0x8e1f289560ee864e, + 0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2, + 0xf5b5d7ec8acb58a2, 0xae10af696774b1db, + 0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29, + 0xbff610b0cc6edd3f, 0x17fd090a58d32af3, + 0xeff394dcff8a948e, 0xddfc4b4cef07f5b0, + 0x95f83d0a1fb69cd9, 0x4abdaf101564f98e, + 0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1, + 0xea53df5fd18d5513, 0x84c86189216dc5ed, + 0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4, + 0xb7118682dbb66a77, 0x3fbc8c33221dc2a1, + 0xe4d5e82392a40515, 0xfabaf3feaa5334a, + 0x8f05b1163ba6832d, 0x29cb4d87f2a7400e, + 0xb2c71d5bca9023f8, 0x743e20e9ef511012, + 0xdf78e4b2bd342cf6, 0x914da9246b255416, + 0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e, + 0xae9672aba3d0c320, 0xa184ac2473b529b1, + 0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e, + 0x8865899617fb1871, 0x7e2fa67c7a658892, + 0xaa7eebfb9df9de8d, 0xddbb901b98feeab7, + 0xd51ea6fa85785631, 0x552a74227f3ea565, + 0x8533285c936b35de, 0xd53a88958f87275f, + 0xa67ff273b8460356, 0x8a892abaf368f137, + 0xd01fef10a657842c, 0x2d2b7569b0432d85, + 0x8213f56a67f6b29b, 0x9c3b29620e29fc73, + 0xa298f2c501f45f42, 0x8349f3ba91b47b8f, + 0xcb3f2f7642717713, 0x241c70a936219a73, + 0xfe0efb53d30dd4d7, 0xed238cd383aa0110, + 0x9ec95d1463e8a506, 0xf4363804324a40aa, + 0xc67bb4597ce2ce48, 0xb143c6053edcd0d5, + 0xf81aa16fdc1b81da, 0xdd94b7868e94050a, + 0x9b10a4e5e9913128, 0xca7cf2b4191c8326, + 0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0, + 0xf24a01a73cf2dccf, 0xbc633b39673c8cec, + 0x976e41088617ca01, 0xd5be0503e085d813, + 0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18, + 0xec9c459d51852ba2, 0xddf8e7d60ed1219e, + 0x93e1ab8252f33b45, 0xcabb90e5c942b503, + 0xb8da1662e7b00a17, 0x3d6a751f3b936243, + 0xe7109bfba19c0c9d, 0xcc512670a783ad4, + 0x906a617d450187e2, 0x27fb2b80668b24c5, + 0xb484f9dc9641e9da, 0xb1f9f660802dedf6, + 0xe1a63853bbd26451, 0x5e7873f8a0396973, + 0x8d07e33455637eb2, 0xdb0b487b6423e1e8, + 0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62, + 0xdc5c5301c56b75f7, 0x7641a140cc7810fb, + 0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d, + 0xac2820d9623bf429, 0x546345fa9fbdcd44, + 0xd732290fbacaf133, 0xa97c177947ad4095, + 0x867f59a9d4bed6c0, 0x49ed8eabcccc485d, + 0xa81f301449ee8c70, 0x5c68f256bfff5a74, + 0xd226fc195c6a2f8c, 0x73832eec6fff3111, + 0x83585d8fd9c25db7, 0xc831fd53c5ff7eab, + 0xa42e74f3d032f525, 0xba3e7ca8b77f5e55, + 0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb, + 0x80444b5e7aa7cf85, 0x7980d163cf5b81b3, + 0xa0555e361951c366, 0xd7e105bcc332621f, + 0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7, + 0xfa856334878fc150, 0xb14f98f6f0feb951, + 0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3, + 0xc3b8358109e84f07, 0xa862f80ec4700c8, + 0xf4a642e14c6262c8, 0xcd27bb612758c0fa, + 0x98e7e9cccfbd7dbd, 0x8038d51cb897789c, + 0xbf21e44003acdd2c, 0xe0470a63e6bd56c3, + 0xeeea5d5004981478, 0x1858ccfce06cac74, + 0x95527a5202df0ccb, 0xf37801e0c43ebc8, + 0xbaa718e68396cffd, 0xd30560258f54e6ba, + 0xe950df20247c83fd, 0x47c6b82ef32a2069, + 0x91d28b7416cdd27e, 0x4cdc331d57fa5441, + 0xb6472e511c81471d, 0xe0133fe4adf8e952, + 0xe3d8f9e563a198e5, 0x58180fddd97723a6, + 0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648, + }; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template +constexpr uint64_t + powers_template::power_of_five_128[number_of_entries]; + +#endif + +using powers = powers_template<>; + +} // namespace fast_float + +#endif + +#ifndef FASTFLOAT_DECIMAL_TO_BINARY_H +#define FASTFLOAT_DECIMAL_TO_BINARY_H + +#include +#include +#include +#include +#include +#include + +namespace fast_float { + +// This will compute or rather approximate w * 5**q and return a pair of 64-bit +// words approximating the result, with the "high" part corresponding to the +// most significant bits and the low part corresponding to the least significant +// bits. +// +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128 +compute_product_approximation(int64_t q, uint64_t w) { + const int index = 2 * int(q - powers::smallest_power_of_five); + // For small values of q, e.g., q in [0,27], the answer is always exact + // because The line value128 firstproduct = full_multiplication(w, + // power_of_five_128[index]); gives the exact answer. + value128 firstproduct = + full_multiplication(w, powers::power_of_five_128[index]); + static_assert((bit_precision >= 0) && (bit_precision <= 64), + " precision should be in (0,64]"); + constexpr uint64_t precision_mask = + (bit_precision < 64) ? (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision) + : uint64_t(0xFFFFFFFFFFFFFFFF); + if ((firstproduct.high & precision_mask) == + precision_mask) { // could further guard with (lower + w < lower) + // regarding the second product, we only need secondproduct.high, but our + // expectation is that the compiler will optimize this extra work away if + // needed. + value128 secondproduct = + full_multiplication(w, powers::power_of_five_128[index + 1]); + firstproduct.low += secondproduct.high; + if (secondproduct.high > firstproduct.low) { + firstproduct.high++; + } + } + return firstproduct; +} + +namespace detail { +/** + * For q in (0,350), we have that + * f = (((152170 + 65536) * q ) >> 16); + * is equal to + * floor(p) + q + * where + * p = log(5**q)/log(2) = q * log(5)/log(2) + * + * For negative values of q in (-400,0), we have that + * f = (((152170 + 65536) * q ) >> 16); + * is equal to + * -ceil(p) + q + * where + * p = log(5**-q)/log(2) = -q * log(5)/log(2) + */ +constexpr fastfloat_really_inline int32_t power(int32_t q) noexcept { + return (((152170 + 65536) * q) >> 16) + 63; +} +} // namespace detail + +// create an adjusted mantissa, biased by the invalid power2 +// for significant digits already multiplied by 10 ** q. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 adjusted_mantissa +compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept { + int hilz = int(w >> 63) ^ 1; + adjusted_mantissa answer; + answer.mantissa = w << hilz; + int bias = binary::mantissa_explicit_bits() - binary::minimum_exponent(); + answer.power2 = int32_t(detail::power(int32_t(q)) + bias - hilz - lz - 62 + + invalid_am_bias); + return answer; +} + +// w * 10 ** q, without rounding the representation up. +// the power2 in the exponent will be adjusted by invalid_am_bias. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +compute_error(int64_t q, uint64_t w) noexcept { + int lz = leading_zeroes(w); + w <<= lz; + value128 product = + compute_product_approximation(q, w); + return compute_error_scaled(q, product.high, lz); +} + +// w * 10 ** q +// The returned value should be a valid ieee64 number that simply need to be +// packed. However, in some very rare cases, the computation will fail. In such +// cases, we return an adjusted_mantissa with a negative power of 2: the caller +// should recompute in such cases. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +compute_float(int64_t q, uint64_t w) noexcept { + adjusted_mantissa answer; + if ((w == 0) || (q < binary::smallest_power_of_ten())) { + answer.power2 = 0; + answer.mantissa = 0; + // result should be zero + return answer; + } + if (q > binary::largest_power_of_ten()) { + // we want to get infinity: + answer.power2 = binary::infinite_power(); + answer.mantissa = 0; + return answer; + } + // At this point in time q is in [powers::smallest_power_of_five, + // powers::largest_power_of_five]. + + // We want the most significant bit of i to be 1. Shift if needed. + int lz = leading_zeroes(w); + w <<= lz; + + // The required precision is binary::mantissa_explicit_bits() + 3 because + // 1. We need the implicit bit + // 2. We need an extra bit for rounding purposes + // 3. We might lose a bit due to the "upperbit" routine (result too small, + // requiring a shift) + + value128 product = + compute_product_approximation(q, w); + // The computed 'product' is always sufficient. + // Mathematical proof: + // Noble Mushtak and Daniel Lemire, Fast Number Parsing Without Fallback (to + // appear) See script/mushtak_lemire.py + + // The "compute_product_approximation" function can be slightly slower than a + // branchless approach: value128 product = compute_product(q, w); but in + // practice, we can win big with the compute_product_approximation if its + // additional branch is easily predicted. Which is best is data specific. + int upperbit = int(product.high >> 63); + int shift = upperbit + 64 - binary::mantissa_explicit_bits() - 3; + + answer.mantissa = product.high >> shift; + + answer.power2 = int32_t(detail::power(int32_t(q)) + upperbit - lz - + binary::minimum_exponent()); + if (answer.power2 <= 0) { // we have a subnormal? + // Here have that answer.power2 <= 0 so -answer.power2 >= 0 + if (-answer.power2 + 1 >= + 64) { // if we have more than 64 bits below the minimum exponent, you + // have a zero for sure. + answer.power2 = 0; + answer.mantissa = 0; + // result should be zero + return answer; + } + // next line is safe because -answer.power2 + 1 < 64 + answer.mantissa >>= -answer.power2 + 1; + // Thankfully, we can't have both "round-to-even" and subnormals because + // "round-to-even" only occurs for powers close to 0. + answer.mantissa += (answer.mantissa & 1); // round up + answer.mantissa >>= 1; + // There is a weird scenario where we don't have a subnormal but just. + // Suppose we start with 2.2250738585072013e-308, we end up + // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal + // whereas 0x40000000000000 x 2^-1023-53 is normal. Now, we need to round + // up 0x3fffffffffffff x 2^-1023-53 and once we do, we are no longer + // subnormal, but we can only know this after rounding. + // So we only declare a subnormal if we are smaller than the threshold. + answer.power2 = + (answer.mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) + ? 0 + : 1; + return answer; + } + + // usually, we round *up*, but if we fall right in between and and we have an + // even basis, we need to round down + // We are only concerned with the cases where 5**q fits in single 64-bit word. + if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) && + (q <= binary::max_exponent_round_to_even()) && + ((answer.mantissa & 3) == 1)) { // we may fall between two floats! + // To be in-between two floats we need that in doing + // answer.mantissa = product.high >> (upperbit + 64 - + // binary::mantissa_explicit_bits() - 3); + // ... we dropped out only zeroes. But if this happened, then we can go + // back!!! + if ((answer.mantissa << shift) == product.high) { + answer.mantissa &= ~uint64_t(1); // flip it so that we do not round up + } + } + + answer.mantissa += (answer.mantissa & 1); // round up + answer.mantissa >>= 1; + if (answer.mantissa >= (uint64_t(2) << binary::mantissa_explicit_bits())) { + answer.mantissa = (uint64_t(1) << binary::mantissa_explicit_bits()); + answer.power2++; // undo previous addition + } + + answer.mantissa &= ~(uint64_t(1) << binary::mantissa_explicit_bits()); + if (answer.power2 >= binary::infinite_power()) { // infinity + answer.power2 = binary::infinite_power(); + answer.mantissa = 0; + } + return answer; +} + +} // namespace fast_float + +#endif + +#ifndef FASTFLOAT_BIGINT_H +#define FASTFLOAT_BIGINT_H + +#include +#include +#include +#include + + +namespace fast_float { + +// the limb width: we want efficient multiplication of double the bits in +// limb, or for 64-bit limbs, at least 64-bit multiplication where we can +// extract the high and low parts efficiently. this is every 64-bit +// architecture except for sparc, which emulates 128-bit multiplication. +// we might have platforms where `CHAR_BIT` is not 8, so let's avoid +// doing `8 * sizeof(limb)`. +#if defined(FASTFLOAT_64BIT) && !defined(__sparc) +#define FASTFLOAT_64BIT_LIMB 1 +typedef uint64_t limb; +constexpr size_t limb_bits = 64; +#else +#define FASTFLOAT_32BIT_LIMB +typedef uint32_t limb; +constexpr size_t limb_bits = 32; +#endif + +typedef span limb_span; + +// number of bits in a bigint. this needs to be at least the number +// of bits required to store the largest bigint, which is +// `log2(10**(digits + max_exp))`, or `log2(10**(767 + 342))`, or +// ~3600 bits, so we round to 4000. +constexpr size_t bigint_bits = 4000; +constexpr size_t bigint_limbs = bigint_bits / limb_bits; + +// vector-like type that is allocated on the stack. the entire +// buffer is pre-allocated, and only the length changes. +template struct stackvec { + limb data[size]; + // we never need more than 150 limbs + uint16_t length{0}; + + stackvec() = default; + stackvec(const stackvec &) = delete; + stackvec &operator=(const stackvec &) = delete; + stackvec(stackvec &&) = delete; + stackvec &operator=(stackvec &&other) = delete; + + // create stack vector from existing limb span. + FASTFLOAT_CONSTEXPR20 stackvec(limb_span s) { + FASTFLOAT_ASSERT(try_extend(s)); + } + + FASTFLOAT_CONSTEXPR14 limb &operator[](size_t index) noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + return data[index]; + } + FASTFLOAT_CONSTEXPR14 const limb &operator[](size_t index) const noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + return data[index]; + } + // index from the end of the container + FASTFLOAT_CONSTEXPR14 const limb &rindex(size_t index) const noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + size_t rindex = length - index - 1; + return data[rindex]; + } + + // set the length, without bounds checking. + FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept { + length = uint16_t(len); + } + constexpr size_t len() const noexcept { return length; } + constexpr bool is_empty() const noexcept { return length == 0; } + constexpr size_t capacity() const noexcept { return size; } + // append item to vector, without bounds checking + FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept { + data[length] = value; + length++; + } + // append item to vector, returning if item was added + FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept { + if (len() < capacity()) { + push_unchecked(value); + return true; + } else { + return false; + } + } + // add items to the vector, from a span, without bounds checking + FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept { + limb *ptr = data + length; + std::copy_n(s.ptr, s.len(), ptr); + set_len(len() + s.len()); + } + // try to add items to the vector, returning if items were added + FASTFLOAT_CONSTEXPR20 bool try_extend(limb_span s) noexcept { + if (len() + s.len() <= capacity()) { + extend_unchecked(s); + return true; + } else { + return false; + } + } + // resize the vector, without bounds checking + // if the new size is longer than the vector, assign value to each + // appended item. + FASTFLOAT_CONSTEXPR20 + void resize_unchecked(size_t new_len, limb value) noexcept { + if (new_len > len()) { + size_t count = new_len - len(); + limb *first = data + len(); + limb *last = first + count; + ::std::fill(first, last, value); + set_len(new_len); + } else { + set_len(new_len); + } + } + // try to resize the vector, returning if the vector was resized. + FASTFLOAT_CONSTEXPR20 bool try_resize(size_t new_len, limb value) noexcept { + if (new_len > capacity()) { + return false; + } else { + resize_unchecked(new_len, value); + return true; + } + } + // check if any limbs are non-zero after the given index. + // this needs to be done in reverse order, since the index + // is relative to the most significant limbs. + FASTFLOAT_CONSTEXPR14 bool nonzero(size_t index) const noexcept { + while (index < len()) { + if (rindex(index) != 0) { + return true; + } + index++; + } + return false; + } + // normalize the big integer, so most-significant zero limbs are removed. + FASTFLOAT_CONSTEXPR14 void normalize() noexcept { + while (len() > 0 && rindex(0) == 0) { + length--; + } + } +}; + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t +empty_hi64(bool &truncated) noexcept { + truncated = false; + return 0; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint64_hi64(uint64_t r0, bool &truncated) noexcept { + truncated = false; + int shl = leading_zeroes(r0); + return r0 << shl; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint64_hi64(uint64_t r0, uint64_t r1, bool &truncated) noexcept { + int shl = leading_zeroes(r0); + if (shl == 0) { + truncated = r1 != 0; + return r0; + } else { + int shr = 64 - shl; + truncated = (r1 << shl) != 0; + return (r0 << shl) | (r1 >> shr); + } +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint32_hi64(uint32_t r0, bool &truncated) noexcept { + return uint64_hi64(r0, truncated); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint32_hi64(uint32_t r0, uint32_t r1, bool &truncated) noexcept { + uint64_t x0 = r0; + uint64_t x1 = r1; + return uint64_hi64((x0 << 32) | x1, truncated); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint32_hi64(uint32_t r0, uint32_t r1, uint32_t r2, bool &truncated) noexcept { + uint64_t x0 = r0; + uint64_t x1 = r1; + uint64_t x2 = r2; + return uint64_hi64(x0, (x1 << 32) | x2, truncated); +} + +// add two small integers, checking for overflow. +// we want an efficient operation. for msvc, where +// we don't have built-in intrinsics, this is still +// pretty fast. +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 limb +scalar_add(limb x, limb y, bool &overflow) noexcept { + limb z; +// gcc and clang +#if defined(__has_builtin) +#if __has_builtin(__builtin_add_overflow) + if (!cpp20_and_in_constexpr()) { + overflow = __builtin_add_overflow(x, y, &z); + return z; + } +#endif +#endif + + // generic, this still optimizes correctly on MSVC. + z = x + y; + overflow = z < x; + return z; +} + +// multiply two small integers, getting both the high and low bits. +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 limb +scalar_mul(limb x, limb y, limb &carry) noexcept { +#ifdef FASTFLOAT_64BIT_LIMB +#if defined(__SIZEOF_INT128__) + // GCC and clang both define it as an extension. + __uint128_t z = __uint128_t(x) * __uint128_t(y) + __uint128_t(carry); + carry = limb(z >> limb_bits); + return limb(z); +#else + // fallback, no native 128-bit integer multiplication with carry. + // on msvc, this optimizes identically, somehow. + value128 z = full_multiplication(x, y); + bool overflow; + z.low = scalar_add(z.low, carry, overflow); + z.high += uint64_t(overflow); // cannot overflow + carry = z.high; + return z.low; +#endif +#else + uint64_t z = uint64_t(x) * uint64_t(y) + uint64_t(carry); + carry = limb(z >> limb_bits); + return limb(z); +#endif +} + +// add scalar value to bigint starting from offset. +// used in grade school multiplication +template +inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec &vec, limb y, + size_t start) noexcept { + size_t index = start; + limb carry = y; + bool overflow; + while (carry != 0 && index < vec.len()) { + vec[index] = scalar_add(vec[index], carry, overflow); + carry = limb(overflow); + index += 1; + } + if (carry != 0) { + FASTFLOAT_TRY(vec.try_push(carry)); + } + return true; +} + +// add scalar value to bigint. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +small_add(stackvec &vec, limb y) noexcept { + return small_add_from(vec, y, 0); +} + +// multiply bigint by scalar value. +template +inline FASTFLOAT_CONSTEXPR20 bool small_mul(stackvec &vec, + limb y) noexcept { + limb carry = 0; + for (size_t index = 0; index < vec.len(); index++) { + vec[index] = scalar_mul(vec[index], y, carry); + } + if (carry != 0) { + FASTFLOAT_TRY(vec.try_push(carry)); + } + return true; +} + +// add bigint to bigint starting from index. +// used in grade school multiplication +template +FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec &x, limb_span y, + size_t start) noexcept { + // the effective x buffer is from `xstart..x.len()`, so exit early + // if we can't get that current range. + if (x.len() < start || y.len() > x.len() - start) { + FASTFLOAT_TRY(x.try_resize(y.len() + start, 0)); + } + + bool carry = false; + for (size_t index = 0; index < y.len(); index++) { + limb xi = x[index + start]; + limb yi = y[index]; + bool c1 = false; + bool c2 = false; + xi = scalar_add(xi, yi, c1); + if (carry) { + xi = scalar_add(xi, 1, c2); + } + x[index + start] = xi; + carry = c1 | c2; + } + + // handle overflow + if (carry) { + FASTFLOAT_TRY(small_add_from(x, 1, y.len() + start)); + } + return true; +} + +// add bigint to bigint. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +large_add_from(stackvec &x, limb_span y) noexcept { + return large_add_from(x, y, 0); +} + +// grade-school multiplication algorithm +template +FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec &x, limb_span y) noexcept { + limb_span xs = limb_span(x.data, x.len()); + stackvec z(xs); + limb_span zs = limb_span(z.data, z.len()); + + if (y.len() != 0) { + limb y0 = y[0]; + FASTFLOAT_TRY(small_mul(x, y0)); + for (size_t index = 1; index < y.len(); index++) { + limb yi = y[index]; + stackvec zi; + if (yi != 0) { + // re-use the same buffer throughout + zi.set_len(0); + FASTFLOAT_TRY(zi.try_extend(zs)); + FASTFLOAT_TRY(small_mul(zi, yi)); + limb_span zis = limb_span(zi.data, zi.len()); + FASTFLOAT_TRY(large_add_from(x, zis, index)); + } + } + } + + x.normalize(); + return true; +} + +// grade-school multiplication algorithm +template +FASTFLOAT_CONSTEXPR20 bool large_mul(stackvec &x, limb_span y) noexcept { + if (y.len() == 1) { + FASTFLOAT_TRY(small_mul(x, y[0])); + } else { + FASTFLOAT_TRY(long_mul(x, y)); + } + return true; +} + +template struct pow5_tables { + static constexpr uint32_t large_step = 135; + static constexpr uint64_t small_power_of_5[] = { + 1UL, + 5UL, + 25UL, + 125UL, + 625UL, + 3125UL, + 15625UL, + 78125UL, + 390625UL, + 1953125UL, + 9765625UL, + 48828125UL, + 244140625UL, + 1220703125UL, + 6103515625UL, + 30517578125UL, + 152587890625UL, + 762939453125UL, + 3814697265625UL, + 19073486328125UL, + 95367431640625UL, + 476837158203125UL, + 2384185791015625UL, + 11920928955078125UL, + 59604644775390625UL, + 298023223876953125UL, + 1490116119384765625UL, + 7450580596923828125UL, + }; +#ifdef FASTFLOAT_64BIT_LIMB + constexpr static limb large_power_of_5[] = { + 1414648277510068013UL, 9180637584431281687UL, 4539964771860779200UL, + 10482974169319127550UL, 198276706040285095UL}; +#else + constexpr static limb large_power_of_5[] = { + 4279965485U, 329373468U, 4020270615U, 2137533757U, 4287402176U, + 1057042919U, 1071430142U, 2440757623U, 381945767U, 46164893U}; +#endif +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template constexpr uint32_t pow5_tables::large_step; + +template constexpr uint64_t pow5_tables::small_power_of_5[]; + +template constexpr limb pow5_tables::large_power_of_5[]; + +#endif + +// big integer type. implements a small subset of big integer +// arithmetic, using simple algorithms since asymptotically +// faster algorithms are slower for a small number of limbs. +// all operations assume the big-integer is normalized. +struct bigint : pow5_tables<> { + // storage of the limbs, in little-endian order. + stackvec vec; + + FASTFLOAT_CONSTEXPR20 bigint() : vec() {} + bigint(const bigint &) = delete; + bigint &operator=(const bigint &) = delete; + bigint(bigint &&) = delete; + bigint &operator=(bigint &&other) = delete; + + FASTFLOAT_CONSTEXPR20 bigint(uint64_t value) : vec() { +#ifdef FASTFLOAT_64BIT_LIMB + vec.push_unchecked(value); +#else + vec.push_unchecked(uint32_t(value)); + vec.push_unchecked(uint32_t(value >> 32)); +#endif + vec.normalize(); + } + + // get the high 64 bits from the vector, and if bits were truncated. + // this is to get the significant digits for the float. + FASTFLOAT_CONSTEXPR20 uint64_t hi64(bool &truncated) const noexcept { +#ifdef FASTFLOAT_64BIT_LIMB + if (vec.len() == 0) { + return empty_hi64(truncated); + } else if (vec.len() == 1) { + return uint64_hi64(vec.rindex(0), truncated); + } else { + uint64_t result = uint64_hi64(vec.rindex(0), vec.rindex(1), truncated); + truncated |= vec.nonzero(2); + return result; + } +#else + if (vec.len() == 0) { + return empty_hi64(truncated); + } else if (vec.len() == 1) { + return uint32_hi64(vec.rindex(0), truncated); + } else if (vec.len() == 2) { + return uint32_hi64(vec.rindex(0), vec.rindex(1), truncated); + } else { + uint64_t result = + uint32_hi64(vec.rindex(0), vec.rindex(1), vec.rindex(2), truncated); + truncated |= vec.nonzero(3); + return result; + } +#endif + } + + // compare two big integers, returning the large value. + // assumes both are normalized. if the return value is + // negative, other is larger, if the return value is + // positive, this is larger, otherwise they are equal. + // the limbs are stored in little-endian order, so we + // must compare the limbs in ever order. + FASTFLOAT_CONSTEXPR20 int compare(const bigint &other) const noexcept { + if (vec.len() > other.vec.len()) { + return 1; + } else if (vec.len() < other.vec.len()) { + return -1; + } else { + for (size_t index = vec.len(); index > 0; index--) { + limb xi = vec[index - 1]; + limb yi = other.vec[index - 1]; + if (xi > yi) { + return 1; + } else if (xi < yi) { + return -1; + } + } + return 0; + } + } + + // shift left each limb n bits, carrying over to the new limb + // returns true if we were able to shift all the digits. + FASTFLOAT_CONSTEXPR20 bool shl_bits(size_t n) noexcept { + // Internally, for each item, we shift left by n, and add the previous + // right shifted limb-bits. + // For example, we transform (for u8) shifted left 2, to: + // b10100100 b01000010 + // b10 b10010001 b00001000 + FASTFLOAT_DEBUG_ASSERT(n != 0); + FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8); + + size_t shl = n; + size_t shr = limb_bits - shl; + limb prev = 0; + for (size_t index = 0; index < vec.len(); index++) { + limb xi = vec[index]; + vec[index] = (xi << shl) | (prev >> shr); + prev = xi; + } + + limb carry = prev >> shr; + if (carry != 0) { + return vec.try_push(carry); + } + return true; + } + + // move the limbs left by `n` limbs. + FASTFLOAT_CONSTEXPR20 bool shl_limbs(size_t n) noexcept { + FASTFLOAT_DEBUG_ASSERT(n != 0); + if (n + vec.len() > vec.capacity()) { + return false; + } else if (!vec.is_empty()) { + // move limbs + limb *dst = vec.data + n; + const limb *src = vec.data; + std::copy_backward(src, src + vec.len(), dst + vec.len()); + // fill in empty limbs + limb *first = vec.data; + limb *last = first + n; + ::std::fill(first, last, 0); + vec.set_len(n + vec.len()); + return true; + } else { + return true; + } + } + + // move the limbs left by `n` bits. + FASTFLOAT_CONSTEXPR20 bool shl(size_t n) noexcept { + size_t rem = n % limb_bits; + size_t div = n / limb_bits; + if (rem != 0) { + FASTFLOAT_TRY(shl_bits(rem)); + } + if (div != 0) { + FASTFLOAT_TRY(shl_limbs(div)); + } + return true; + } + + // get the number of leading zeros in the bigint. + FASTFLOAT_CONSTEXPR20 int ctlz() const noexcept { + if (vec.is_empty()) { + return 0; + } else { +#ifdef FASTFLOAT_64BIT_LIMB + return leading_zeroes(vec.rindex(0)); +#else + // no use defining a specialized leading_zeroes for a 32-bit type. + uint64_t r0 = vec.rindex(0); + return leading_zeroes(r0 << 32); +#endif + } + } + + // get the number of bits in the bigint. + FASTFLOAT_CONSTEXPR20 int bit_length() const noexcept { + int lz = ctlz(); + return int(limb_bits * vec.len()) - lz; + } + + FASTFLOAT_CONSTEXPR20 bool mul(limb y) noexcept { return small_mul(vec, y); } + + FASTFLOAT_CONSTEXPR20 bool add(limb y) noexcept { return small_add(vec, y); } + + // multiply as if by 2 raised to a power. + FASTFLOAT_CONSTEXPR20 bool pow2(uint32_t exp) noexcept { return shl(exp); } + + // multiply as if by 5 raised to a power. + FASTFLOAT_CONSTEXPR20 bool pow5(uint32_t exp) noexcept { + // multiply by a power of 5 + size_t large_length = sizeof(large_power_of_5) / sizeof(limb); + limb_span large = limb_span(large_power_of_5, large_length); + while (exp >= large_step) { + FASTFLOAT_TRY(large_mul(vec, large)); + exp -= large_step; + } +#ifdef FASTFLOAT_64BIT_LIMB + uint32_t small_step = 27; + limb max_native = 7450580596923828125UL; +#else + uint32_t small_step = 13; + limb max_native = 1220703125U; +#endif + while (exp >= small_step) { + FASTFLOAT_TRY(small_mul(vec, max_native)); + exp -= small_step; + } + if (exp != 0) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + // This is similar to https://github.com/llvm/llvm-project/issues/47746, + // except the workaround described there don't work here + FASTFLOAT_TRY(small_mul( + vec, limb(((void)small_power_of_5[0], small_power_of_5[exp])))); + } + + return true; + } + + // multiply as if by 10 raised to a power. + FASTFLOAT_CONSTEXPR20 bool pow10(uint32_t exp) noexcept { + FASTFLOAT_TRY(pow5(exp)); + return pow2(exp); + } +}; + +} // namespace fast_float + +#endif + +#ifndef FASTFLOAT_DIGIT_COMPARISON_H +#define FASTFLOAT_DIGIT_COMPARISON_H + +#include +#include +#include +#include + + +namespace fast_float { + +// 1e0 to 1e19 +constexpr static uint64_t powers_of_ten_uint64[] = {1UL, + 10UL, + 100UL, + 1000UL, + 10000UL, + 100000UL, + 1000000UL, + 10000000UL, + 100000000UL, + 1000000000UL, + 10000000000UL, + 100000000000UL, + 1000000000000UL, + 10000000000000UL, + 100000000000000UL, + 1000000000000000UL, + 10000000000000000UL, + 100000000000000000UL, + 1000000000000000000UL, + 10000000000000000000UL}; + +// calculate the exponent, in scientific notation, of the number. +// this algorithm is not even close to optimized, but it has no practical +// effect on performance: in order to have a faster algorithm, we'd need +// to slow down performance for faster algorithms, and this is still fast. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int32_t +scientific_exponent(parsed_number_string_t &num) noexcept { + uint64_t mantissa = num.mantissa; + int32_t exponent = int32_t(num.exponent); + while (mantissa >= 10000) { + mantissa /= 10000; + exponent += 4; + } + while (mantissa >= 100) { + mantissa /= 100; + exponent += 2; + } + while (mantissa >= 10) { + mantissa /= 10; + exponent += 1; + } + return exponent; +} + +// this converts a native floating-point number to an extended-precision float. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +to_extended(T value) noexcept { + using equiv_uint = typename binary_format::equiv_uint; + constexpr equiv_uint exponent_mask = binary_format::exponent_mask(); + constexpr equiv_uint mantissa_mask = binary_format::mantissa_mask(); + constexpr equiv_uint hidden_bit_mask = binary_format::hidden_bit_mask(); + + adjusted_mantissa am; + int32_t bias = binary_format::mantissa_explicit_bits() - + binary_format::minimum_exponent(); + equiv_uint bits; +#if FASTFLOAT_HAS_BIT_CAST + bits = std::bit_cast(value); +#else + ::memcpy(&bits, &value, sizeof(T)); +#endif + if ((bits & exponent_mask) == 0) { + // denormal + am.power2 = 1 - bias; + am.mantissa = bits & mantissa_mask; + } else { + // normal + am.power2 = int32_t((bits & exponent_mask) >> + binary_format::mantissa_explicit_bits()); + am.power2 -= bias; + am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; + } + + return am; +} + +// get the extended precision value of the halfway point between b and b+u. +// we are given a native float that represents b, so we need to adjust it +// halfway between b and b+u. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +to_extended_halfway(T value) noexcept { + adjusted_mantissa am = to_extended(value); + am.mantissa <<= 1; + am.mantissa += 1; + am.power2 -= 1; + return am; +} + +// round an extended-precision float to the nearest machine float. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void round(adjusted_mantissa &am, + callback cb) noexcept { + int32_t mantissa_shift = 64 - binary_format::mantissa_explicit_bits() - 1; + if (-am.power2 >= mantissa_shift) { + // have a denormal float + int32_t shift = -am.power2 + 1; + cb(am, std::min(shift, 64)); + // check for round-up: if rounding-nearest carried us to the hidden bit. + am.power2 = (am.mantissa < + (uint64_t(1) << binary_format::mantissa_explicit_bits())) + ? 0 + : 1; + return; + } + + // have a normal float, use the default shift. + cb(am, mantissa_shift); + + // check for carry + if (am.mantissa >= + (uint64_t(2) << binary_format::mantissa_explicit_bits())) { + am.mantissa = (uint64_t(1) << binary_format::mantissa_explicit_bits()); + am.power2++; + } + + // check for infinite: we could have carried to an infinite power + am.mantissa &= ~(uint64_t(1) << binary_format::mantissa_explicit_bits()); + if (am.power2 >= binary_format::infinite_power()) { + am.power2 = binary_format::infinite_power(); + am.mantissa = 0; + } +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void +round_nearest_tie_even(adjusted_mantissa &am, int32_t shift, + callback cb) noexcept { + const uint64_t mask = (shift == 64) ? UINT64_MAX : (uint64_t(1) << shift) - 1; + const uint64_t halfway = (shift == 0) ? 0 : uint64_t(1) << (shift - 1); + uint64_t truncated_bits = am.mantissa & mask; + bool is_above = truncated_bits > halfway; + bool is_halfway = truncated_bits == halfway; + + // shift digits into position + if (shift == 64) { + am.mantissa = 0; + } else { + am.mantissa >>= shift; + } + am.power2 += shift; + + bool is_odd = (am.mantissa & 1) == 1; + am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above)); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void +round_down(adjusted_mantissa &am, int32_t shift) noexcept { + if (shift == 64) { + am.mantissa = 0; + } else { + am.mantissa >>= shift; + } + am.power2 += shift; +} +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +skip_zeros(UC const *&first, UC const *last) noexcept { + uint64_t val; + while (!cpp20_and_in_constexpr() && + std::distance(first, last) >= int_cmp_len()) { + ::memcpy(&val, first, sizeof(uint64_t)); + if (val != int_cmp_zeros()) { + break; + } + first += int_cmp_len(); + } + while (first != last) { + if (*first != UC('0')) { + break; + } + first++; + } +} + +// determine if any non-zero digits were truncated. +// all characters must be valid digits. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +is_truncated(UC const *first, UC const *last) noexcept { + // do 8-bit optimizations, can just compare to 8 literal 0s. + uint64_t val; + while (!cpp20_and_in_constexpr() && + std::distance(first, last) >= int_cmp_len()) { + ::memcpy(&val, first, sizeof(uint64_t)); + if (val != int_cmp_zeros()) { + return true; + } + first += int_cmp_len(); + } + while (first != last) { + if (*first != UC('0')) { + return true; + } + ++first; + } + return false; +} +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +is_truncated(span s) noexcept { + return is_truncated(s.ptr, s.ptr + s.len()); +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +parse_eight_digits(const UC *&p, limb &value, size_t &counter, + size_t &count) noexcept { + value = value * 100000000 + parse_eight_digits_unrolled(p); + p += 8; + counter += 8; + count += 8; +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void +parse_one_digit(UC const *&p, limb &value, size_t &counter, + size_t &count) noexcept { + value = value * 10 + limb(*p - UC('0')); + p++; + counter++; + count++; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +add_native(bigint &big, limb power, limb value) noexcept { + big.mul(power); + big.add(value); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +round_up_bigint(bigint &big, size_t &count) noexcept { + // need to round-up the digits, but need to avoid rounding + // ....9999 to ...10000, which could cause a false halfway point. + add_native(big, 10, 1); + count++; +} + +// parse the significant digits into a big integer +template +inline FASTFLOAT_CONSTEXPR20 void +parse_mantissa(bigint &result, parsed_number_string_t &num, + size_t max_digits, size_t &digits) noexcept { + // try to minimize the number of big integer and scalar multiplication. + // therefore, try to parse 8 digits at a time, and multiply by the largest + // scalar value (9 or 19 digits) for each step. + size_t counter = 0; + digits = 0; + limb value = 0; +#ifdef FASTFLOAT_64BIT_LIMB + size_t step = 19; +#else + size_t step = 9; +#endif + + // process all integer digits. + UC const *p = num.integer.ptr; + UC const *pend = p + num.integer.len(); + skip_zeros(p, pend); + // process all digits, in increments of step per loop + while (p != pend) { + while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && + (max_digits - digits >= 8)) { + parse_eight_digits(p, value, counter, digits); + } + while (counter < step && p != pend && digits < max_digits) { + parse_one_digit(p, value, counter, digits); + } + if (digits == max_digits) { + // add the temporary value, then check if we've truncated any digits + add_native(result, limb(powers_of_ten_uint64[counter]), value); + bool truncated = is_truncated(p, pend); + if (num.fraction.ptr != nullptr) { + truncated |= is_truncated(num.fraction); + } + if (truncated) { + round_up_bigint(result, digits); + } + return; + } else { + add_native(result, limb(powers_of_ten_uint64[counter]), value); + counter = 0; + value = 0; + } + } + + // add our fraction digits, if they're available. + if (num.fraction.ptr != nullptr) { + p = num.fraction.ptr; + pend = p + num.fraction.len(); + if (digits == 0) { + skip_zeros(p, pend); + } + // process all digits, in increments of step per loop + while (p != pend) { + while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && + (max_digits - digits >= 8)) { + parse_eight_digits(p, value, counter, digits); + } + while (counter < step && p != pend && digits < max_digits) { + parse_one_digit(p, value, counter, digits); + } + if (digits == max_digits) { + // add the temporary value, then check if we've truncated any digits + add_native(result, limb(powers_of_ten_uint64[counter]), value); + bool truncated = is_truncated(p, pend); + if (truncated) { + round_up_bigint(result, digits); + } + return; + } else { + add_native(result, limb(powers_of_ten_uint64[counter]), value); + counter = 0; + value = 0; + } + } + } + + if (counter != 0) { + add_native(result, limb(powers_of_ten_uint64[counter]), value); + } +} + +template +inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +positive_digit_comp(bigint &bigmant, int32_t exponent) noexcept { + FASTFLOAT_ASSERT(bigmant.pow10(uint32_t(exponent))); + adjusted_mantissa answer; + bool truncated; + answer.mantissa = bigmant.hi64(truncated); + int bias = binary_format::mantissa_explicit_bits() - + binary_format::minimum_exponent(); + answer.power2 = bigmant.bit_length() - 64 + bias; + + round(answer, [truncated](adjusted_mantissa &a, int32_t shift) { + round_nearest_tie_even( + a, shift, + [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool { + return is_above || (is_halfway && truncated) || + (is_odd && is_halfway); + }); + }); + + return answer; +} + +// the scaling here is quite simple: we have, for the real digits `m * 10^e`, +// and for the theoretical digits `n * 2^f`. Since `e` is always negative, +// to scale them identically, we do `n * 2^f * 5^-f`, so we now have `m * 2^e`. +// we then need to scale by `2^(f- e)`, and then the two significant digits +// are of the same magnitude. +template +inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa negative_digit_comp( + bigint &bigmant, adjusted_mantissa am, int32_t exponent) noexcept { + bigint &real_digits = bigmant; + int32_t real_exp = exponent; + + // get the value of `b`, rounded down, and get a bigint representation of b+h + adjusted_mantissa am_b = am; + // gcc7 buf: use a lambda to remove the noexcept qualifier bug with + // -Wnoexcept-type. + round(am_b, + [](adjusted_mantissa &a, int32_t shift) { round_down(a, shift); }); + T b; + to_float(false, am_b, b); + adjusted_mantissa theor = to_extended_halfway(b); + bigint theor_digits(theor.mantissa); + int32_t theor_exp = theor.power2; + + // scale real digits and theor digits to be same power. + int32_t pow2_exp = theor_exp - real_exp; + uint32_t pow5_exp = uint32_t(-real_exp); + if (pow5_exp != 0) { + FASTFLOAT_ASSERT(theor_digits.pow5(pow5_exp)); + } + if (pow2_exp > 0) { + FASTFLOAT_ASSERT(theor_digits.pow2(uint32_t(pow2_exp))); + } else if (pow2_exp < 0) { + FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp))); + } + + // compare digits, and use it to director rounding + int ord = real_digits.compare(theor_digits); + adjusted_mantissa answer = am; + round(answer, [ord](adjusted_mantissa &a, int32_t shift) { + round_nearest_tie_even( + a, shift, [ord](bool is_odd, bool _, bool __) -> bool { + (void)_; // not needed, since we've done our comparison + (void)__; // not needed, since we've done our comparison + if (ord > 0) { + return true; + } else if (ord < 0) { + return false; + } else { + return is_odd; + } + }); + }); + + return answer; +} + +// parse the significant digits as a big integer to unambiguously round the +// the significant digits. here, we are trying to determine how to round +// an extended float representation close to `b+h`, halfway between `b` +// (the float rounded-down) and `b+u`, the next positive float. this +// algorithm is always correct, and uses one of two approaches. when +// the exponent is positive relative to the significant digits (such as +// 1234), we create a big-integer representation, get the high 64-bits, +// determine if any lower bits are truncated, and use that to direct +// rounding. in case of a negative exponent relative to the significant +// digits (such as 1.2345), we create a theoretical representation of +// `b` as a big-integer type, scaled to the same binary exponent as +// the actual digits. we then compare the big integer representations +// of both, and use that to direct rounding. +template +inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +digit_comp(parsed_number_string_t &num, adjusted_mantissa am) noexcept { + // remove the invalid exponent bias + am.power2 -= invalid_am_bias; + + int32_t sci_exp = scientific_exponent(num); + size_t max_digits = binary_format::max_digits(); + size_t digits = 0; + bigint bigmant; + parse_mantissa(bigmant, num, max_digits, digits); + // can't underflow, since digits is at most max_digits. + int32_t exponent = sci_exp + 1 - int32_t(digits); + if (exponent >= 0) { + return positive_digit_comp(bigmant, exponent); + } else { + return negative_digit_comp(bigmant, am, exponent); + } +} + +} // namespace fast_float + +#endif + +#ifndef FASTFLOAT_PARSE_NUMBER_H +#define FASTFLOAT_PARSE_NUMBER_H + + +#include +#include +#include +#include +namespace fast_float { + +namespace detail { +/** + * Special case +inf, -inf, nan, infinity, -infinity. + * The case comparisons could be made much faster given that we know that the + * strings a null-free and fixed. + **/ +template +from_chars_result_t + FASTFLOAT_CONSTEXPR14 parse_infnan(UC const *first, UC const *last, + T &value, chars_format fmt) noexcept { + from_chars_result_t answer{}; + answer.ptr = first; + answer.ec = std::errc(); // be optimistic + // assume first < last, so dereference without checks; + bool const minusSign = (*first == UC('-')); + // C++17 20.19.3.(7.1) explicitly forbids '+' sign here + if ((*first == UC('-')) || + (uint64_t(fmt & chars_format::allow_leading_plus) && + (*first == UC('+')))) { + ++first; + } + if (last - first >= 3) { + if (fastfloat_strncasecmp(first, str_const_nan(), 3)) { + answer.ptr = (first += 3); + value = minusSign ? -std::numeric_limits::quiet_NaN() + : std::numeric_limits::quiet_NaN(); + // Check for possible nan(n-char-seq-opt), C++17 20.19.3.7, + // C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan). + if (first != last && *first == UC('(')) { + for (UC const *ptr = first + 1; ptr != last; ++ptr) { + if (*ptr == UC(')')) { + answer.ptr = ptr + 1; // valid nan(n-char-seq-opt) + break; + } else if (!((UC('a') <= *ptr && *ptr <= UC('z')) || + (UC('A') <= *ptr && *ptr <= UC('Z')) || + (UC('0') <= *ptr && *ptr <= UC('9')) || *ptr == UC('_'))) + break; // forbidden char, not nan(n-char-seq-opt) + } + } + return answer; + } + if (fastfloat_strncasecmp(first, str_const_inf(), 3)) { + if ((last - first >= 8) && + fastfloat_strncasecmp(first + 3, str_const_inf() + 3, 5)) { + answer.ptr = first + 8; + } else { + answer.ptr = first + 3; + } + value = minusSign ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(); + return answer; + } + } + answer.ec = std::errc::invalid_argument; + return answer; +} + +/** + * Returns true if the floating-pointing rounding mode is to 'nearest'. + * It is the default on most system. This function is meant to be inexpensive. + * Credit : @mwalcott3 + */ +fastfloat_really_inline bool rounds_to_nearest() noexcept { + // https://lemire.me/blog/2020/06/26/gcc-not-nearest/ +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return false; +#endif + // See + // A fast function to check your floating-point rounding mode + // https://lemire.me/blog/2022/11/16/a-fast-function-to-check-your-floating-point-rounding-mode/ + // + // This function is meant to be equivalent to : + // prior: #include + // return fegetround() == FE_TONEAREST; + // However, it is expected to be much faster than the fegetround() + // function call. + // + // The volatile keyword prevents the compiler from computing the function + // at compile-time. + // There might be other ways to prevent compile-time optimizations (e.g., + // asm). The value does not need to be std::numeric_limits::min(), any + // small value so that 1 + x should round to 1 would do (after accounting for + // excess precision, as in 387 instructions). + static volatile float fmin = std::numeric_limits::min(); + float fmini = fmin; // we copy it so that it gets loaded at most once. +// +// Explanation: +// Only when fegetround() == FE_TONEAREST do we have that +// fmin + 1.0f == 1.0f - fmin. +// +// FE_UPWARD: +// fmin + 1.0f > 1 +// 1.0f - fmin == 1 +// +// FE_DOWNWARD or FE_TOWARDZERO: +// fmin + 1.0f == 1 +// 1.0f - fmin < 1 +// +// Note: This may fail to be accurate if fast-math has been +// enabled, as rounding conventions may not apply. +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(push) +// todo: is there a VS warning? +// see +// https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013 +#elif defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wfloat-equal" +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + return (fmini + 1.0f == 1.0f - fmini); +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(pop) +#elif defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif +} + +} // namespace detail + +template struct from_chars_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_advanced(first, last, value, options); + } +}; + +#if __STDCPP_FLOAT32_T__ == 1 +template <> struct from_chars_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, std::float32_t &value, + parse_options_t options) noexcept { + // if std::float32_t is defined, and we are in C++23 mode; macro set for + // float32; set value to float due to equivalence between float and + // float32_t + float val; + auto ret = from_chars_advanced(first, last, val, options); + value = val; + return ret; + } +}; +#endif + +#if __STDCPP_FLOAT64_T__ == 1 +template <> struct from_chars_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, std::float64_t &value, + parse_options_t options) noexcept { + // if std::float64_t is defined, and we are in C++23 mode; macro set for + // float64; set value as double due to equivalence between double and + // float64_t + double val; + auto ret = from_chars_advanced(first, last, val, options); + value = val; + return ret; + } +}; +#endif + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, + chars_format fmt /*= chars_format::general*/) noexcept { + return from_chars_caller::call(first, last, value, + parse_options_t(fmt)); +} + +/** + * This function overload takes parsed_number_string_t structure that is created + * and populated either by from_chars_advanced function taking chars range and + * parsing options or other parsing custom function implemented by user. + */ +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_advanced(parsed_number_string_t &pns, T &value) noexcept { + + static_assert(is_supported_float_type(), + "only some floating-point types are supported"); + static_assert(is_supported_char_type(), + "only char, wchar_t, char16_t and char32_t are supported"); + + from_chars_result_t answer; + + answer.ec = std::errc(); // be optimistic + answer.ptr = pns.lastmatch; + // The implementation of the Clinger's fast path is convoluted because + // we want round-to-nearest in all cases, irrespective of the rounding mode + // selected on the thread. + // We proceed optimistically, assuming that detail::rounds_to_nearest() + // returns true. + if (binary_format::min_exponent_fast_path() <= pns.exponent && + pns.exponent <= binary_format::max_exponent_fast_path() && + !pns.too_many_digits) { + // Unfortunately, the conventional Clinger's fast path is only possible + // when the system rounds to the nearest float. + // + // We expect the next branch to almost always be selected. + // We could check it first (before the previous branch), but + // there might be performance advantages at having the check + // be last. + if (!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) { + // We have that fegetround() == FE_TONEAREST. + // Next is Clinger's fast path. + if (pns.mantissa <= binary_format::max_mantissa_fast_path()) { + value = T(pns.mantissa); + if (pns.exponent < 0) { + value = value / binary_format::exact_power_of_ten(-pns.exponent); + } else { + value = value * binary_format::exact_power_of_ten(pns.exponent); + } + if (pns.negative) { + value = -value; + } + return answer; + } + } else { + // We do not have that fegetround() == FE_TONEAREST. + // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's + // proposal + if (pns.exponent >= 0 && + pns.mantissa <= + binary_format::max_mantissa_fast_path(pns.exponent)) { +#if defined(__clang__) || defined(FASTFLOAT_32BIT) + // Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD + if (pns.mantissa == 0) { + value = pns.negative ? T(-0.) : T(0.); + return answer; + } +#endif + value = T(pns.mantissa) * + binary_format::exact_power_of_ten(pns.exponent); + if (pns.negative) { + value = -value; + } + return answer; + } + } + } + adjusted_mantissa am = + compute_float>(pns.exponent, pns.mantissa); + if (pns.too_many_digits && am.power2 >= 0) { + if (am != compute_float>(pns.exponent, pns.mantissa + 1)) { + am = compute_error>(pns.exponent, pns.mantissa); + } + } + // If we called compute_float>(pns.exponent, pns.mantissa) + // and we have an invalid power (am.power2 < 0), then we need to go the long + // way around again. This is very uncommon. + if (am.power2 < 0) { + am = digit_comp(pns, am); + } + to_float(pns.negative, am, value); + // Test for over/underflow. + if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) || + am.power2 == binary_format::infinite_power()) { + answer.ec = std::errc::result_out_of_range; + } + return answer; +} + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_float_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + + static_assert(is_supported_float_type(), + "only some floating-point types are supported"); + static_assert(is_supported_char_type(), + "only char, wchar_t, char16_t and char32_t are supported"); + + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + + from_chars_result_t answer; + if (uint64_t(fmt & chars_format::skip_white_space)) { + while ((first != last) && fast_float::is_space(*first)) { + first++; + } + } + if (first == last) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + parsed_number_string_t pns = + parse_number_string(first, last, options); + if (!pns.valid) { + if (uint64_t(fmt & chars_format::no_infnan)) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } else { + return detail::parse_infnan(first, last, value, fmt); + } + } + + // call overload that takes parsed_number_string_t directly. + return from_chars_advanced(pns, value); +} + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, int base) noexcept { + + static_assert(std::is_integral::value, "only integer types are supported"); + static_assert(is_supported_char_type(), + "only char, wchar_t, char16_t and char32_t are supported"); + + parse_options_t options; + options.base = base; + return from_chars_advanced(first, last, value, options); +} + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_int_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + + static_assert(std::is_integral::value, "only integer types are supported"); + static_assert(is_supported_char_type(), + "only char, wchar_t, char16_t and char32_t are supported"); + + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + int const base = options.base; + + from_chars_result_t answer; + if (uint64_t(fmt & chars_format::skip_white_space)) { + while ((first != last) && fast_float::is_space(*first)) { + first++; + } + } + if (first == last || base < 2 || base > 36) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + + return parse_int_string(first, last, value, options); +} + +template struct from_chars_advanced_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_float_advanced(first, last, value, options); + } +}; + +template <> struct from_chars_advanced_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_int_advanced(first, last, value, options); + } +}; + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_advanced_caller()>::call( + first, last, value, options); +} + +} // namespace fast_float + +#endif + diff --git a/lib3mf/Lib/lib3mfD32.lib b/lib3mf/Lib/lib3mfD32.lib index ba320b3..37f0634 100644 Binary files a/lib3mf/Lib/lib3mfD32.lib and b/lib3mf/Lib/lib3mfD32.lib differ diff --git a/lib3mf/Lib/lib3mfD32.pdb b/lib3mf/Lib/lib3mfD32.pdb index 74e27db..7767f95 100644 Binary files a/lib3mf/Lib/lib3mfD32.pdb and b/lib3mf/Lib/lib3mfD32.pdb differ diff --git a/lib3mf/Lib/lib3mfD64.lib b/lib3mf/Lib/lib3mfD64.lib index 2f553b8..f5c69b7 100644 Binary files a/lib3mf/Lib/lib3mfD64.lib and b/lib3mf/Lib/lib3mfD64.lib differ diff --git a/lib3mf/Lib/lib3mfD64.pdb b/lib3mf/Lib/lib3mfD64.pdb index b40c2ea..eb8ef8b 100644 Binary files a/lib3mf/Lib/lib3mfD64.pdb and b/lib3mf/Lib/lib3mfD64.pdb differ diff --git a/lib3mf/Lib/lib3mfR32.lib b/lib3mf/Lib/lib3mfR32.lib index e792e36..a2c2e18 100644 Binary files a/lib3mf/Lib/lib3mfR32.lib and b/lib3mf/Lib/lib3mfR32.lib differ diff --git a/lib3mf/Lib/lib3mfR64.lib b/lib3mf/Lib/lib3mfR64.lib index 1c931d1..39ff7c8 100644 Binary files a/lib3mf/Lib/lib3mfR64.lib and b/lib3mf/Lib/lib3mfR64.lib differ diff --git a/libzip/Lib/zipD32.lib b/libzip/Lib/zipD32.lib index d47bbc7..f6e05f3 100644 Binary files a/libzip/Lib/zipD32.lib and b/libzip/Lib/zipD32.lib differ diff --git a/libzip/Lib/zipD32.pdb b/libzip/Lib/zipD32.pdb index 2073d3f..83ce649 100644 Binary files a/libzip/Lib/zipD32.pdb and b/libzip/Lib/zipD32.pdb differ diff --git a/libzip/Lib/zipD64.lib b/libzip/Lib/zipD64.lib index b7877e8..0004a66 100644 Binary files a/libzip/Lib/zipD64.lib and b/libzip/Lib/zipD64.lib differ diff --git a/libzip/Lib/zipD64.pdb b/libzip/Lib/zipD64.pdb index c6c9c6c..b63e44c 100644 Binary files a/libzip/Lib/zipD64.pdb and b/libzip/Lib/zipD64.pdb differ diff --git a/libzip/Lib/zipR32.lib b/libzip/Lib/zipR32.lib index fcada75..14ce1e7 100644 Binary files a/libzip/Lib/zipR32.lib and b/libzip/Lib/zipR32.lib differ diff --git a/libzip/Lib/zipR64.lib b/libzip/Lib/zipR64.lib index 0d9b502..d34cc4a 100644 Binary files a/libzip/Lib/zipR64.lib and b/libzip/Lib/zipR64.lib differ diff --git a/opennurbs/Lib/opennurbs_publicD64.lib b/opennurbs/Lib/opennurbs_publicD64.lib index d2335fc..0015549 100644 Binary files a/opennurbs/Lib/opennurbs_publicD64.lib and b/opennurbs/Lib/opennurbs_publicD64.lib differ diff --git a/opennurbs/Lib/opennurbs_publicD64.pdb b/opennurbs/Lib/opennurbs_publicD64.pdb index 97768b5..c5f808c 100644 Binary files a/opennurbs/Lib/opennurbs_publicD64.pdb and b/opennurbs/Lib/opennurbs_publicD64.pdb differ diff --git a/opennurbs/Lib/opennurbs_publicR32.lib b/opennurbs/Lib/opennurbs_publicR32.lib index 1ece764..bdb9a0f 100644 Binary files a/opennurbs/Lib/opennurbs_publicR32.lib and b/opennurbs/Lib/opennurbs_publicR32.lib differ diff --git a/opennurbs/Lib/opennurbs_publicR64.lib b/opennurbs/Lib/opennurbs_publicR64.lib index 347d0bc..b9ddfb9 100644 Binary files a/opennurbs/Lib/opennurbs_publicR64.lib and b/opennurbs/Lib/opennurbs_publicR64.lib differ diff --git a/opennurbs/Lib/opennurbs_publicR64.pdb b/opennurbs/Lib/opennurbs_publicR64.pdb index daf98d4..1c1ff0d 100644 Binary files a/opennurbs/Lib/opennurbs_publicR64.pdb and b/opennurbs/Lib/opennurbs_publicR64.pdb differ diff --git a/vroni/Lib/vroniD32.lib b/vroni/Lib/vroniD32.lib index 88ace2a..365e5cb 100644 Binary files a/vroni/Lib/vroniD32.lib and b/vroni/Lib/vroniD32.lib differ diff --git a/vroni/Lib/vroniD32.pdb b/vroni/Lib/vroniD32.pdb index ef28ba5..e7a8140 100644 Binary files a/vroni/Lib/vroniD32.pdb and b/vroni/Lib/vroniD32.pdb differ diff --git a/vroni/Lib/vroniD64.lib b/vroni/Lib/vroniD64.lib index 308646b..66755ca 100644 Binary files a/vroni/Lib/vroniD64.lib and b/vroni/Lib/vroniD64.lib differ diff --git a/vroni/Lib/vroniR32.lib b/vroni/Lib/vroniR32.lib index e0ce79e..7d86273 100644 Binary files a/vroni/Lib/vroniR32.lib and b/vroni/Lib/vroniR32.lib differ diff --git a/vroni/Lib/vroniR64.lib b/vroni/Lib/vroniR64.lib index b758702..3d28780 100644 Binary files a/vroni/Lib/vroniR64.lib and b/vroni/Lib/vroniR64.lib differ diff --git a/zlib/Lib/zlibD32.lib b/zlib/Lib/zlibD32.lib index 2f47f94..45489f4 100644 Binary files a/zlib/Lib/zlibD32.lib and b/zlib/Lib/zlibD32.lib differ diff --git a/zlib/Lib/zlibD32.pdb b/zlib/Lib/zlibD32.pdb index e666db5..37319b0 100644 Binary files a/zlib/Lib/zlibD32.pdb and b/zlib/Lib/zlibD32.pdb differ diff --git a/zlib/Lib/zlibD64.lib b/zlib/Lib/zlibD64.lib index 483582d..d0e8c9c 100644 Binary files a/zlib/Lib/zlibD64.lib and b/zlib/Lib/zlibD64.lib differ diff --git a/zlib/Lib/zlibD64.pdb b/zlib/Lib/zlibD64.pdb index 0e6f7fb..d85ecfb 100644 Binary files a/zlib/Lib/zlibD64.pdb and b/zlib/Lib/zlibD64.pdb differ diff --git a/zlib/Lib/zlibR32.lib b/zlib/Lib/zlibR32.lib index c9cdc6d..5e855b6 100644 Binary files a/zlib/Lib/zlibR32.lib and b/zlib/Lib/zlibR32.lib differ diff --git a/zlib/Lib/zlibR64.lib b/zlib/Lib/zlibR64.lib index 4bfcb07..e25bbd5 100644 Binary files a/zlib/Lib/zlibR64.lib and b/zlib/Lib/zlibR64.lib differ