Merge pull request #9780 from chennes/toponamingComplexGeoDataDressing
Toponaming: ComplexGeoData dressing
This commit is contained in:
@@ -1,27 +1,30 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* Copyright (c) 2022 Zheng, Lei <realthunder.dev@gmail.com> *
|
||||
* Copyright (c) 2023 FreeCAD Project Association *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#include "PreCompiled.h"// NOLINT
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <cstdlib>
|
||||
@@ -30,19 +33,27 @@
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include "ComplexGeoData.h"
|
||||
#include "ElementMap.h"
|
||||
#include "ElementNamingUtils.h"
|
||||
|
||||
#include <Base/BoundBox.h>
|
||||
#include <Base/Placement.h>
|
||||
#include <Base/Rotation.h>
|
||||
|
||||
#include <boost/iostreams/device/array.hpp>
|
||||
|
||||
|
||||
using namespace Data;
|
||||
|
||||
TYPESYSTEM_SOURCE_ABSTRACT(Data::Segment , Base::BaseClass)
|
||||
TYPESYSTEM_SOURCE_ABSTRACT(Data::Segment , Base::BaseClass)// NOLINT
|
||||
TYPESYSTEM_SOURCE_ABSTRACT(Data::ComplexGeoData , Base::Persistence)// NOLINT
|
||||
|
||||
FC_LOG_LEVEL_INIT("ComplexGeoData", true,true)// NOLINT
|
||||
|
||||
TYPESYSTEM_SOURCE_ABSTRACT(Data::ComplexGeoData , Base::Persistence)
|
||||
namespace bio = boost::iostreams;
|
||||
using namespace Data;
|
||||
|
||||
// NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
|
||||
ComplexGeoData::ComplexGeoData()
|
||||
:Tag(0)
|
||||
@@ -94,10 +105,10 @@ Base::Placement ComplexGeoData::getPlacement() const
|
||||
{
|
||||
Base::Matrix4D mat = getTransform();
|
||||
|
||||
return Base::Placement(Base::Vector3d(mat[0][3],
|
||||
mat[1][3],
|
||||
mat[2][3]),
|
||||
Base::Rotation(mat));
|
||||
return {Base::Vector3d(mat[0][3],
|
||||
mat[1][3],
|
||||
mat[2][3]),
|
||||
Base::Rotation(mat)};
|
||||
}
|
||||
|
||||
double ComplexGeoData::getAccuracy() const
|
||||
@@ -105,19 +116,21 @@ double ComplexGeoData::getAccuracy() const
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void ComplexGeoData::getLinesFromSubElement(const Segment*,
|
||||
void ComplexGeoData::getLinesFromSubElement(const Segment* segment,
|
||||
std::vector<Base::Vector3d> &Points,
|
||||
std::vector<Line> &lines) const
|
||||
{
|
||||
(void)segment;
|
||||
(void)Points;
|
||||
(void)lines;
|
||||
}
|
||||
|
||||
void ComplexGeoData::getFacesFromSubElement(const Segment*,
|
||||
void ComplexGeoData::getFacesFromSubElement(const Segment* segment,
|
||||
std::vector<Base::Vector3d> &Points,
|
||||
std::vector<Base::Vector3d> &PointNormals,
|
||||
std::vector<Facet> &faces) const
|
||||
{
|
||||
(void)segment;
|
||||
(void)Points;
|
||||
(void)PointNormals;
|
||||
(void)faces;
|
||||
@@ -161,8 +174,215 @@ void ComplexGeoData::getFaces(std::vector<Base::Vector3d> &Points,
|
||||
(void)flags;
|
||||
}
|
||||
|
||||
bool ComplexGeoData::getCenterOfGravity(Base::Vector3d&) const
|
||||
bool ComplexGeoData::getCenterOfGravity(Base::Vector3d& unused) const
|
||||
{
|
||||
(void)unused;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t ComplexGeoData::getElementMapSize(bool flush) const {
|
||||
if (flush) {
|
||||
flushElementMap();
|
||||
#ifdef _FC_MEM_TRACE
|
||||
FC_MSG("memory size " << (_MemSize/1024/1024) << "MB, " << (_MemMaxSize/1024/1024));
|
||||
for (auto &unit : _MemUnits)
|
||||
FC_MSG("unit " << unit.first << ": " << unit.second.count << ", " << unit.second.maxcount);
|
||||
#endif
|
||||
}
|
||||
return _elementMap ? _elementMap->size():0;
|
||||
}
|
||||
|
||||
MappedName ComplexGeoData::getMappedName(const IndexedName & element,
|
||||
bool allowUnmapped,
|
||||
ElementIDRefs *sid) const
|
||||
{
|
||||
if (!element) {
|
||||
return {};
|
||||
}
|
||||
flushElementMap();
|
||||
if(!_elementMap) {
|
||||
if (allowUnmapped) {
|
||||
return MappedName(element);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
MappedName name = _elementMap->find(element, sid);
|
||||
if (allowUnmapped && !name) {
|
||||
return MappedName(element);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
IndexedName ComplexGeoData::getIndexedName(const MappedName & name,
|
||||
ElementIDRefs *sid) const
|
||||
{
|
||||
flushElementMap();
|
||||
if (!name) {
|
||||
return IndexedName();
|
||||
}
|
||||
if (!_elementMap) {
|
||||
std::string str;
|
||||
return {name.appendToBuffer(str), getElementTypes()};
|
||||
}
|
||||
return _elementMap->find(name, sid);
|
||||
}
|
||||
|
||||
Data::MappedElement
|
||||
ComplexGeoData::getElementName(const char *name,
|
||||
ElementIDRefs *sid,
|
||||
bool copy) const
|
||||
{
|
||||
IndexedName element(name, getElementTypes());
|
||||
if (element) {
|
||||
return {getMappedName(element, false, sid), element};
|
||||
}
|
||||
|
||||
const char * mapped = isMappedElement(name);
|
||||
if (mapped) {
|
||||
name = mapped;
|
||||
}
|
||||
|
||||
MappedElement result;
|
||||
// Strip out the trailing '.XXXX' if any
|
||||
const char *dot = strchr(name,'.');
|
||||
if(dot) {
|
||||
result.name = MappedName(name, dot - name);
|
||||
}
|
||||
else if (copy) {
|
||||
result.name = name;
|
||||
}
|
||||
else {
|
||||
result.name = MappedName(name);
|
||||
}
|
||||
result.index = getIndexedName(result.name, sid);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::pair<MappedName, ElementIDRefs> >
|
||||
ComplexGeoData::getElementMappedNames(const IndexedName & element, bool needUnmapped) const {
|
||||
flushElementMap();
|
||||
if(_elementMap) {
|
||||
auto res = _elementMap->findAll(element);
|
||||
if (!res.empty()) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needUnmapped) {
|
||||
return {};
|
||||
}
|
||||
return {std::make_pair(MappedName(element), ElementIDRefs())};
|
||||
}
|
||||
|
||||
std::vector<MappedElement> ComplexGeoData::getElementMap() const {
|
||||
flushElementMap();
|
||||
if(!_elementMap) {
|
||||
return {};
|
||||
}
|
||||
return _elementMap->getAll();
|
||||
}
|
||||
|
||||
ElementMapPtr ComplexGeoData::elementMap(bool flush) const
|
||||
{
|
||||
if (flush) {
|
||||
flushElementMap();
|
||||
}
|
||||
return _elementMap;
|
||||
}
|
||||
|
||||
void ComplexGeoData::flushElementMap() const
|
||||
{
|
||||
}
|
||||
|
||||
void ComplexGeoData::setElementMap(const std::vector<MappedElement> &map) {
|
||||
_elementMap = std::make_shared<Data::ElementMap>(); // Get rid of the old one, if any, but make
|
||||
// sure the memory exists for the new data.
|
||||
for(auto &element : map) {
|
||||
_elementMap->setElementName(element.index, element.name, Tag);
|
||||
}
|
||||
}
|
||||
|
||||
char ComplexGeoData::elementType(const Data::MappedName &name) const
|
||||
{
|
||||
if(!name) {
|
||||
return 0;
|
||||
}
|
||||
auto indexedName = getIndexedName(name);
|
||||
if (indexedName) {
|
||||
return elementType(indexedName);
|
||||
}
|
||||
char element_type=0;
|
||||
if (name.findTagInElementName(nullptr,nullptr,nullptr,&element_type) < 0) {
|
||||
return elementType(name.toIndexedName());
|
||||
}
|
||||
return element_type;
|
||||
}
|
||||
|
||||
char ComplexGeoData::elementType(const Data::IndexedName &element) const
|
||||
{
|
||||
if(!element) {
|
||||
return 0;
|
||||
}
|
||||
for(auto &type : getElementTypes()) {
|
||||
if(boost::equals(element.getType(), type)) {
|
||||
return type[0];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The elementType function can take a char *, in which case it tries a sequence of checks to
|
||||
// see what it got.
|
||||
// 1) Check to see if it is an indexedName, and if so directly look up the type
|
||||
// 2) If not:
|
||||
// a) Remove any element map prefix that is present
|
||||
// b) See if the name contains a dot:
|
||||
// i) If yes, create a MappedName from the part before the dot, and set the type to the
|
||||
// part after the dot
|
||||
// ii) If no, create a MappedName from the whole name
|
||||
// c) Try to get the elementType based on the MappedName. Return it if found
|
||||
// 3) Check to make sure the discovered type is in the list of types, and return its first
|
||||
// character if so.
|
||||
char ComplexGeoData::elementType(const char *name) const {
|
||||
if(!name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *type = nullptr;
|
||||
IndexedName element(name, getElementTypes());
|
||||
if (element) {
|
||||
type = element.getType();
|
||||
}
|
||||
else {
|
||||
const char * mapped = isMappedElement(name);
|
||||
if (mapped) {
|
||||
name = mapped;
|
||||
}
|
||||
|
||||
MappedName mappedName;
|
||||
const char *dot = strchr(name,'.');
|
||||
if(dot) {
|
||||
mappedName = MappedName(name, dot-name);
|
||||
type = dot+1;
|
||||
}
|
||||
else {
|
||||
mappedName = MappedName::fromRawData(name);
|
||||
}
|
||||
char res = elementType(mappedName);
|
||||
if (res != 0) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if(type && type[0]) {
|
||||
for(auto &elementTypes : getElementTypes()) {
|
||||
if(boost::starts_with(type, elementTypes)) {
|
||||
return type[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
|
||||
@@ -1,33 +1,40 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* Copyright (c) 2022 Zheng, Lei <realthunder.dev@gmail.com> *
|
||||
* Copyright (c) 2023 FreeCAD Project Association *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef _AppComplexGeoData_h_
|
||||
#define _AppComplexGeoData_h_
|
||||
#ifndef APP_COMPLEX_GEO_DATA_H
|
||||
#define APP_COMPLEX_GEO_DATA_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <Base/Handle.h>
|
||||
#include <Base/Matrix.h>
|
||||
#include <Base/Persistence.h>
|
||||
#include "MappedName.h"
|
||||
#include "MappedElement.h"
|
||||
#include "ElementMap.h"
|
||||
#include "StringHasher.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
# include <cstdint>
|
||||
@@ -38,20 +45,22 @@ namespace Base
|
||||
{
|
||||
class Placement;
|
||||
class Rotation;
|
||||
template <class _Precision> class BoundBox3;
|
||||
template <class _Precision> class BoundBox3;// NOLINT
|
||||
using BoundBox3d = BoundBox3<double>;
|
||||
}
|
||||
|
||||
namespace Data
|
||||
{
|
||||
|
||||
struct MappedChildElements;
|
||||
|
||||
/** Segments
|
||||
* Subelement type of the ComplexGeoData type
|
||||
* Sub-element type of the ComplexGeoData type
|
||||
* It is used to split an object in further sub-parts.
|
||||
*/
|
||||
class AppExport Segment: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT
|
||||
|
||||
public:
|
||||
~Segment() override = default;
|
||||
@@ -63,7 +72,7 @@ public:
|
||||
*/
|
||||
class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT
|
||||
|
||||
public:
|
||||
struct Line {uint32_t I1; uint32_t I2;};
|
||||
@@ -78,17 +87,17 @@ public:
|
||||
/// Destructor
|
||||
~ComplexGeoData() override;
|
||||
|
||||
/** @name Subelement management */
|
||||
/** @name Sub-element management */
|
||||
//@{
|
||||
/** Sub type list
|
||||
* List of different subelement types
|
||||
* its NOT a list of the subelements itself
|
||||
* List of different sub-element types
|
||||
* its NOT a list of the sub-elements itself
|
||||
*/
|
||||
virtual std::vector<const char*> getElementTypes() const=0;
|
||||
virtual unsigned long countSubElements(const char* Type) const=0;
|
||||
/// get the subelement by type and number
|
||||
/// get the sub-element by type and number
|
||||
virtual Segment* getSubElement(const char* Type, unsigned long) const=0;
|
||||
/// get subelement by combined name
|
||||
/// get sub-element by combined name
|
||||
virtual Segment* getSubElementByName(const char* Name) const;
|
||||
/** Get lines from segment */
|
||||
virtual void getLinesFromSubElement(
|
||||
@@ -164,6 +173,110 @@ public:
|
||||
virtual bool getCenterOfGravity(Base::Vector3d& center) const;
|
||||
//@}
|
||||
|
||||
|
||||
/** @name Element name mapping */
|
||||
//@{
|
||||
|
||||
/** Get element indexed name
|
||||
*
|
||||
* @param name: the input name
|
||||
* @param sid: optional output of and App::StringID involved forming this mapped name
|
||||
*
|
||||
* @return Returns an indexed name.
|
||||
*/
|
||||
IndexedName getIndexedName(const MappedName & name,
|
||||
ElementIDRefs *sid = nullptr) const;
|
||||
|
||||
/** Get element mapped name
|
||||
*
|
||||
* @param name: the input name
|
||||
* @param allowUnmapped: If the queried element is not mapped, then return
|
||||
* an empty name if \c allowUnmapped is false, or
|
||||
* else, return the indexed name.
|
||||
* @param sid: optional output of and App::StringID involved forming this mapped name
|
||||
* @return Returns the mapped name.
|
||||
*/
|
||||
MappedName getMappedName(const IndexedName & element,
|
||||
bool allowUnmapped = false,
|
||||
ElementIDRefs *sid = nullptr) const;
|
||||
|
||||
/** Return a pair of indexed name and mapped name
|
||||
*
|
||||
* @param name: the input name.
|
||||
* @param sid: optional output of any App::StringID involved in forming
|
||||
* this mapped name
|
||||
* @param copy: if true, copy the name string, or else use it as constant
|
||||
* string, and caller must make sure the memory is not freed.
|
||||
*
|
||||
* @return Returns the MappedElement which contains both the indexed and
|
||||
* mapped name.
|
||||
*
|
||||
* This function guesses whether the input name is an indexed name or
|
||||
* mapped, and perform a lookup and return the names found. If the input
|
||||
* name contains only alphabets and underscore followed by optional digits,
|
||||
* it will be treated as indexed name. Or else, it will be treated as
|
||||
* mapped name.
|
||||
*/
|
||||
MappedElement getElementName(const char * name,
|
||||
ElementIDRefs *sid = nullptr,
|
||||
bool copy = false) const;
|
||||
|
||||
/** Get mapped element names
|
||||
*
|
||||
* @param element: original element name with \c Type + \c Index
|
||||
* @param needUnmapped: if true, return the original element name if no
|
||||
* mapping is found
|
||||
*
|
||||
* @return a list of mapped names of the give element along with their
|
||||
* associated string ID references
|
||||
*/
|
||||
std::vector<std::pair<MappedName, ElementIDRefs> >
|
||||
getElementMappedNames(const IndexedName & element, bool needUnmapped=false) const;
|
||||
|
||||
/// Append the Tag (if and only if it is non zero) into the element map
|
||||
virtual void reTagElementMap(long tag,
|
||||
App::StringHasherRef hasher,
|
||||
const char *postfix=nullptr) {
|
||||
(void)tag;
|
||||
(void)hasher;
|
||||
(void)postfix;
|
||||
}
|
||||
|
||||
// NOTE: getElementHistory is now in ElementMap
|
||||
|
||||
char elementType(const Data::MappedName &) const;
|
||||
char elementType(const Data::IndexedName &) const;
|
||||
char elementType(const char *name) const;
|
||||
|
||||
/** Reset/swap the element map
|
||||
*
|
||||
* @param elementMap: optional new element map
|
||||
*
|
||||
* @return Returns the existing element map.
|
||||
*/
|
||||
virtual ElementMapPtr resetElementMap(ElementMapPtr elementMap=ElementMapPtr()) {
|
||||
_elementMap.swap(elementMap);
|
||||
return elementMap;
|
||||
}
|
||||
|
||||
/// Get the entire element map
|
||||
std::vector<MappedElement> getElementMap() const;
|
||||
|
||||
/// Set the entire element map
|
||||
void setElementMap(const std::vector<MappedElement> &elements);
|
||||
|
||||
/// Get the current element map size
|
||||
size_t getElementMapSize(bool flush=true) const;
|
||||
|
||||
/// Check if the given sub-name only contains an element name
|
||||
static bool isElementName(const char *subName) {
|
||||
return (subName != nullptr) && (*subName != 0) && findElementName(subName)==subName;
|
||||
}
|
||||
|
||||
/** Flush an internal buffering for element mapping */
|
||||
virtual void flushElementMap() const;
|
||||
//@}
|
||||
|
||||
protected:
|
||||
|
||||
/// from local to outside
|
||||
@@ -223,6 +336,37 @@ protected:
|
||||
}
|
||||
public:
|
||||
mutable long Tag;
|
||||
|
||||
|
||||
public:
|
||||
/// String hasher for element name shortening
|
||||
mutable App::StringHasherRef Hasher;
|
||||
|
||||
protected:
|
||||
|
||||
/// from local to outside
|
||||
inline Base::Vector3d transformToOutside(const Base::Vector3f& vec) const
|
||||
{
|
||||
return getTransform() * Base::Vector3d(static_cast<double>(vec.x),
|
||||
static_cast<double>(vec.y),
|
||||
static_cast<double>(vec.z));
|
||||
}
|
||||
/// from local to inside
|
||||
inline Base::Vector3f transformToInside(const Base::Vector3d& vec) const
|
||||
{
|
||||
Base::Matrix4D tmpM(getTransform());
|
||||
tmpM.inverse();
|
||||
Base::Vector3d tmp = tmpM * vec;
|
||||
return Base::Vector3f(static_cast<float>(tmp.x),
|
||||
static_cast<float>(tmp.y),
|
||||
static_cast<float>(tmp.z));
|
||||
}
|
||||
|
||||
protected:
|
||||
ElementMapPtr elementMap(bool flush=true) const;
|
||||
|
||||
private:
|
||||
ElementMapPtr _elementMap;
|
||||
};
|
||||
|
||||
} //namespace App
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -63,27 +63,27 @@ public:
|
||||
ElementMap();
|
||||
|
||||
/** Ensures that naming is properly assigned. It then marks as "used" all the StringID
|
||||
* that are used to make up this particular map and are stored in the hasher passed
|
||||
* that are used to make up this particular map and are stored in the hasherRef passed
|
||||
* as a parameter. Finally do this recursively for all childEelementMaps as well.
|
||||
*
|
||||
* @param hasher where all the StringID needed to build the map are stored.
|
||||
* @param hasherRef where all the StringID needed to build the map are stored.
|
||||
*/
|
||||
// FIXME this should be made part of \c save, to achieve symmetry with the restore method
|
||||
void beforeSave(const ::App::StringHasherRef& hasher) const;
|
||||
void beforeSave(const ::App::StringHasherRef& hasherRef) const;
|
||||
|
||||
/** Serialize this map. Calls \c collectChildMaps to get \c childMapSet and
|
||||
* \c postfixMap, then calls the other (private) save function with those parameters.
|
||||
* @param s: serialized stream
|
||||
* @param stream: serialized stream
|
||||
*/
|
||||
void save(std::ostream& s) const;
|
||||
void save(std::ostream& stream) const;
|
||||
|
||||
/** Deserialize and restore this map. This function restores \c childMaps and
|
||||
/** Deserialize and restore this map. This function restores \c childMaps and
|
||||
* \c postfixes from the stream, then calls the other (private) restore function with those
|
||||
* parameters.
|
||||
* @param hasher: where all the StringIDs are stored
|
||||
* @param s: stream to deserialize
|
||||
* @param hasherRef: where all the StringIDs are stored
|
||||
* @param stream: stream to deserialize
|
||||
*/
|
||||
ElementMapPtr restore(::App::StringHasherRef hasher, std::istream& s);
|
||||
ElementMapPtr restore(::App::StringHasherRef hasherRef, std::istream& stream);
|
||||
|
||||
|
||||
/** Add a sub-element name mapping.
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
QByteArray postfix;
|
||||
ElementIDRefs sids;
|
||||
|
||||
// prefix() has been moved to PostfixStringReferences.h
|
||||
// prefix() has been moved to ElementNamingUtils.h
|
||||
};
|
||||
|
||||
/* Note: the original addChildElements passed `ComplexGeoData& master` for getting the `Tag`,
|
||||
@@ -181,22 +181,26 @@ public:
|
||||
|
||||
std::vector<MappedElement> getAll() const;
|
||||
|
||||
long getElementHistory(const MappedName & name,
|
||||
long masterTag,
|
||||
MappedName *original=0, std::vector<MappedName> *history=0) const;
|
||||
|
||||
private:
|
||||
/** Serialize this map
|
||||
* @param s: serialized stream
|
||||
* @param stream: serialized stream
|
||||
* @param childMapSet: where all child element maps are stored
|
||||
* @param postfixMap. where all postfixes are stored
|
||||
*/
|
||||
void save(std::ostream& s, int index, const std::map<const ElementMap*, int>& childMapSet,
|
||||
void save(std::ostream& stream, int index, const std::map<const ElementMap*, int>& childMapSet,
|
||||
const std::map<QByteArray, int>& postfixMap) const;
|
||||
|
||||
/** Deserialize and restore this map.
|
||||
* @param hasher: where all the StringIDs are stored
|
||||
* @param s: stream to deserialize
|
||||
* @param hasherRef: where all the StringIDs are stored
|
||||
* @param stream: stream to deserialize
|
||||
* @param childMaps: where all child element maps are stored
|
||||
* @param postfixes. where all postfixes are stored
|
||||
*/
|
||||
ElementMapPtr restore(::App::StringHasherRef hasher, std::istream& s,
|
||||
ElementMapPtr restore(::App::StringHasherRef hasherRef, std::istream& stream,
|
||||
std::vector<ElementMapPtr>& childMaps,
|
||||
const std::vector<std::string>& postfixes);
|
||||
|
||||
@@ -220,9 +224,9 @@ private:
|
||||
|
||||
/* Note: the original proc passed `ComplexGeoData& master` for getting the `Tag`,
|
||||
* now it just passes `long masterTag`.*/
|
||||
virtual MappedName renameDuplicateElement(int index, const IndexedName& element,
|
||||
const IndexedName& element2, const MappedName& name,
|
||||
ElementIDRefs& sids, long masterTag);
|
||||
MappedName renameDuplicateElement(int index, const IndexedName& element,
|
||||
const IndexedName& element2, const MappedName& name,
|
||||
ElementIDRefs& sids, long masterTag) const;
|
||||
|
||||
/** Convenience method to hash the main element name
|
||||
*
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#ifndef APP_MAPPED_ELEMENT_H
|
||||
#define APP_MAPPED_ELEMENT_H
|
||||
|
||||
#include "ComplexGeoData.h"
|
||||
#include "IndexedName.h"
|
||||
#include "MappedName.h"
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#ifndef APP_MAPPED_NAME_H
|
||||
#define APP_MAPPED_NAME_H
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -34,11 +33,11 @@
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
#include <QVector>
|
||||
#include <utility>
|
||||
|
||||
#include "ComplexGeoData.h"
|
||||
#include "ElementNamingUtils.h"
|
||||
#include "IndexedName.h"
|
||||
#include "StringHasher.h"
|
||||
#include "ElementNamingUtils.h"
|
||||
|
||||
|
||||
namespace Data
|
||||
@@ -93,8 +92,9 @@ public:
|
||||
/// is appended as text to the MappedName. In that case the memory is *not* shared between the
|
||||
/// original IndexedName and the MappedName.
|
||||
explicit MappedName(const IndexedName& element)
|
||||
: data(QByteArray::fromRawData(element.getType(), qstrlen(element.getType()))),
|
||||
raw(true)
|
||||
: data(QByteArray::fromRawData(element.getType(),
|
||||
static_cast<int>(qstrlen(element.getType()))))
|
||||
, raw(true)
|
||||
{
|
||||
if (element.getIndex() > 0) {
|
||||
this->data += QByteArray::number(element.getIndex());
|
||||
@@ -102,6 +102,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
explicit MappedName(const App::StringIDRef& sid)
|
||||
: raw(false)
|
||||
{
|
||||
sid.toBytes(this->data);
|
||||
}
|
||||
|
||||
MappedName()
|
||||
: raw(false)
|
||||
{}
|
||||
@@ -125,16 +131,16 @@ public:
|
||||
/// \param other The mapped name to copy. Its data and postfix become the new MappedName's data
|
||||
/// \param postfix The postfix for the new MappedName
|
||||
MappedName(const MappedName& other, const char* postfix)
|
||||
: data(other.data + other.postfix),
|
||||
postfix(postfix),
|
||||
raw(false)
|
||||
: data(other.data + other.postfix)
|
||||
, postfix(postfix)
|
||||
, raw(false)
|
||||
{}
|
||||
|
||||
/// Move constructor
|
||||
MappedName(MappedName&& other) noexcept
|
||||
: data(std::move(other.data)),
|
||||
postfix(std::move(other.postfix)),
|
||||
raw(other.raw)
|
||||
: data(std::move(other.data))
|
||||
, postfix(std::move(other.postfix))
|
||||
, raw(other.raw)
|
||||
{}
|
||||
|
||||
~MappedName() = default;
|
||||
@@ -894,7 +900,7 @@ public:
|
||||
///
|
||||
/// \param tag: optional pointer to receive the extracted tag
|
||||
/// \param len: optional pointer to receive the length field after the tag field.
|
||||
/// This gives the length of the previous hashsed element name starting
|
||||
/// This gives the length of the previous hashed element name starting
|
||||
/// from the beginning of the give element name.
|
||||
/// \param postfix: optional pointer to receive the postfix starting at the found tag field.
|
||||
/// \param type: optional pointer to receive the element type character
|
||||
@@ -903,8 +909,9 @@ public:
|
||||
/// \param recursive: recursively find the last non-zero tag
|
||||
///
|
||||
/// \return Return the end position of the tag field, or return -1 if not found.
|
||||
int findTagInElementName(long* tag = 0, int* len = 0, const char* postfix = 0, char* type = 0,
|
||||
bool negative = false, bool recursive = true) const;
|
||||
int findTagInElementName(long* tag = nullptr, int* len = nullptr, const char* postfix = nullptr,
|
||||
char* type = nullptr, bool negative = false,
|
||||
bool recursive = true) const;
|
||||
|
||||
/// Get a hash for this MappedName
|
||||
std::size_t hash() const
|
||||
@@ -919,7 +926,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
typedef QVector<::App::StringIDRef> ElementIDRefs;
|
||||
using ElementIDRefs = QVector<::App::StringIDRef>;
|
||||
|
||||
struct MappedNameRef
|
||||
{
|
||||
@@ -929,25 +936,34 @@ struct MappedNameRef
|
||||
|
||||
MappedNameRef() = default;
|
||||
|
||||
MappedNameRef(const MappedName& name, const ElementIDRefs& sids = ElementIDRefs())
|
||||
: name(name),
|
||||
sids(sids)
|
||||
~MappedNameRef() = default;
|
||||
|
||||
MappedNameRef(MappedName name, ElementIDRefs sids = ElementIDRefs())
|
||||
: name(std::move(name))
|
||||
, sids(std::move(sids))
|
||||
{
|
||||
compact();
|
||||
}
|
||||
|
||||
MappedNameRef(const MappedNameRef& other)
|
||||
: name(other.name),
|
||||
sids(other.sids)
|
||||
: name(other.name)
|
||||
, sids(other.sids)
|
||||
{}
|
||||
|
||||
MappedNameRef(MappedNameRef&& other)
|
||||
: name(std::move(other.name)),
|
||||
sids(std::move(other.sids)),
|
||||
next(std::move(other.next))
|
||||
MappedNameRef(MappedNameRef&& other) noexcept
|
||||
: name(std::move(other.name))
|
||||
, sids(std::move(other.sids))
|
||||
, next(std::move(other.next))
|
||||
{}
|
||||
|
||||
MappedNameRef& operator=(MappedNameRef&& other)
|
||||
MappedNameRef& operator=(const MappedNameRef& other) noexcept
|
||||
{
|
||||
name = other.name;
|
||||
sids = other.sids;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MappedNameRef& operator=(MappedNameRef&& other) noexcept
|
||||
{
|
||||
name = std::move(other.name);
|
||||
sids = std::move(other.sids);
|
||||
@@ -960,22 +976,24 @@ struct MappedNameRef
|
||||
return !name.empty();
|
||||
}
|
||||
|
||||
void append(const MappedName& name, const ElementIDRefs sids = ElementIDRefs())
|
||||
void append(const MappedName& _name, const ElementIDRefs _sids = ElementIDRefs())
|
||||
{
|
||||
if (!name)
|
||||
if (!_name) {
|
||||
return;
|
||||
}
|
||||
if (!this->name) {
|
||||
this->name = name;
|
||||
this->sids = sids;
|
||||
this->name = _name;
|
||||
this->sids = _sids;
|
||||
compact();
|
||||
return;
|
||||
}
|
||||
std::unique_ptr<MappedNameRef> n(new MappedNameRef(name, sids));
|
||||
if (!this->next)
|
||||
this->next = std::move(n);
|
||||
std::unique_ptr<MappedNameRef> mappedName(new MappedNameRef(_name, _sids));
|
||||
if (!this->next) {
|
||||
this->next = std::move(mappedName);
|
||||
}
|
||||
else {
|
||||
this->next.swap(n);
|
||||
this->next->next = std::move(n);
|
||||
this->next.swap(mappedName);
|
||||
this->next->next = std::move(mappedName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,9 +1005,9 @@ struct MappedNameRef
|
||||
}
|
||||
}
|
||||
|
||||
bool erase(const MappedName& name)
|
||||
bool erase(const MappedName& _name)
|
||||
{
|
||||
if (this->name == name) {
|
||||
if (this->name == _name) {
|
||||
this->name.clear();
|
||||
this->sids.clear();
|
||||
if (this->next) {
|
||||
@@ -1002,11 +1020,11 @@ struct MappedNameRef
|
||||
return true;
|
||||
}
|
||||
|
||||
for (std::unique_ptr<MappedNameRef>* p = &this->next; *p; p = &(*p)->next) {
|
||||
if ((*p)->name == name) {
|
||||
for (std::unique_ptr<MappedNameRef>* ptr = &this->next; *ptr; ptr = &(*ptr)->next) {
|
||||
if ((*ptr)->name == _name) {
|
||||
std::unique_ptr<MappedNameRef> tmp;
|
||||
tmp.swap(*p);
|
||||
*p = std::move(tmp->next);
|
||||
tmp.swap(*ptr);
|
||||
*ptr = std::move(tmp->next);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1028,4 +1046,4 @@ struct MappedNameRef
|
||||
}// namespace Data
|
||||
|
||||
|
||||
#endif// APP_MAPPED_NAME_H
|
||||
#endif// APP_MAPPED_NAME_H
|
||||
|
||||
@@ -173,7 +173,7 @@ public:
|
||||
}
|
||||
|
||||
/// Returns the data (prefix)
|
||||
QByteArray data() const
|
||||
const QByteArray& data() const
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
@@ -556,6 +556,7 @@ public:
|
||||
|
||||
void toBytes(QByteArray& bytes) const
|
||||
{
|
||||
// TODO: return the QByteArray instead of passing in by reference
|
||||
if (_sid) {
|
||||
bytes = _sid->dataToBytes(_index);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#ifdef _PreComp_
|
||||
|
||||
#ifdef FC_OS_WIN32
|
||||
# undef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ target_sources(
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Application.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Branding.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ComplexGeoData.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Expression.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ElementMap.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/IndexedName.cpp
|
||||
|
||||
417
tests/src/App/ComplexGeoData.cpp
Normal file
417
tests/src/App/ComplexGeoData.cpp
Normal file
@@ -0,0 +1,417 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <array>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/ComplexGeoData.h>
|
||||
#include <Base/BoundBox.h>
|
||||
|
||||
|
||||
class ConcreteComplexGeoDataForTesting: public Data::ComplexGeoData
|
||||
{
|
||||
public:
|
||||
std::vector<const char*> getElementTypes() const override
|
||||
{
|
||||
return {"EDGE"};
|
||||
}
|
||||
|
||||
unsigned long countSubElements(const char* Type) const override
|
||||
{
|
||||
(void)Type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Data::Segment* getSubElement(const char* Type, unsigned long number) const override
|
||||
{
|
||||
(void)number;
|
||||
(void)Type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned int getMemSize() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Save(Base::Writer& writer) const override
|
||||
{
|
||||
(void)writer;
|
||||
}
|
||||
|
||||
void Restore(Base::XMLReader& reader) override
|
||||
{
|
||||
(void)reader;
|
||||
}
|
||||
|
||||
void setTransform(const Base::Matrix4D& rclTrf) override
|
||||
{
|
||||
(void)rclTrf;
|
||||
}
|
||||
|
||||
Base::Matrix4D getTransform() const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void transformGeometry(const Base::Matrix4D& rclMat) override
|
||||
{
|
||||
(void)rclMat;
|
||||
}
|
||||
|
||||
Base::BoundBox3d getBoundBox() const override
|
||||
{
|
||||
return Base::BoundBox3d();
|
||||
}
|
||||
};
|
||||
|
||||
class ComplexGeoDataTest: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
if (App::Application::GetARGC() == 0) {
|
||||
constexpr int argc = 1;
|
||||
std::array<char*, argc> argv {"FreeCAD"};
|
||||
App::Application::Config()["ExeName"] = "FreeCAD";
|
||||
App::Application::init(argc, argv.data());
|
||||
}
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
_docName = App::GetApplication().getUniqueDocumentName("test");
|
||||
App::GetApplication().newDocument(_docName.c_str(), "testUser");
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
App::GetApplication().closeDocument(_docName.c_str());
|
||||
}
|
||||
|
||||
ConcreteComplexGeoDataForTesting& cgd()
|
||||
{
|
||||
return _complexGeoData;
|
||||
}
|
||||
|
||||
std::tuple<Data::IndexedName, Data::MappedName> createMappedName(const std::string& name)
|
||||
{
|
||||
auto elementMap = std::make_shared<Data::ElementMap>();
|
||||
cgd().resetElementMap(elementMap);
|
||||
auto mappedName = Data::MappedName(name.c_str());
|
||||
auto indexedName = Data::IndexedName(_complexGeoData.getElementTypes().front(), 1);
|
||||
elementMap->setElementName(indexedName, mappedName, 0);
|
||||
return std::make_tuple(indexedName, mappedName);
|
||||
}
|
||||
|
||||
private:
|
||||
ConcreteComplexGeoDataForTesting _complexGeoData;
|
||||
std::string _docName;
|
||||
};
|
||||
|
||||
// NOLINTBEGIN(readability-magic-numbers)
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getIndexedNameNoName)// NOLINT
|
||||
{
|
||||
// Arrange & Act
|
||||
auto result = cgd().getIndexedName(Data::MappedName());
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getIndexedNameNoElementMap)// NOLINT
|
||||
{
|
||||
// Arrange & Act
|
||||
auto result = cgd().getIndexedName(Data::MappedName("TestName"));
|
||||
|
||||
// Assert
|
||||
EXPECT_TRUE(result);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getMappedNameNoElement)// NOLINT
|
||||
{
|
||||
// Arrange & Act
|
||||
auto result = cgd().getMappedName(Data::IndexedName {});
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getMappedNameDisallowUnmappedNoMap)// NOLINT
|
||||
{
|
||||
// Arrange & Act
|
||||
auto result = cgd().getMappedName(Data::IndexedName {"TestName"}, false);
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getMappedNameDisallowUnmappedWithMap)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
auto elementMap = std::make_shared<Data::ElementMap>();
|
||||
cgd().resetElementMap(elementMap);
|
||||
auto mappedName = Data::MappedName("TestMappedName");
|
||||
auto indexedName = Data::IndexedName("EDGE", 1);
|
||||
elementMap->setElementName(indexedName, mappedName, 0);
|
||||
|
||||
// Act
|
||||
auto result = cgd().getMappedName(indexedName, false);
|
||||
|
||||
// Assert
|
||||
EXPECT_TRUE(result);
|
||||
EXPECT_EQ(mappedName, result);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getMappedNameDisallowUnmappedMissingFromMap)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
auto mappedName = Data::MappedName("NotTheTestName");
|
||||
cgd().getIndexedName(mappedName);// Put it in the map
|
||||
|
||||
// Act
|
||||
auto result = cgd().getMappedName(Data::IndexedName {"TestName"}, false);
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getMappedNameAllowUnmapped)// NOLINT
|
||||
{
|
||||
// Arrange & Act
|
||||
auto result = cgd().getMappedName(Data::IndexedName {"TestName"}, true);
|
||||
|
||||
// Assert
|
||||
EXPECT_TRUE(result);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getElementNameGivenIndexedName)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
const char* name {"EDGE123"};
|
||||
auto indexedName = cgd().getIndexedName(Data::MappedName(name));
|
||||
|
||||
// Act
|
||||
auto result = cgd().getElementName(name);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result.index, indexedName);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getElementNameGivenMappedName)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
const char* name {"EDGE123"};
|
||||
auto mappedName = cgd().getMappedName(Data::IndexedName(name));
|
||||
|
||||
// Act
|
||||
auto result = cgd().getElementName(name);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result.name, mappedName);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getElementMappedNamesNoMapNoUnmapped)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
// Do not create an element map
|
||||
auto indexedName = Data::IndexedName("EDGE1");
|
||||
|
||||
// Act
|
||||
auto result = cgd().getElementMappedNames(indexedName, false);
|
||||
|
||||
// Assert
|
||||
EXPECT_TRUE(result.empty());
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getElementMappedNamesWithMapNoUnmapped)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
auto elementMap = std::make_shared<Data::ElementMap>();
|
||||
cgd().resetElementMap(elementMap);
|
||||
auto mappedName = Data::MappedName("TestMappedName");
|
||||
auto indexedName = Data::IndexedName("EDGE", 1);
|
||||
elementMap->setElementName(indexedName, mappedName, 0);
|
||||
|
||||
// Act
|
||||
auto result = cgd().getElementMappedNames(indexedName, false);
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(result.empty());
|
||||
EXPECT_EQ(result[0].first, mappedName);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getElementMappedNamesNoMapWithUnmapped)// NOLINT
|
||||
{
|
||||
// Do not create an element map
|
||||
auto indexedName = Data::IndexedName("EDGE1");
|
||||
|
||||
// Act
|
||||
auto result = cgd().getElementMappedNames(indexedName, true);
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(result.empty());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getElementMappedNamesWithMapWithUnmapped)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
Data::MappedName mappedName;
|
||||
Data::IndexedName indexedName;
|
||||
std::tie(indexedName, mappedName) = createMappedName("TestMappedName");
|
||||
auto unmappedName = Data::IndexedName("EDGE", 2);
|
||||
|
||||
// Act
|
||||
auto result = cgd().getElementMappedNames(unmappedName, true);
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(result.empty());
|
||||
EXPECT_NE(result[0].first, mappedName);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, elementTypeValidIndexName)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
auto indexedName = Data::IndexedName("EDGE", 1);
|
||||
|
||||
// Act
|
||||
char elementType = cgd().elementType(indexedName);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(elementType, 'E');
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, elementTypeInvalidIndexedName)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
auto indexedName = Data::IndexedName("INVALID", 1);// Not in the element type list
|
||||
|
||||
// Act
|
||||
char elementType = cgd().elementType(indexedName);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(elementType, 0);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, elementTypeCharEmptyName)// NOLINT
|
||||
{
|
||||
// Arrange & Act
|
||||
char elementType = cgd().elementType(nullptr);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(elementType, 0);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, elementTypeCharIndexedName)// NOLINT
|
||||
{
|
||||
// Arrange & Act
|
||||
char elementType = cgd().elementType("EDGE1");
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(elementType, 'E');
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, elementTypeCharMappedNameNoPrefix)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
int size {0};
|
||||
Data::MappedName mappedName;
|
||||
Data::IndexedName indexedName;
|
||||
std::tie(indexedName, mappedName) = createMappedName("TestMappedName:;");
|
||||
|
||||
// Act
|
||||
char elementType = cgd().elementType(mappedName.toConstString(0, size));
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(elementType, 'E');
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, elementTypeCharMappedNameWithPrefix)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
int size {0};
|
||||
Data::MappedName mappedName;
|
||||
Data::IndexedName indexedName;
|
||||
auto name = fmt::format("{}TestMappedElement:;", Data::ELEMENT_MAP_PREFIX);
|
||||
std::tie(indexedName, mappedName) = createMappedName(name);
|
||||
|
||||
// Act
|
||||
char elementType = cgd().elementType(mappedName.toConstString(0, size));
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(elementType, 'E');
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, resetElementMapNoArgument)// NOLINT
|
||||
{
|
||||
// Arrange & Act
|
||||
cgd().resetElementMap();
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(cgd().getElementMapSize(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, resetElementMapWithArgument)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
auto elementMap = std::make_shared<Data::ElementMap>();
|
||||
auto mappedName = Data::MappedName("TestMappedName");
|
||||
auto indexedName = Data::IndexedName("EDGE", 1);
|
||||
elementMap->setElementName(indexedName, mappedName, 0);
|
||||
|
||||
// Act
|
||||
cgd().resetElementMap(elementMap);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(cgd().getElementMapSize(), 1);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, setAndGetElementMap)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
auto elementMap = std::make_shared<Data::ElementMap>();
|
||||
cgd().resetElementMap(elementMap);
|
||||
std::vector<Data::MappedElement> vecMappedElements;
|
||||
auto mappedNameA = Data::MappedName("TestMappedNameA");
|
||||
auto indexedNameA = Data::IndexedName("EDGE", 1);
|
||||
vecMappedElements.emplace_back(indexedNameA, mappedNameA);
|
||||
auto mappedNameB = Data::MappedName("TestMappedNameB");
|
||||
auto indexedNameB = Data::IndexedName("EDGE", 2);
|
||||
vecMappedElements.emplace_back(indexedNameB, mappedNameB);
|
||||
|
||||
// Act
|
||||
auto emptyElementMap = cgd().getElementMap();
|
||||
cgd().setElementMap(vecMappedElements);
|
||||
auto resultingElementMap = cgd().getElementMap();
|
||||
|
||||
// Assert
|
||||
EXPECT_TRUE(emptyElementMap.empty());
|
||||
EXPECT_EQ(resultingElementMap.size(), vecMappedElements.size());
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, getElementMapSize)// NOLINT
|
||||
{
|
||||
// Arrange
|
||||
auto elementMap = std::make_shared<Data::ElementMap>();
|
||||
auto mappedName = Data::MappedName("TestMappedName");
|
||||
auto indexedName = Data::IndexedName("EDGE", 1);
|
||||
elementMap->setElementName(indexedName, mappedName, 0);
|
||||
cgd().resetElementMap(elementMap);
|
||||
|
||||
// Act
|
||||
auto result = cgd().getElementMapSize();
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, 1);
|
||||
}
|
||||
|
||||
TEST_F(ComplexGeoDataTest, flushElementMap)// NOLINT
|
||||
{
|
||||
// Does nothing in the base class
|
||||
}
|
||||
|
||||
// NOLINTEND(readability-magic-numbers)
|
||||
@@ -45,21 +45,29 @@ class ElementMapTest: public ::testing::Test
|
||||
protected:
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
int argc = 1;
|
||||
char* argv[] = {"FreeCAD"};
|
||||
App::Application::Config()["ExeName"] = "FreeCAD";
|
||||
App::Application::init(argc, argv);
|
||||
if (App::Application::GetARGC() == 0) {
|
||||
int argc = 1;
|
||||
char* argv[] = {"FreeCAD"};
|
||||
App::Application::Config()["ExeName"] = "FreeCAD";
|
||||
App::Application::init(argc, argv);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
App::GetApplication().newDocument("test", "testUser");
|
||||
_docName = App::GetApplication().getUniqueDocumentName("test");
|
||||
App::GetApplication().newDocument(_docName.c_str(), "testUser");
|
||||
_sids = &_sid;
|
||||
_hasher = Base::Reference<App::StringHasher>(new App::StringHasher);
|
||||
ASSERT_EQ(_hasher.getRefCount(), 1);
|
||||
}
|
||||
|
||||
// void TearDown() override {}
|
||||
void TearDown() override
|
||||
{
|
||||
App::GetApplication().closeDocument(_docName.c_str());
|
||||
}
|
||||
|
||||
std::string _docName;
|
||||
Data::ElementIDRefs _sid;
|
||||
QVector<App::StringIDRef>* _sids;
|
||||
App::StringHasherRef _hasher;
|
||||
|
||||
@@ -225,8 +225,11 @@ TEST(MappedName, fromRawData)
|
||||
|
||||
TEST(MappedName, fromRawDataQByteArray)
|
||||
{
|
||||
// Arrange
|
||||
QByteArray testByteArray("TESTTEST", 10);
|
||||
|
||||
// Act
|
||||
Data::MappedName mappedName = Data::MappedName::fromRawData(QByteArray("TESTTEST", 10));
|
||||
Data::MappedName mappedName = Data::MappedName::fromRawData(testByteArray);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(mappedName.isRaw(), true);
|
||||
@@ -239,7 +242,8 @@ TEST(MappedName, fromRawDataQByteArray)
|
||||
TEST(MappedName, fromRawDataCopy)
|
||||
{
|
||||
// Arrange
|
||||
Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TESTTEST", 10));
|
||||
QByteArray testByteArray("TESTTEST", 10);
|
||||
Data::MappedName temp = Data::MappedName::fromRawData(testByteArray);
|
||||
temp.append("TESTPOSTFIX");
|
||||
temp.compact();// Always call compact before accessing data!
|
||||
|
||||
@@ -257,7 +261,8 @@ TEST(MappedName, fromRawDataCopy)
|
||||
TEST(MappedName, fromRawDataCopyStartposAndSize)
|
||||
{
|
||||
// Arrange
|
||||
Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TESTTEST", 8));
|
||||
QByteArray testByteArray("TESTTEST", 8);
|
||||
Data::MappedName temp = Data::MappedName::fromRawData(testByteArray);
|
||||
temp.append("ABCDEFGHIJKLM");// postfix
|
||||
temp.compact(); // Always call compact before accessing data!
|
||||
|
||||
@@ -373,11 +378,12 @@ TEST(MappedName, additionOperators)
|
||||
{
|
||||
// Arrange
|
||||
Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST");
|
||||
QByteArray post3("POST3");
|
||||
|
||||
// Act
|
||||
mappedName += "POST1";
|
||||
mappedName += std::string("POST2");
|
||||
mappedName += QByteArray("POST3");
|
||||
mappedName += post3;
|
||||
mappedName += Data::MappedName("POST4");
|
||||
|
||||
// Assert
|
||||
@@ -389,12 +395,13 @@ TEST(MappedName, additionOperators)
|
||||
|
||||
// Arrange
|
||||
mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST");
|
||||
QByteArray post8("POST8");
|
||||
|
||||
// Act
|
||||
mappedName = mappedName + Data::MappedName("POST5");
|
||||
mappedName = mappedName + "POST6";
|
||||
mappedName = mappedName + std::string("POST7");
|
||||
mappedName = mappedName + QByteArray("POST8");
|
||||
mappedName = mappedName + post8;
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(mappedName.isRaw(), false);
|
||||
|
||||
Reference in New Issue
Block a user