更新数据持久化设计

pull/7/head
cx 7 years ago
parent fdf14278c5
commit 980b5529fb

@ -1,5 +1,6 @@
import { ArrayRemove } from '../../src/Common/Utils'; import { ArrayRemove } from '../../src/Common/Utils';
import { Vector3 } from 'three';
/* /*
webCAD . webCAD .
,,. ,,.
@ -96,12 +97,13 @@ cmdName:"Ohther" //假设这个是一个复杂度很高的命令
id.. id..
:id. :id.
,id.
,,.
*/ ,,.
*/
//CAD对象工厂,通过注册 和暴露的创建方法,动态创建对象 //CAD对象工厂,通过注册 和暴露的创建方法,动态创建对象
@ -130,16 +132,16 @@ class CADObject
{ {
//#region -------------------------DB------------------------- //#region -------------------------DB-------------------------
protected db: Database; protected _db: Database;
get Db(): Database get Db(): Database
{ {
return this.db; return this._db;
} }
SetDb(db: Database) SetDb(db: Database)
{ {
if (!this.db) if (!this._db)
{ {
this.db = db; this._db = db;
this.objectId = db.AllocateId(this); this.objectId = db.AllocateId(this);
} }
else else
@ -150,14 +152,14 @@ class CADObject
//#endregion //#endregion
//#region -------------------------isErase------------------------- //#region -------------------------isErase-------------------------
protected isErase: boolean = false; protected _isErase: boolean = false;
get IsErase(): boolean get IsErase(): boolean
{ {
return this.isErase; return this._isErase;
} }
Erase(isErase: boolean = true) Erase(isErase: boolean = true)
{ {
this.isErase = isErase; this._isErase = isErase;
} }
//#endregion //#endregion
@ -182,49 +184,153 @@ class CADObject
//对象从文件中读取数据,初始化自身 //对象从文件中读取数据,初始化自身
FileIn(file: CADFile) FileIn(file: CADFile)
{ {
//write Id;
this.objectId = this.ReadObjectId(file);
if (this.objectId)
{
this.objectId.Object = this;
}
} }
//对象将自身数据写入到文件. //对象将自身数据写入到文件.
FileOut(file: CADFile) FileOut(file: CADFile)
{ {
this.WriteObjectId(file)
} }
//局部撤销 //局部撤销
ApplyPartialUndo(file: CADFile) ApplyPartialUndo(file: CADObject)
{ {
} }
//#endregion //#endregion
private WriteObjectId(file: CADFile)
{
if (this.objectId)
{
file.Write(this.objectId.Index);
}
else
file.Write(-1);
}
private ReadObjectId(file: CADFile): ObjectId
{
let index = file.Read();
if (index >= 0 && this._db)
{
return this._db.GetObjectId(index);
}
}
} }
/*
CADObjectId,.
id,.
ObjectId使 Database(dbid,便id)
*/
class ObjectId class ObjectId
{ {
private id: number; private id: number;
private obj: CADObject; private obj: CADObject;
constructor(id: number, obj: CADObject) private constructor()
{ {
this.id = id; this.id = -1;
this.obj = obj; }
static Create(db: Database, index: number): ObjectId
{
let id = db.GetObjectId(index);
if (!id)
{
id = new ObjectId();
id.id = index;
}
return id;
} }
set Object(v: CADObject)
{
this.obj = v;
}
get Object(): CADObject get Object(): CADObject
{ {
return this.obj; return this.obj;
} }
get Index(): number
{
return this.id;
}
} }
//cad文件数据 //cad文件数据
class CADFile class CADFile
{ {
private readIndex: number = 0;
private dataList: any[] = [];
WriteString(str: string)
{
this.dataList.push(str);
}
ReadString(): string
{
let str = this.dataList[this.readIndex] as string;
this.readIndex++;
return str;
}
WriteObject(obj: CADObject)
{
this.WriteString(obj.ClassName);
obj.FileOut(this);
}
ReadObject(db: Database): CADObject
{
let className = this.ReadString();
let obj = CADFactory.CreateObject(className);
obj.SetDb(db);
obj.FileIn(this);
return obj;
}
Write(data: any)
{
this.dataList.push(data);
}
Read(): any
{
let data = this.dataList[this.readIndex];
this.readIndex++;
return data;
}
} }
class AppendData extends CADObject class AppendData extends CADObject
{ {
objData: CADFile; private object: CADObject;
private cadFile: CADFile;
constructor(obj: CADObject)
{
super();
this.cadFile = new CADFile();
this.cadFile.WriteObject(obj);
}
getObject(db: Database): CADObject
{
if (!this.object)
{
this.object = this.cadFile.ReadObject(db);
}
return this.object;
}
//#region -----------------------------File----------------------------- //#region -----------------------------File-----------------------------
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化 //对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
//类名,保证序列化时得到正确的new //类名,保证序列化时得到正确的new
get ClassName(): string get ClassName(): string
{ {
return "CADObject"; return "AppendData";
} }
//对象从文件中读取数据,初始化自身 //对象从文件中读取数据,初始化自身
FileIn(file: CADFile) FileIn(file: CADFile)
@ -233,20 +339,29 @@ class AppendData extends CADObject
FileOut(file: CADFile) FileOut(file: CADFile)
{ } { }
//局部撤销 //局部撤销
ApplyPartialUndo(file: CADFile) ApplyPartialUndo(file: CADObject)
{ } { }
//#endregion -----------------------------File End----------------------------- //#endregion -----------------------------File End-----------------------------
} }
class RemoveData extends CADObject class RemoveData extends CADObject
{ {
index: number; private index: number;
constructor(index: number)
{
super();
this.index = index;
}
get Index()
{
return this.index;
}
//#region -----------------------------File----------------------------- //#region -----------------------------File-----------------------------
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化 //对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
//类名,保证序列化时得到正确的new //类名,保证序列化时得到正确的new
get ClassName(): string get ClassName(): string
{ {
return "CADObject"; return "RemoveData";
} }
//对象从文件中读取数据,初始化自身 //对象从文件中读取数据,初始化自身
FileIn(file: CADFile) FileIn(file: CADFile)
@ -255,7 +370,7 @@ class RemoveData extends CADObject
FileOut(file: CADFile) FileOut(file: CADFile)
{ } { }
//局部撤销 //局部撤销
ApplyPartialUndo(file: CADFile) ApplyPartialUndo(file: CADObject)
{ } { }
//#endregion -----------------------------File End----------------------------- //#endregion -----------------------------File End-----------------------------
} }
@ -268,23 +383,31 @@ class ObjectCollection<T> extends CADObject
{ {
this.objectCol.push(obj); this.objectCol.push(obj);
let hisRec = new HistoricRecord();
let redo = new AppendData();
redo.objData = new CADFile();
obj.FileOut(redo.objData);
hisRec.redoData = redo;
let undo = new RemoveData(); if (this._db && this._db.hm.UndoData)
undo.index = this.objectCol.length - 1; {
hisRec.undoData = undo; let hisRec = new HistoricRecord();
hisRec.redoData = new AppendData(obj);
hisRec.undoData = new RemoveData(this.objectCol.length - 1);
this.db.hm.UndoData.WriteObjectHistoryPath(this, hisRec); this._db.hm.UndoData.WriteObjectHistoryPath(this, hisRec);
}
} }
Remove(obj: CADObject) Remove(obj: CADObject)
{ {
ArrayRemove(this.objectCol, obj); ArrayRemove(this.objectCol, obj);
if (this._db && this._db.hm.UndoData)
{
let hisRec = new HistoricRecord();
hisRec.undoData = new AppendData(obj);
hisRec.redoData = new RemoveData(this.objectCol.length - 1);
this.db.hm.UndoData.WriteObjectHistoryPath(this, undefined); this._db.hm.UndoData.WriteObjectHistoryPath(this, hisRec);
}
}
Cout(): number
{
return this.objectCol.length;
} }
//#region -----------------------------File----------------------------- //#region -----------------------------File-----------------------------
@ -301,17 +424,15 @@ class ObjectCollection<T> extends CADObject
FileOut(file: CADFile) FileOut(file: CADFile)
{ } { }
//局部撤销 //局部撤销
ApplyPartialUndo(file: CADObject) ApplyPartialUndo(undoData: CADObject)
{ {
if (file instanceof AppendData) if (undoData instanceof AppendData)
{ {
file.objData//cad file. let obj = undoData.getObject(this._db);
//create object
//append object
} }
else if (file instanceof RemoveData) else if (undoData instanceof RemoveData)
{ {
//remove object this.Remove(this.objectCol[undoData.Index]);
} }
} }
//#endregion -----------------------------File End----------------------------- //#endregion -----------------------------File End-----------------------------
@ -363,14 +484,19 @@ class HistoricManage extends CADObject
{ {
private curIndex: number = -1; //当前执行位置 private curIndex: number = -1; //当前执行位置
private historyRecord: CommandHistoryRecord[] = []; //历史记录 private historyRecord: CommandHistoryRecord[] = []; //历史记录
private doing: boolean = false;
constructor(db: Database) constructor(db: Database)
{ {
super(); super();
this.db = db; this._db = db;
} }
get UndoData(): CommandHistoryRecord get UndoData(): CommandHistoryRecord
{ {
if (this.doing)
{
return undefined;
}
if (this.historyRecord.length === 0) if (this.historyRecord.length === 0)
{ {
this.StartCmd(""); this.StartCmd("");
@ -392,7 +518,7 @@ class HistoricManage extends CADObject
{ {
return false; return false;
} }
this.doing = true;
for (let [id, recList] of historyRec.HistoryList) for (let [id, recList] of historyRec.HistoryList)
{ {
let obj = id.Object; let obj = id.Object;
@ -402,7 +528,7 @@ class HistoricManage extends CADObject
} }
} }
this.curIndex--; this.curIndex--;
this.doing = false;
return true; return true;
} }
Redo() Redo()
@ -412,6 +538,7 @@ class HistoricManage extends CADObject
{ {
return false; return false;
} }
this.doing = true;
for (let [id, recList] of historyRec.HistoryList) for (let [id, recList] of historyRec.HistoryList)
{ {
let obj = id.Object; let obj = id.Object;
@ -421,7 +548,7 @@ class HistoricManage extends CADObject
} }
} }
this.curIndex++; this.curIndex++;
this.doing = false;
return true; return true;
} }
} }
@ -478,7 +605,7 @@ class Database
if (obj.Db === this) if (obj.Db === this)
{ {
this.idCout++; this.idCout++;
let id = new ObjectId(this.idCout, obj); let id = ObjectId.Create(this, this.idCout);
this.idMap.set(this.idCout, id); this.idMap.set(this.idCout, id);
return id; return id;
} }
@ -487,18 +614,15 @@ class Database
console.warn("对象不属于该数据库!"); console.warn("对象不属于该数据库!");
} }
} }
//获得指定索引的id //获得指定索引的id
GetId(index: number) GetObjectId(index: number): ObjectId
{ {
return this.idMap.get(index); return this.idMap.get(index);
} }
} }
class BlockTableRecord extends ObjectCollection<Entity>
class BlockTableRecord extends CADObject
{ {
private objectCol: CADObject[] = [];
constructor(db: Database) constructor(db: Database)
{ {
super(); super();
@ -519,8 +643,10 @@ class BlockTableRecord extends CADObject
FileOut(file: CADFile) FileOut(file: CADFile)
{ } { }
//局部撤销 //局部撤销
ApplyPartialUndo(file: CADFile) ApplyPartialUndo(file: CADObject)
{ } {
super.ApplyPartialUndo(file);
}
//#endregion-----------------------------File End----------------------------- //#endregion-----------------------------File End-----------------------------
AppendEntity(ent: Entity): ObjectId AppendEntity(ent: Entity): ObjectId
{ {
@ -530,21 +656,12 @@ class BlockTableRecord extends CADObject
return; return;
} }
ent.SetDb(this.Db); ent.SetDb(this.Db);
this.objectCol.push(ent); this.Append(ent);
let historyData = new HistoricRecord();
// historyData.undoData
this.db.hm.UndoData.WriteObjectHistoryPath(this, historyData);
return ent.Id; return ent.Id;
} }
}
enum EntityUndoType
{
} }
//所有图元的基类 //所有图元的基类
class Entity extends CADObject class Entity extends CADObject
{ {
@ -561,9 +678,11 @@ export enum LineUndoType
//直线对象 //直线对象
class Line extends Entity class Line extends Entity
{ {
private startPoint: Vector3;
constructor() constructor()
{ {
super(); super();
this.startPoint = new Vector3(0, 0, 0);
} }
//-----------------------------File----------------------------- //-----------------------------File-----------------------------
@ -578,10 +697,14 @@ class Line extends Entity
//对象从文件中读取数据,初始化自身 //对象从文件中读取数据,初始化自身
FileIn(file: CADFile) FileIn(file: CADFile)
{ {
super.FileIn(file);
this.startPoint.fromArray(file.Read());
} }
//对象将自身数据写入到文件. //对象将自身数据写入到文件.
FileOut(file: CADFile) FileOut(file: CADFile)
{ {
super.FileOut(file);
file.Write(this.startPoint.toArray());
} }
ApplyPartialUndo(data) ApplyPartialUndo(data)
{ {
@ -596,19 +719,54 @@ class Line extends Entity
} }
} }
//-----------------------------File End----------------------------- //-----------------------------File End-----------------------------
set StartPoint(v: Vector3)
{
this.startPoint.copy(v);
}
get StartPoint(): Vector3
{
return this.startPoint.clone();
}
} }
CADFactory.RegisterObject(Line); CADFactory.RegisterObject(Line);
let l = CADFactory.CreateObject("Line") as Entity; let db = new Database();
let l = CADFactory.CreateObject("Line") as Line;
console.log(l); console.log(l);
let db = new Database(); l.StartPoint = new Vector3(0, 1, 0);
let id = db.ModelSpace.AppendEntity(l); let id = db.ModelSpace.AppendEntity(l);
db.GetId(0).Object.ClassName /*?*/ db.GetObjectId(0).Object.ClassName /*?*/
console.log(id); console.log(id);
db.hm.Undo();/*?*/
db.hm.Redo();/*?*/ function createLine()
{
for (let i = 0; i < 5000; i++)
{
let l = CADFactory.CreateObject("Line") as Line;
}
}
test('create line', () =>
{
});
// createLine(); //?.
function undoRedo()
{
for (let i = 0; i < 5000; i++)
{
db.hm.Undo();
db.hm.Redo();
}
}
// undoRedo(); //?.

