Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,9 @@ func (c *commandContext) AddSurface(resolution float32) bool {
it.Incr()
}
}
c.editor.merge(pcNew)
if err := c.editor.merge(pcNew); err != nil {
return false
}
c.setPointCloudUpdated()
return true
}
Expand Down Expand Up @@ -631,8 +633,10 @@ func (c *commandContext) VoxelFilter(resolution float32) error {

if selected {
c.editor.passThrough(c.baseFilter(false))
c.editor.pop()
c.editor.merge(pcFiltered)
if err := c.editor.merge(pcFiltered); err != nil {
return err
}
c.editor.squashLatest()
} else {
if err := c.editor.SetPointCloud(pcFiltered, cloudMain); err != nil {
return err
Expand Down Expand Up @@ -731,7 +735,9 @@ func (c *commandContext) FinalizeCurrentMode() error {
for ; it.IsValid(); it.Incr() {
it.SetVec3(trans.Transform(it.Vec3()))
}
c.editor.merge(c.editor.ppSub)
if err := c.editor.merge(c.editor.ppSub); err != nil {
return err
}
c.setPointCloudUpdated()
c.UnsetCursors()
}
Expand Down
53 changes: 34 additions & 19 deletions editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const (
)

type editor struct {
history
*history
pp *pc.PointCloud
ppSub *pc.PointCloud
ppSubRect rect
Expand All @@ -33,17 +33,8 @@ func newEditor() *editor {
}
}

type history interface {
MaxHistory() int
SetMaxHistory(m int)
push(pp *pc.PointCloud) *pc.PointCloud
pop() *pc.PointCloud
undo() (*pc.PointCloud, bool)
clear()
}

func (e *editor) Undo() bool {
pp, ok := e.history.undo()
pp, ok := e.history.undo(e.pp)
if ok {
e.pp = pp
}
Expand Down Expand Up @@ -114,7 +105,12 @@ func (e *editor) SetPointCloud(pp *pc.PointCloud, id cloudID) error {
}
switch id {
case cloudMain:
e.pp = e.push(pcNew)
if e.pp != nil {
if err := e.push(newUndoDataEntireCloud(e.pp)); err != nil {
return err
}
}
e.pp = pcNew
case cloudSub:
e.ppSub = pcNew
it, err := pcNew.Vec3Iterator()
Expand Down Expand Up @@ -161,7 +157,10 @@ func (e *editor) label(fn func(int, mat.Vec3) (uint32, bool)) error {
itL.Incr()
i++
}
e.pp = e.push(pcNew)
if err := e.push(newUndoDataEntireCloud(e.pp)); err != nil {
return err
}
e.pp = pcNew
runtime.GC()
return nil
}
Expand All @@ -171,7 +170,10 @@ func (e *editor) passThrough(fn func(int, mat.Vec3) bool) error {
if err != nil {
return err
}
e.pp = e.push(pp)
if err := e.push(newUndoDataEntireCloud(e.pp)); err != nil {
return err
}
e.pp = pp
runtime.GC()
return nil
}
Expand All @@ -181,7 +183,10 @@ func (e *editor) passThroughByMask(sel []uint32, mask, val uint32) error {
if err != nil {
return err
}
e.pp = e.push(pp)
if err := e.push(newUndoDataEntireCloud(e.pp)); err != nil {
return err
}
e.pp = pp
runtime.GC()
return nil
}
Expand Down Expand Up @@ -214,7 +219,10 @@ func (e *editor) relabelPointsInLabelRange(minLabel, maxLabel, newLabel uint32)
lt.SetUint32(newLabel)
}

e.pp = e.push(pcNew)
if err := e.push(newUndoDataEntireCloud(e.pp)); err != nil {
return err
}
e.pp = pcNew
runtime.GC()
return nil
}
Expand Down Expand Up @@ -255,7 +263,10 @@ func (e *editor) unlabelPoints(labelsToKeep []uint32) error {
lt.SetUint32(0)
}

e.pp = e.push(pcNew)
if err := e.push(newUndoDataEntireCloud(e.pp)); err != nil {
return err
}
e.pp = pcNew
runtime.GC()
return nil
}
Expand Down Expand Up @@ -347,7 +358,7 @@ func passThroughImpl(pp *pc.PointCloud, core func(_, _ *pc.PointCloud) int) (*pc
return pcNew, nil
}

func (e *editor) merge(pp *pc.PointCloud) {
func (e *editor) merge(pp *pc.PointCloud) error {
pcNew := &pc.PointCloud{
PointCloudHeader: e.pp.PointCloudHeader.Clone(),
Points: e.pp.Points + pp.Points,
Expand All @@ -356,6 +367,10 @@ func (e *editor) merge(pp *pc.PointCloud) {
pcNew.Width = pcNew.Points
pcNew.Height = 1

e.pp = e.push(pcNew)
if err := e.push(newUndoDataEntireCloud(e.pp)); err != nil {
return err
}
e.pp = pcNew
runtime.GC()
return nil
}
79 changes: 79 additions & 0 deletions history.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package main

import (
"bytes"

"github.com/seqsense/pcgol/pc"
)

type recordStore interface {
store(parts ...[]byte) record
}

type record interface {
load() []byte
}

type undoStep []record

type history struct {
store recordStore
steps []undoStep
maxHistory int
}

func (h *history) MaxHistory() int {
return h.maxHistory
}

func (h *history) SetMaxHistory(m int) {
if m < 0 {
m = 0
}
h.maxHistory = m
}

func (h *history) push(d undoData) error {
var head bytes.Buffer
if err := encodeUndoData(&head, d); err != nil {
return err
}
h.steps = append(h.steps, undoStep{h.store.store(head.Bytes(), d.payload())})
for len(h.steps) > h.maxHistory {
h.steps[0] = nil
h.steps = h.steps[1:]
}
return nil
}

func (h *history) squashLatest() {
if n := len(h.steps); n >= 2 {
h.steps[n-2] = append(h.steps[n-2], h.steps[n-1]...)
h.steps[n-1] = nil
h.steps = h.steps[:n-1]
}
}

func (h *history) undo(pp *pc.PointCloud) (*pc.PointCloud, bool) {
n := len(h.steps)
if n == 0 {
return nil, false
}
step := h.steps[n-1]
for i := len(step) - 1; i >= 0; i-- {
d, err := decodeRecord(step[i].load())
if err != nil {
return nil, false
}
if pp, err = d.restore(pp); err != nil {
return nil, false
}
}
h.steps[n-1] = nil
h.steps = h.steps[:n-1]
return pp, true
}

func (h *history) clear() {
h.steps = nil
}
Loading
Loading