OCCT基础
基础
构成总览
- Root类
- 基本类型,如布尔,字符,整数或实数
- 安全处理动态创建的对象,确保自动删除未引用的对象
- 可配置的内存管理器,提高了应用程序的性能
- 包含运行时类型信息机制,有助于创建复杂应用
- 异常管理
- 一些C++的流
- 集合类
- 字符串
- 集合
- 向量和矩阵
- 向量矩阵的基本计算
- 基础几何类
- 基础几何(点,圆等)
- 基础几何动作(缩放等)
- 常用的数学工具
- 求解一组线性代数方程的算法
- 找到一个或多个自变量函数最小值的算法
- 找到一个或一组非线性方程的根的算法
- 找到方阵的特征值和特征向量的算法
- 原子类
- 应用服务
- 单位转换工具,提供处理数量和相关物理单位的统一机制,详情UnitsAPI
- 表达式的基本解释器,用于脚本创建等等。详情ExprIntrp
- 用于处理配置资源文件和可自定义消息文件的工具。详情
- 进度指示和用户中断接口
库的组织方法
模块和工具
整个OCCT库由一组模块组成。Root模块提供了基础的服务并被其他模块所使用。
每个模块主要由一个或多个工具包组成。在计算机中,工具包由共享库(例如.so或.dll)表示。
包
一个包由语义上由联系的类组织在一起。例如:几何包包括点,线,圆等。包的命名规范,通常情况下包的命名为:包名_类名。例如:集合包下的圆的名字就是:Geom_Circle。包中的内容可以包括的数据类型:
- 枚举
- 对象类
- 异常
- 指向其他对象类的指针在包中
数据类型
对象是数据类型的实例,其定义决定了如何使用它。每种数据类型由一个或多个类实现,这些类构成系统的基本元素。
Open CASCADE技术中的数据类型分为两类:
- 由值操作的数据类型
- 由句柄操作的数据类型
由值操作的数据类型
由值操纵的类型的变量包含实例本身。
有三种类型:
- 基础类型
- 枚举类型
- 不是直接从Standard_Transient继承的类定义的类型。
由句柄操作的数据类型
由句柄操纵的类型的变量包含对实例的引用。
注意
由句柄操作的类型默认是NULL。因此我们需要使用
Handle(MyClass) m=new MyClass;
来进行赋初值。
类型:
由继承自Transient类的类
什么时候需要句柄类型的数据?
- 如果对象的生命周期比较长,那么就使用句柄类型的。
- 如果对象的生命周期短,那么就是用值类型的。
- 如果一个对象只在一段时间内创建,但在整个应用程序的生命周期中都存在,那么最好的选择可能是由句柄操作的类或声明为全局变量的值。
使用句柄的编程方法
句柄的定义
句柄是在OCCT中的智能指针。几个句柄可以同时使用一个对象,单个句柄可以引用多个对象,但一次只能引用一个对象。如果需要引用其他对象,必须像使用C ++指针一样取消引用句柄。
类的组织
类Standard_Transient是OCCT类大的基类,可以被句柄操作。
从Transient派生(直接或间接)的类的对象通常使用new在动态内存中分配,并由句柄操作。句柄的定义使用模板类opencascade :: handle <>
Handle(Geom_Line) aLine; // "Handle(Geom_Line)" 扩展于 "opencascade::handleL<Geom_Line>"
在OCCT中,为句柄定义了附加的typedef,直接在相关的句柄中添加Handle_
即可:
Handle_Geom_Line aLine; //“Handle_Geom_Line”的本质是使用typedef重定义了“opencascade :: handleL <Geom_Line>”
使用句柄:
句柄的特征在于它引用的对象。
声明句柄:
Handle(Geom_Point) p1, p2;
声明句柄会创建一个不引用任何对象的空句柄。可以通过其方法IsNull()检查句柄为空。要使句柄无效,可以使用Nullify()方法。
初始化句柄:
可以创建一个新对象,或者可以为其分配另一个句柄的值,但是它们的类型必须是兼容的。
- 内联值可以一行代码解决
#include <Geom_Surface.hxx>
class Appli_ExtSurface : public Geom_Surface
{
. . .
public:
DEFINE_STANDARD_RTTIEXT(Appli_ExtSurface,Geom_Surface)
};
- 外联使用宏的方式
#include <Appli_ExtSurface.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Appli_ExtSurface,Geom_Surface)
类型管理:
Open CASCADE技术提供了一种以通用方式描述数据类型层次结构的方法,可以在运行时检查给定对象的确切类型(类似于C ++ RTTI)。
如果需要使用这个功能,类声明应包括OCCT RTTI的声明。
多态:
Handle (Geom_Point) p1;
Handle (Geom_CartesianPoint) p2;
p2 = new Geom_CartesianPoint;
p1 = p2; // 这样是Ok的
显式类型转换:
强制类型转换
Handle (Geom_Point) p1;
Handle (Geom_CartesianPoint) p2, p3;
p2 = new Geom_CartesianPoint;
p1 = p2; // OK, standard assignment
p3 = Handle (Geom_CartesianPoint)::DownCast (p1);
如果转换与引用对象的实际类型不兼容,则“强制转换”的句柄变为空(并且不会引发异常)。稳健的做法如下:
void MyFunction (const Handle(A) & a)
{
Handle(B) b = Handle(B)::DownCast(a);
if (! b.IsNull()) {
//我们可以使用b,如果b是A的子类
}
else {
//
}
}
向下转换特别适用于不同类型的对象集合; 但是,这些对象应该从相同的根类继承。
例:
Handle (A) a;
Handle (B) b;
Handle (Standard_Transient) t;
SequenceOfTransient s;
a = new A;
s.Append (a);
b = new B;
s.Append (b);
t = s.Value (1);
// here, you cannot write:
// a = t; // ERROR !
// so you downcast:
a = Handle (A)::Downcast (t); //
if (! a.IsNull()) {
// types are compatible, you can use a
}
else {
// the types are incompatible
}
使用句柄创建对象
要创建一个由句柄操作的对象,请声明句柄并使用标准C ++ new运算符对其进行初始化,然后立即调用构造函数。构造函数可以是实例化对象的类源中指定的任何构造函数。
Handle (Geom_CartesianPoint) p;
p = new Geom_CartesianPoint (0, 0, 0);
注意:
与指针不同,删除操作符不适用于句柄; 引用的对象在不再使用时会自动销毁。
调用方法类
方法类近似于C++中的静态函数。使用类名::方法名的方式的形式调用
例如:
Standard_Integer n;
n = Geom_BezierCurve :: MaxDegree();
释放与处理
删除对象之前,必须确保不再引用该对象。为了减少与此对象生命管理相关的编程负载,Open CASCADE技术中的删除功能由handle操作的类的引用计数器保护。句柄在不再引用时自动删除对象。通常,用户不需要在Standard_Transient的子类实例上显式调用delete运算符。
创建同一对象的新句柄时,引用计数器会递增。当句柄被销毁,无效或重新分配给另一个对象时,该计数器会递减。当引用计数器变为0时,句柄会自动删除该对象。
分配原理的例子:
...
{
Handle (TColStd_HSequenceOfInteger) H1 = new TColStd_HSequenceOfInteger;
// H1申明并占用了 48 bytes内存
{
Handle (TColStd_HSequenceOfInteger) H2;
H2 = H1; // H1 有两个引用
if (argc == 3) {
Handle (TColStd_HSequenceOfInteger) H3;
H3 = H1;
// Here, H1 有三个引用
...
}
// Here, H1 有两个引用
}
// Here, H1有一个引用
}
// Here, H1 没有引用并且引用 TColStd_HSequenceOfInteger 对象被删除.
通过定义以下内容,您可以轻松地将对象的引用转换为void *:
void *pointer;
Handle(Some_class) aHandle;
// 这里复制指针
Pointer = &aHandle;
aHandle = * (Handle(Some_Class) *)pointer;
周期
如果两个或多个对象通过句柄相互引用,则会出现循环。在这种情况下,自动销毁将不起作用。
考虑例如图形,其对象(图元)必须知道它们所属的图形对象,即图元必须具有对完整图形对象的引用。如果两个基元和图形都由句柄操纵,并且它们通过将句柄保持为字段来相互引用,则会出现循环。当应用程序中的最后一个句柄被破坏时,图形对象不会被删除,因为它的句柄存储在它自己的数据结构中。
避免这种情况有两种方法:
- 将C ++指针用于一种引用,例如从基元到图形
- 当需要销毁图形对象时,将一组句柄(例如,基元中的图形的句柄)置为NULL
插件管理
插件的分发
插件是可以动态加载到客户端应用程序中的组件,不需要直接链接到它。
插件可用于:
- 实现驱动程序的机制,即根据当前事务动态更改驱动程序实现(例如,检索存储在另一个应用程序版本中的文档),
- 将处理资源限制到所需的最小值(例如,只要用户不需要,它就不会在运行时加载任何应用程序服务),
- 促进模块化开发(应用程序可以提供基本功能,而一些高级功能将作为插件添加时可用)。
在全局通用标识符(GUID)的帮助下识别插件。
C++插件实现
路径位置
$CSF_PluginDefaults/Plugin
C++客户端插件实现
例子:
FAFactory.h
#include <Standard_Macro.hxx>
#include <Standard_GUID.hxx>
#include <Standard_Transient.hxx>
class FAFactory
{
public:
Standard_EXPORT static Handle(Standard_Transient) Factory (const Standard_GUID& theGUID);
};
FAFactory.c
#include <FAFactory.hxx>
#include <FADriver_PartRetriever.hxx>
#include <FADriver_PartStorer.hxx>
#include <FirstAppSchema.hxx>
#include <Standard_Failure.hxx>
#include <FACDM_Application.hxx>
#include <Plugin_Macro.hxx>
static Standard_GUID StorageDriver ("45b3c690-22f3-11d2-b09e-0000f8791463");
static Standard_GUID RetrievalDriver("45b3c69c-22f3-11d2-b09e-0000f8791463");
static Standard_GUID Schema ("45b3c6a2-22f3-11d2-b09e-0000f8791463");
//======================================================
// function : Factory
// purpose :
//======================================================
Handle(Standard_Transient) FAFactory::Factory (const Standard_GUID& theGUID)
{
if (theGUID == StorageDriver)
{
std::cout << "FAFactory : Create store driver\n";
static Handle(FADriver_PartStorer) sd = new FADriver_PartStorer();
return sd;
}
if (theGUID == RetrievalDriver)
{
std::cout << "FAFactory : Create retrieve driver\n";
static Handle(FADriver_PartRetriever) rd = new FADriver_PartRetriever();
return rd;
}
if (theGUID == Schema)
{
std::cout << "FAFactory : Create schema\n";
static Handle(FirstAppSchema) s = new FirstAppSchema();
return s;
}
Standard_Failure::Raise ("FAFactory: unknown GUID");
return Handle(Standard_Transient)();
}
// export plugin function "PLUGINFACTORY"
PLUGIN(FAFactory)
Root类
基本数据类型
OCCT中的基本数据类型与C++之间的对比
表中大部分数据类型都是对其相应的C++类型的typedef的重命名。但是,有几个个例:
- Standard_Boolean是对是作为C ++ unsigned int基本类型的typedef实现的。
- Standard_ExtString是对C ++ short基本类型的typedef实现的。
内存管理
在工作会话中,几何建模应用程序创建和删除在动态内存(堆)中分配的大量C ++对象。在这种情况下,用于分配和释放的标准存储器的的性能可能是不够的。
因此,Open CASCADE技术采用标准包中实现的专用内存管理器。
内存管理器基于以下原则:
- 小内存阵列被分组成集群然后再循环(不在使用也不会回到系统中,被循环使用)。
- 大的内存阵列通过系统的标准功能进行分配和解除分配(当不再使用时,阵列将被释放到系统中)。
内存管理器的用法
使用OCCT内存管理,我们不需要传统的malloc和free,取而代之的是Standard :: Allocate(),和Standard :: Free()。同时,使用Standard :: Reallocate()来代替C中的realloc()。
配置内存管理器
OCCT存储器管理器可以被配置为将不同的优化技术应用于不同的存储器块(取决于它们的大小),甚至可以避免任何优化并直接使用C函数malloc()和free()。
- MMGT_OPT:如果设置为0(默认值),则每个内存块直接在C内存堆中分配(通过malloc()和free()函数)。在这种情况下,忽略除MMGT_CLEAR之外的所有其他选项; 如果设置为1,则内存管理器执行如下所述的优化; 如果设置为2,则使用英特尔TBB优化内存管理器。
- MMGT_CLEAR:如果设置为1(默认值),则每个分配的内存块由零清零; 如果设置为0,则按原样返回内存块。
- MMGT_CELLSIZE:定义在大型内存池中分配的块的最大大小。默认值为200。
- MMGT_NBPAGES:定义为页面中的小块分配的内存块的大小(取决于操作系统)。默认值为1000。
- MMGT_THRESHOLD:定义在内部循环而不是返回到堆的块的最大大小。默认值为40000。
- MMGT_MMAP:当设置为1(默认)时,使用操作系统的内存映射功能分配大内存块; 如果设置为0,它们将通过malloc()在C堆中分配。
内存管理器的优化
当MMGT_OPT设置为1时,使用以下优化技术:
- 尺寸小于MMGT_CELLSIZE的小块不单独分配。而是分配在大型的内存池(每个池的大小为MMGT_NBPAGES的大小)。每个新的内存块都安排在当前池的备用位置。当前内存池完全占用时,将分配下一个内存池,依此类推。
- 大小大于MMGT_CELLSIZE但小于MMGT_THRESHOLD的中型块直接在堆中分配(使用malloc()和free())。当通过方法Standard :: Free()释放这些块时,它们就像小块一样被回收。
- 大小大于MMGT_THRESHOLD的大块,包括用于小块的内存池,根据MMGT_MMAP的值进行分配:如果为0,则这些块在堆中分配; 否则,它们使用管理内存的操作系统特定功能进行分配。调用Standard :: Free()时,会立即将大块返回给系统。
优点和缺点
OCCT内存管理器的主要优点在于它的小型和中型块的回收,这使得应用程序在不断分配和释放类似大小的多个内存块时工作得更快。
相关的缺点是在程序执行期间回收的存储器不会返回到操作系统。这可能会导致大量内存消耗,甚至被误解为内存泄漏。为了最大限度地减少这种影响,必须在完成内存密集型操作后调用Standard :: Purge方法。
OCCT内存管理器需要注意的是:
- 仅当MMGT_OPT为1 时,在每个存储块的开头分配额外的4个字节(或64位平台上的8个字节)以保持其大小
- 每个分配的内存块的大小最多为8个字节(当MMGT_OPT为0(默认值); 32位平台的典型值为4个字节)。
OCCT内存管理器使用互斥锁来锁定对空闲列表的访问,因此在不同线程经常同时调用内存管理器的情况下,它可能比非优化模式更差的性能。原因是malloc()和free()的现代实现采用了几个分配场所,从而避免了等待互斥释放的延迟。
异常
每个异常都直接或通过继承另一个异常从Standard_Failure继承。
抛出异常
DomainError::Raise(“Cannot cope with this condition”);
捕捉异常
try {
OCC_CATCH_SIGNALS
// try block
}
catch(DomainError) {
// handle DomainError exceptions here
}
注意
通常,为了编写与平台无关的代码,建议在try {}块或其他可能发生信号的代码中插入宏OCC_CATCH_SIGNALS。
集合类
Collections 集合组件包含处理数据的动态大小的聚集体的类。集合类是通用的(类似C ++模板),也就是说,它们定义了一个结构和算法,允许保存各种对象,这些对象不一定从唯一的根类继承。当您需要使用给定类型对象的集合时,必须为此特定类型的元素实例化它。
字符串
字符串是基于ASCII / Unicode UTF-8(普通8位字符类型)和UTF-16 / UCS-2(16位字符类型)处理动态大小的字符序列的类。它们提供内置内存管理的编辑操作,使相对对象比普通字符数组更容易使用。
- 使用内置字符串管理器对字符串对象进行编辑操作
- 处理动态大小的字符序列
- 从ASCII到UTF-8字符串的转换。
ASCII字符的可变长度序列(正常的8位字符类型)。它提供了内置内存管理的编辑操作,使AsciiString对象比普通字符数组更容易使用。
TCollection_ExtendedString:
可变长度的“扩展”(UNICODE)字符序列(16位字符类型)。它提供了内置内存管理的编辑操作,使ExtendedString对象比普通的扩展字符数组更容易使用。
ExtendedString对象遵循值语义;也就是说,它们是实际的字符串,而不是字符串的句柄,并通过赋值进行复制。您可以使用HExtendedString对象来获取字符串的句柄。
集合
通用集合
Array
TCollection_Array1:与C阵列类似的一维数组,即固定大小但在构造时动态标注尺寸。
TCollection_Array2:固定大小但在构造时动态标注尺寸的二维数组。
TCollection_HArray1:与C容器类似的一维数组,即固定大小但在构造时动态标注尺寸。HArray1对象是数组的句柄。
TCollection_HArray2:是TCollection_HArray1的二维形态
TCollection_HSequence:这是一个由整数索引的序列。这个序列是可变大小的结构。
TCollection_List:这些是非唯一对象的有序列表,可以使用迭代器按顺序访问。列表中的项目插入在任何位置都非常快。但是,如果列表很长,则按值搜索项目可能会很慢,因为它需要顺序搜索。
TCollection_Sequence:这是一个由整数索引的序列。
Map
Map是动态扩展的数据结构,可以使用Key快速访问数据。TCollection_BasicMap是地图的根类。
Map的一般属性
映射项可能包含复杂的非单一数据,因此使用数组管理它们可能很困难。所以,需要使用Map数据结构。
DataMap是一个通用类,它依赖于三个参数:
- Key是地图中条目的键类型,
- Item是与地图中的键相关联的元素的类型,
- Hasher是键上的哈希类型。
DoubleMap是一个泛型类,它依赖于四个参数:
- Key1是地图中条目的第一个键的类型,
- Key2是地图中条目的第二个键的类型,
- Hasher1是第一个键上的哈希类型,
- Hasher2是第二个键上的哈希类型。
IndexedDataMap是一个通用类,它依赖于三个参数:
- Key是地图中条目的键类型,
- Item是与地图中的键相关联的元素的类型,
- Hasher是键上的哈希类型。
常用的数学算法
Open CASCADE技术中提供的数学算法包括:
- 向量和矩阵
- 几何图元
- 数学算法
向量和矩阵
Vectors和Matrices组件提供了基本类型Vector和Matrix的C ++实现,它们经常用于定义更复杂的数据结构。
算法包括:
- 涉及矢量和矩阵的基本计算;
- 计算方阵的特征值和特征向量;
- 求解一组线性代数方程;
- 找到一组非线性方程的根的算法;
- 用于查找一个或多个自变量的最小函数的算法。
向量和矩阵具有的范围,必须在声明时定义,并且在声明后不能更改。
math_Vector v(1, 3);
// a vector of dimension 3 with range (1..3)
math_Matrix m(0, 2, 0, 2);
// a matrix of dimension 3x3 with range (0..2, 0..2)
math_Vector v(N1, N2);
// a vector of dimension N2-N1+1 with range (N1..N2)
它们不能被共享并通过赋值进行复制。
math_Vector v1(1, 3), v2(0, 2);
v2 = v1;
// v1 is copied into v2. a modification of v1 does not affect v2
math_Vector v(1, 3);
math_Matrix m(1, 3, 1, 3);
Standard_Real value;
v(2) = 1.0;
value = v(1);
m(1, 3) = 1.0;
value = m(2, 2);
Vector和Matrix对象上的某些操作可能不合法。在这种情况下会引发异常。使用了两个异常:
- 当操作中涉及的两个矩阵或向量具有不兼容的维度时,会引发Standard_DimensionError异常。
- 当操作中涉及的两个矩阵或向量具有不兼容的维度时,会引发Standard_DimensionError异常。
math_Vector v1(1, 3), v2(1, 2), v3(0, 2);
v1 = v2;
// error: Standard_DimensionError is raised
v1 = v3;
// OK: ranges are not equal but dimensions are
// compatible
v1(0) = 2.0;
// error: Standard_RangeError is raised
来源: https://www.opencascade.com/doc/occt-7.3.0/overview/html/occt_user_guides__foundation_classes.html
数学算法
Gauss算法,为一组线性方程求Gauss解
class Gauss {
public:
Gauss (const math_Matrix& A);
Standard_Boolean IsDone() const;
void Solve (const math_Vector& B,
math_Vector& X) const;
};
#include <math_Vector.hxx>
#include <math_Matrix.hxx>
main ()
{
math_Vector a(1, 3, 1, 3);
math_Vector b1(1, 3), b2(1, 3);
math_Vector x1(1, 3), x2(1, 3);
// a, b1 and b2 are set here to the appropriate values
math_Gauss sol(a); // computation of the
// LU decomposition of A
if(sol.IsDone()) { // is it OK ?
sol.Solve(b1, x1); // yes, so compute x1
sol.Solve(b2, x2); // then x2
...
}
else { // it is not OK:
// fix up
sol.Solve(b1, x1); // error:
// StdFail_NotDone is raised
}
}
原子类
原子类是用来支持各种类别日期和时间信息的处理,以及大多数物理量的基本类型。例如长度,面积,体积,质量,密度,重量,温度,压力等。
原子类提供以下功能:
- 表示大部分数学和物理量的原始类型的定义;
- 单位转换工具提供统一的机制来处理数量和相关的物理单位:检查单位兼容性,执行不同单位之间的价值转换等(参见)
- 管理时间信息(如日期和时间段)的资源
- 用于管理颜色定义的资源
OCCT基础的更多相关文章
- Open CASCADE Technology(OCCT)概述
OCCT模块结构图 基础类: Foundation Classes module underlies all other OCCT classes; 模型数据: Modeling Data modul ...
- java基础集合经典训练题
第一题:要求产生10个随机的字符串,每一个字符串互相不重复,每一个字符串中组成的字符(a-zA-Z0-9)也不相同,每个字符串长度为10; 分析:*1.看到这个题目,或许你脑海中会想到很多方法,比如判 ...
- node-webkit 环境搭建与基础demo
首先去github上面下载(地址),具体更具自己的系统,我的是windows,这里只给出windows的做法 下载windows x64版本 下载之后解压,得到以下东西 为了方便,我们直接在这个目录中 ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- Golang, 以17个简短代码片段,切底弄懂 channel 基础
(原创出处为本博客:http://www.cnblogs.com/linguanh/) 前序: 因为打算自己搞个基于Golang的IM服务器,所以复习了下之前一直没怎么使用的协程.管道等高并发编程知识 ...
- [C#] C# 基础回顾 - 匿名方法
C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...
- HTTPS 互联网世界的安全基础
近一年公司在努力推进全站的 HTTPS 化,作为负责应用系统的我们,在配合这个趋势的过程中,顺便也就想去搞清楚 HTTP 后面的这个 S 到底是个什么含义?有什么作用?带来了哪些影响?毕竟以前也就只是 ...
- Swift与C#的基础语法比较
背景: 这两天不小心看了一下Swift的基础语法,感觉既然看了,还是写一下笔记,留个痕迹~ 总体而言,感觉Swift是一种前后端多种语言混合的产物~~~ 做为一名.NET阵营人士,少少多多总喜欢通过对 ...
- .NetCore MVC中的路由(1)路由配置基础
.NetCore MVC中的路由(1)路由配置基础 0x00 路由在MVC中起到的作用 前段时间一直忙于别的事情,终于搞定了继续学习.NetCore.这次学习的主题是MVC中的路由.路由是所有MVC框 ...
随机推荐
- 清除git中缓存的凭证(用户名及密码)
今天刚接触Git,还有Gitstack,然后在克隆Gitstack服务器上的仓库时出现了一直用户身份识别失败问题,找了一些大佬的文章才知道原因在于密码输入错误过多.那么如何重新输入呢? 需要清空本地的 ...
- JFrame实现圆角窗体
感谢大佬:https://blog.csdn.net/Mr_Pang/article/details/47808299?utm_source=blogxgwz0 注:使用AWTUtilities类跨平 ...
- NSArray基本概念
1.NSArray的基本概念 什么是NSArray? NSArray是OC中的数组类,开发中建议尽量使用NSArray替代C语言中的数组 C语言中数组的弊端 int array[4] = {10, 8 ...
- 对于Web性能优化, 了解和经验
我们在发布项目之前压缩CSS和JavaScript源代码,这样文件体积就变小了,用户加载必要资源所花的时间也就更短了. 压缩源码和图片 JavaScript文件源代码可以采用混淆压缩的方式,CSS文件 ...
- LeetCode随缘刷题之字符串转换整数
package leetcode.day_01_29; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 请你 ...
- 列出ubuntu软件管理工具apt的一些用法(自由总结)
安装软件包 [root@CentOS7 ~]#apt install tree 删除软件包 [root@CentOS7 ~]# apt remove tree 列出仓库软件包 [root@CentOS ...
- 使用代码绑定 DataGridView 控件用于程序界面显示表格
需求 软件界面需要使用表格,对数据进行显示.交互,这是一个非常通用的需求. 实现方法 DataGridView介绍 参考 https://docs.microsoft.com/en-us/dotnet ...
- 根据经纬度坐标获得省市区县行政区划城市名称,自建数据库 java python php c# .net 均适用
目录 步骤一.下载省市区边界数据 步骤二.解析CSV文件导入数据库 步骤三.在程序中根据坐标解析获得城市 在LBS应用中,根据坐标来解析获得对应是哪个城市是一个很常见的功能,比如App里面通过手机定位 ...
- find+grep+正则表达式
目录 find+grep+正则表达式 1.find 2.grep 3.正则表达式 find+grep+正则表达式 1.find 根据文件的名称或者属性查找文件. # 自己在 /root/adc目录下长 ...
- OSI七层协议&TCP协议(三次握手四次挥手)
今日内容 python 基础回顾 软件开发架构 网络理论前戏 OSI 七层协议(五层) TCP协议 三次握手与四次挥手 UDP协议 内容详细 一.python 基础回顾 1.基本数据类型 整型 int ...