@ -1,353 +0,0 @@
/*
webCAD .
,,.
.
ID
.
*/
import { List } from "immutable"
class CADObject
{
ApplyUndoData(data: any)
{
}
}
/**
*
*
* @class Database
*/
class Database extends CADObject
{
private curUndoIndex = -1;
//命令撤销数据列表
commandUndoData: { cmdName: string, undoData: Map<CADObject, UndoFile> }[] = [];
get UndoData(): Map<CADObject, UndoFile>
{
if (this.commandUndoData.length == 0)
{
this.startCmd("");
}
return this.commandUndoData[this.commandUndoData.length - 1].undoData;
}
startCmd(cmdName: string)
{
if (this.commandUndoData.length > 0 && this.curUndoIndex != this.commandUndoData.length - 1)
{
this.commandUndoData.splice(this.curUndoIndex, this.commandUndoData.length - this.curUndoIndex);
}
this.commandUndoData.push({ cmdName: "", undoData: new Map<CADObject, UndoFile>() });
this.curUndoIndex = this.commandUndoData.length - 1;
}
Undo(cout: number)
{
if (this.curUndoIndex == -1)
{
return;
}
for (let [obj, data] of this.commandUndoData[this.curUndoIndex].undoData)
{
for (let i = data.m_UndoDataList.length; i--;)
{
let d = data.m_UndoDataList[i];
obj.ApplyUndoData(d);
}
}
this.curUndoIndex--;
}
Redo(cout: number)
{
let undoFile = this.commandUndoData[this.curUndoIndex + 1];
if (undoFile)
{
for (let [obj, data] of undoFile.undoData)
{
for (let d of data.m_UndoDataList)
{
obj.ApplyUndoData(d);
}
}
this.curUndoIndex++;
}
}
}
let arr = [0, 1, 2, 3, 4, 5, 6];
arr.splice(3, arr.length - 3);
arr
/**
*
*
* @class UndoFile
*/
class UndoFile
{
m_UndoDataList = [];
}
enum EntityUndoType
{
}
//
interface EntityData
{
id: number;
isErase: boolean;
}
/**
*
*
*
* @class Entity
*/
class Entity extends CADObject
{
protected m_Data: EntityData;
m_Db: Database;
constructor()
{
super();
this.m_Data = {
id: -1,
isErase: false
}
}
get UndoFile(): UndoFile
{
if (this.m_Db)
{
let undoData = this.m_Db.UndoData;
if (!undoData.has(this))
{
undoData.set(this, new UndoFile());
}
return undoData.get(this);
}
}
WriteUndoData(data: any)
{
let undoFile = this.UndoFile;
if (undoFile)
{
undoFile.m_UndoDataList.push(data);
}
}
}
/**
* 线
*
* @enum {number}
*/
enum LineUndoType
{
Full = 0,
StartPoint = 1,
EndPoint = 2,
}
//
interface LineData extends EntityData
{
startPoint: List<number>,
endPoint: List<number>
}
/**
* 线
*
* @class Line
*/
class Line extends Entity
{
protected m_Data: LineData;
constructor()
{
super();
this.m_Data.startPoint = List([0, 0, 0]);
this.m_Data.endPoint = List([0, 0, 0]);
}
get StartPoint(): number[]
{
return this.m_Data.startPoint.toJS();
}
set StartPoint(value: number[])
{
let newP = List(value);
this.WriteUndoData({ type: LineUndoType.StartPoint, data: { startPoint: this.m_Data.startPoint } });
this.m_Data.startPoint = newP;
}
ApplyUndoData(data: any)
{
switch (data.type)
{
case LineUndoType.Full:
break;
case LineUndoType.StartPoint:
this.m_Data.startPoint = data.data.startPoint;
break;
default:
break;
}
}
}
/**
* ,使.
*
* @class EentiyDrawAdapter
*/
class EentiyDrawAdapter
{
Draw()
{
return undefined;
}
}
/**
* 线
*
* @class LineAdapter
* @extends {EentiyDrawAdapter}
*/
class LineAdapter extends EentiyDrawAdapter
{
Draw()
{
return undefined;
}
Update(type: number)
{
switch (type)
{
case LineUndoType.Full:
break;
case LineUndoType.StartPoint:
break;
case LineUndoType.EndPoint:
break;
default:
break;
}
}
}
let line = new Line();
console.log(line);
line.StartPoint = [1, 2, 3];
console.log(line);
let db = new Database();
line.m_Db = db;
line.StartPoint = [3, 3, 3];
console.log(line);
line.StartPoint = [3, 3, 5];
line.StartPoint = [12, 3, 5];
console.log(line);
console.log(db.commandUndoData);
db.Undo(1);
console.log(line.StartPoint);
db.Redo(1);
db.startCmd("");
console.log(line.StartPoint);
function per()
{
for (let i = 0; i < 5000; i++)
{
new Line();
}
}
function per2()
{
for (let i = 0; i < 5000; i++)
{
line.StartPoint = [3, 3, 3];
// console.log(line);
// line.StartPoint = [3, 3, 5];
line.StartPoint = [12, 3, 5];
// console.log(line);
// console.log(db.commandUndoData);
db.Undo(1);
// console.log(line);
db.Redo(1);
db.startCmd("");
// console.log(line.StartPoint);
}
}
per();/*?.*/
per2();/*?.*/
per2();/*?.*/
per2();/*?.*/
per2();/*?.*/
console.log(3);

@ -1,15 +0,0 @@
import { GeUtils } from '../../src/Geometry/GeUtils';
import * as THREE from "three";
import { Vector3 } from 'three';
test("测试平行", () =>
{
let v1 = new Vector3(0, 0, 1);
let v2 = new Vector3(0.0001, 0, 1);
expect(GeUtils.isParallelTo(v1, v2)).toBe(false);
expect(v1.equals(new THREE.Vector3(0, 0, 1))).toBe(true);
expect(v2.equals(new THREE.Vector3(0.0001, 0, 1))).toBe(true);
// console.log(v1.isParallelTo(v2));
// console.log(v1);
// console.log(v2);
})
Loading…
Cancel
Save