// The actual collection must contain all expected elements and nothing else. // The order of elements is not significant. func ContainsExactly(actual_ interface{}, expected_ interface{}) (match bool, pos Message, neg Message, err os.Error) { actual, err := toArray(actual_) if err != nil { return } expected, err := toArray(expected_) if err != nil { return } containsAll := true remaining := new(vector.Vector) remaining.AppendVector((*vector.Vector)(&actual)) for i := 0; i < len(expected); i++ { if idx, found := findIndex(*remaining, expected[i]); found { remaining.Delete(idx) } else { containsAll = false break } } match = containsAll && remaining.Len() == 0 pos = Messagef(actual, "contains exactly ā%vā", expected) neg = Messagef(actual, "does NOT contain exactly ā%vā", expected) return }
func test1() { var a [1000]*S for i := 0; i < len(a); i++ { a[i] = new(S).Init(i) } v := new(vector.Vector) for i := 0; i < len(a); i++ { v.Insert(0, a[i]) if v.Len() != i+1 { panic("len = ", v.Len(), "\n") } } for i := 0; i < v.Len(); i++ { x := v.At(i).(*S) if x.val != v.Len()-i-1 { panic("expected ", i, ", found ", x.val, "\n") } } for v.Len() > 10 { v.Delete(10) } }
func (self Transformer) shorten(arr vec.Vector, index, inside, count int) (rindex int, rinside int) { mut := arr[index] if IsDeleteMutation(mut) { del := toDeleteMutation(mut) del.SetCount(del.Count() - count) if inside == del.Count() { inside = 0 if del.Count() == 0 { arr.Delete(index) } else { index++ } } } else if IsSkipMutation(mut) { skip := toSkipMutation(mut) skip.SetCount(skip.Count() - 1) if inside == skip.Count() { inside = 0 if skip.Count() == 0 { arr.Delete(index) } else { index++ } } } else { panic("Unsupported mutation for shorten()") } return index, inside }
func (self DocumentMutation) applyArrayMutation(arr []interface{}, mutation ArrayMutation, flags uint32) []interface{} { index := 0 var v vec.Vector = arr // Find the lifts lifts := make(map[string]interface{}) for _, mut := range mutation.Array() { switch { case IsInsertMutation(mut), IsSqueezeMutation(mut): continue case IsDeleteMutation(mut): index += toDeleteMutation(mut).Count() case IsSkipMutation(mut): index += toSkipMutation(mut).Count() case IsObjectMutation(mut), IsArrayMutation(mut), IsTextMutation(mut): index++ case IsLiftMutation(mut): l := toLiftMutation(mut) val := v[index] if l.HasMutation() { val = self.apply(val, l.Mutation(), flags) } lifts[l.Id()] = val index++ default: panic("Should never happen") } } index = 0 for _, m := range mutation.Array() { switch { case IsDeleteMutation(m): count := toDeleteMutation(m).Count() for i := 0; i < count; i++ { v.Delete(i) } case IsSkipMutation(m): index += toSkipMutation(m).Count() case IsLiftMutation(m): v.Delete(index) case IsSqueezeMutation(m): v.Insert(index, lifts[toSqueezeMutation(m).Id()]) index++ case IsObjectMutation(m), IsArrayMutation(m), IsTextMutation(m): v[index] = self.apply(v[index], m, flags) index++ default: // Must be an insert mutation v.Insert(index, self.apply(nil, m, flags)) index++ } } return v }
func (g *Game) calcDistances() { q := new(vector.Vector) g.distances = make([][]int, len(g.rootBoard)) for i, x := range g.rootBoard { g.distances[i] = make([]int, len(g.rootBoard)) if x >= 0 { visited := make(map[int]bool) q.Push([]int{i, 0}) for q.Len() > 0 { cell := q.At(0).([]int) index, step := cell[0], cell[1] q.Delete(0) visited[index] = true g.distances[i][index] = step for _, next := range g.nexts(index) { if visited[next+index] != true { q.Push([]int{next + index, step + 1}) } } } } } }
func (self Transformer) transform_pass1_array(sobj, cobj ArrayMutation) os.Error { var ( sarr vec.Vector = sobj.Array() carr vec.Vector = cobj.Array() sindex int = 0 cindex int = 0 sinside int = 0 cinside int = 0 ) // Loop until end of one mutation is reached for sindex < len(sarr) || cindex < len(carr) { var smut, cmut interface{} if sindex < len(sarr) { smut = sarr[sindex] } if cindex < len(carr) { cmut = carr[cindex] } // Server insert/squeeze go first for IsInsertMutation(smut) || IsSqueezeMutation(smut) { if cinside > 0 { self.split(&carr, cindex, cinside) cinside = 0 cindex++ cmut = carr[cindex] } if IsInsertMutation(smut) { // TODO: check the Insert mutation individually for correctness carr.Insert(cindex, NewSkipMutation(1)) cindex++ sindex++ } else if IsSqueezeMutation(smut) { sSqueeze := toSqueezeMutation(smut) // Which operation does the client side have for this object? c, hasCounterpart := self.cLiftCounterpart[sSqueeze.Id()] if !hasCounterpart || IsSkipMutation(c) { // Server lift remains, client skips it at the new position carr.Insert(cindex, NewSkipMutation(1)) cindex++ sindex++ } else if IsDeleteMutation(c) { // Client deletes the object at its new position carr.Insert(cindex, NewDeleteMutation(1)) cindex++ // Server removes squeeze because it is already deleted by the client sarr.Delete(sindex) } else if IsLiftMutation(c) { // sLift := self.sLifts[sSqueeze.Id()] cLift := toLiftMutation(c) if cLift.HasMutation() { // The client does not lift it and therefore it mutates it at the new position carr.Insert(cindex, cLift.Mutation()) cindex++ // Server keeps its squeeze at this position sindex++ } else { // Client skips the squeezed object and does not lift it carr.Insert(cindex, NewSkipMutation(1)) cindex++ // Server keeps its squeeze at this position sindex++ } } else { // The client somehow mutates the object. It must do so at its new position carr.Insert(cindex, c) cindex++ sindex++ } } if sindex < len(sarr) { smut = sarr[sindex] } else { smut = nil } } // Client insert/squeeze go next for IsInsertMutation(cmut) || IsSqueezeMutation(cmut) { if sinside > 0 { self.split(&sarr, sindex, sinside) sinside = 0 sindex++ smut = sarr[sindex] } if IsInsertMutation(cmut) { // TODO: check the Insert mutation individually for correctness cindex++ sarr.Insert(sindex, NewSkipMutation(1)) sindex++ } else { cSqueeze := toSqueezeMutation(cmut) // Which operation does the server side have for this object? s, hasCounterpart := self.sLiftCounterpart[cSqueeze.Id()] if !hasCounterpart || IsSkipMutation(s) { sarr.Insert(sindex, NewSkipMutation(1)) sindex++ cindex++ } else if IsDeleteMutation(s) { // Server deletes the object at its the new position sarr.Insert(sindex, NewDeleteMutation(1)) sindex++ // Client removes squeeze because it is already deleted by the client carr.Delete(cindex) } else if IsLiftMutation(s) { // The server must lift the object here instead sarr.Insert(sindex, s) sindex++ // The server lifted this object as well -> the client cannot lift it -> // then the client cannot squeeze it in here carr.Delete(cindex) } else { // The server mutates the object at its new position sarr.Insert(sindex, s) sindex++ // The client squeezes the object in here cindex++ } } if cindex < len(carr) { cmut = carr[sindex] } else { cmut = nil } } if sindex == len(sarr) && cindex == len(carr) { break } if sindex == len(sarr) || cindex == len(carr) { return os.NewError("The mutations do not have equal length") } // // Lift, Skip, Delete, mutations // if IsLiftMutation(smut) { // Both are lifting the same object? if IsLiftMutation(cmut) { // The client removes its lift. If it has a mutation then it will be moved to the corresponding squeeze carr.Delete(cindex) // The server removes its lift. It will be placed where the client moved it. sarr.Delete(sindex) } else if IsDeleteMutation(cmut) { // The server does not lift the object because it is deleted sarr.Delete(sindex) // The client removes its delete. The delete is put where the server squeezed it. cindex, cinside = self.shorten(carr, cindex, cinside, 1) } else if IsSkipMutation(cmut) { // The client does not skip this element here. It is skipped where it is squeezed in cindex, cinside = self.shorten(carr, cindex, cinside, 1) // Server remains with its lift sindex++ } else { // Q_ASSERT(cmut.isArrayMutation() || cmut.isObjectMutation() || cmut.isTextMutation() || cmut.isRichTextMutation() ); // The client removes its mutation here. It is shifted to the new position where the object is squeezed in. carr.Delete(cindex) // Server remains with its lift sindex++ } } else if IsLiftMutation(cmut) { if IsDeleteMutation(smut) { // The client does not lift the object because it is deleted carr.Delete(cindex) // The server removes its delete. The delete is put where the client squeezed it. sindex, sinside = self.shorten(sarr, sindex, sinside, 1) } else if IsSkipMutation(smut) { // The server does not skip this element here. It is skipped where it is squeezed in sindex, sinside = self.shorten(sarr, sindex, sinside, 1) // Client remains with its lift cindex++ } else { // Q_ASSERT(smut.isArrayMutation() || smut.isObjectMutation() || smut.isTextMutation() || smut.isRichTextMutation() ); // The server removes its mutation here. It is shifted to the new position where the object is squeezed in. sarr.Delete(sindex) // Client remains with its lift cindex++ } } else if IsDeleteMutation(smut) && IsDeleteMutation(cmut) { sdel := toDeleteMutation(smut).Count() cdel := toDeleteMutation(cmut).Count() del := IntMin(sdel-sinside, cdel-cinside) sindex, sinside = self.shorten(sarr, sindex, sinside, del) cindex, cinside = self.shorten(carr, cindex, cinside, del) } else if IsSkipMutation(smut) && IsSkipMutation(cmut) { sskip := toSkipMutation(smut).Count() cskip := toSkipMutation(cmut).Count() skip := IntMin(sskip-sinside, cskip-cinside) sinside += skip cinside += skip if sinside == sskip { sinside = 0 sindex++ } if cinside == cskip { cinside = 0 cindex++ } } else if IsDeleteMutation(smut) && IsSkipMutation(cmut) { sdel := toDeleteMutation(smut).Count() cskip := toSkipMutation(cmut).Count() count := IntMin(sdel-sinside, cskip-cinside) sinside += count if sinside == sdel { sinside = 0 sindex++ } cindex, cinside = self.shorten(carr, cindex, cinside, count) } else if IsSkipMutation(smut) && IsDeleteMutation(cmut) { sskip := toSkipMutation(smut).Count() cdel := toDeleteMutation(cmut).Count() count := IntMin(sskip-sinside, cdel-cinside) sindex, sinside = self.shorten(sarr, sindex, sinside, count) cinside += count if cinside == cdel { cinside = 0 cindex++ } } else if IsSkipMutation(smut) { // ... and mutation at the client cindex++ sinside++ if toSkipMutation(smut).Count() == sinside { sinside = 0 sindex++ } } else if IsSkipMutation(cmut) { // ... and mutation at the srver sindex++ cinside++ if toSkipMutation(cmut).Count() == cinside { cinside = 0 cindex++ } } else if IsDeleteMutation(smut) { // ... and mutation at the client carr.Delete(cindex) sinside++ if toDeleteMutation(smut).Count() == sinside { sinside = 0 sindex++ } } else if IsDeleteMutation(cmut) { // ... and mutation at the server sarr.Delete(sindex) cinside++ if toDeleteMutation(cmut).Count() == cinside { cinside = 0 cindex++ } } else { if IsObjectMutation(smut) && IsObjectMutation(cmut) { if err := self.transform_pass1_object(toObjectMutation(smut), toObjectMutation(cmut)); err != nil { return err } } else if IsArrayMutation(smut) && IsArrayMutation(cmut) { if err := self.transform_pass1_array(toArrayMutation(smut), toArrayMutation(cmut)); err != nil { return err } } else if IsTextMutation(smut) && IsTextMutation(cmut) { if err := self.transform_pass1_text(toTextMutation(smut), toTextMutation(cmut)); err != nil { return err } } else if IsRichTextMutation(smut) && IsRichTextMutation(cmut) { if err := self.transform_pass1_richtext(toRichTextMutation(smut), toRichTextMutation(cmut)); err != nil { return err } } else { return os.NewError("The mutations are not compatible or not allowed inside an array mutation") } sindex++ cindex++ } } sobj.SetArray(sarr) cobj.SetArray(carr) return nil }
func (self Transformer) transform_pass1_richtext(sobj, cobj RichTextMutation) os.Error { var ( sarr vec.Vector = sobj.TextArray() carr vec.Vector = cobj.TextArray() sindex int = 0 cindex int = 0 sinside int = 0 cinside int = 0 ) // Loop until end of one mutation is reached for sindex < len(sarr) || cindex < len(carr) { var smut, cmut interface{} if sindex < len(sarr) { smut = sarr[sindex] } if cindex < len(carr) { cmut = carr[cindex] } // Server insertions go first if IsInsertMutation(smut) { // In the middle of a client skip/delete? Split it if cinside > 0 { self.split(&carr, cindex, cinside) cinside = 0 cindex++ cmut = carr[cindex] } if str, ok := smut.(string); ok { sindex++ if len(str) > 0 { carr.Insert(cindex, NewSkipMutation(len(str))) cindex++ } } else if _, ok := smut.(map[string]interface{}); ok { sindex++ carr.Insert(cindex, NewSkipMutation(1)) cindex++ } else { panic("Only strings allowed inside a text mutation") } continue } // Client insertions go next if IsInsertMutation(cmut) { // In the middle of a server skip/delete? Split it if sinside > 0 { self.split(&sarr, sindex, sinside) sinside = 0 sindex++ smut = sarr[sindex] } if str, ok := cmut.(string); ok { cindex++ if len(str) > 0 { sarr.Insert(sindex, NewSkipMutation(len(str))) sindex++ } } else if _, ok := cmut.(map[string]interface{}); ok { cindex++ sarr.Insert(sindex, NewSkipMutation(1)) sindex++ } else { return os.NewError("Only strings allowed inside a text mutation") } continue } if sindex == len(sarr) && cindex == len(carr) { break } if sindex == len(sarr) || cindex == len(carr) { return os.NewError("The mutations do not have equal length") } if IsDeleteMutation(smut) && IsDeleteMutation(cmut) { sdel := toDeleteMutation(smut).Count() cdel := toDeleteMutation(cmut).Count() del := IntMin(sdel-sinside, cdel-cinside) sindex, sinside = self.shorten(sarr, sindex, sinside, del) cindex, cinside = self.shorten(carr, cindex, cinside, del) } else if IsSkipMutation(smut) && IsSkipMutation(cmut) { sskip := toSkipMutation(smut).Count() cskip := toSkipMutation(cmut).Count() skip := IntMin(sskip-sinside, cskip-cinside) sinside += skip cinside += skip if sinside == sskip { sinside = 0 sindex++ } if cinside == cskip { cinside = 0 cindex++ } } else if IsDeleteMutation(smut) && IsSkipMutation(cmut) { sdel := toDeleteMutation(smut).Count() cskip := toSkipMutation(cmut).Count() count := IntMin(sdel-sinside, cskip-cinside) sinside += count if sinside == sdel { sinside = 0 sindex++ } cindex, cinside = self.shorten(carr, cindex, cinside, count) } else if IsSkipMutation(smut) && IsDeleteMutation(cmut) { sskip := toSkipMutation(smut).Count() cdel := toDeleteMutation(cmut).Count() count := IntMin(sskip-sinside, cdel-cinside) sindex, sinside = self.shorten(sarr, sindex, sinside, count) cinside += count if cinside == cdel { cinside = 0 cindex++ } } else if IsSkipMutation(smut) && IsObjectMutation(cmut) { sskip := toSkipMutation(smut).Count() sinside += 1 cindex++ if sinside == sskip { sinside = 0 sindex++ } } else if IsObjectMutation(smut) && IsSkipMutation(cmut) { cskip := toSkipMutation(cmut).Count() cinside += 1 sindex++ if cinside == cskip { cinside = 0 cindex++ } } else if IsObjectMutation(smut) && IsDeleteMutation(cmut) { sarr.Delete(sindex) cdel := toDeleteMutation(cmut).Count() cinside += 1 if cinside == cdel { cinside = 0 cindex++ } } else if IsDeleteMutation(smut) && IsObjectMutation(cmut) { carr.Delete(cindex) sdel := toDeleteMutation(smut).Count() sinside += 1 if sinside == sdel { sinside = 0 sindex++ } } else { return os.NewError(fmt.Sprintf("Mutation not allowed in a richtext mutation:\n%v %v\n%v %v", smut, IsSkipMutation(smut), cmut, IsSkipMutation(cmut))) } } sobj.SetTextArray(sarr) cobj.SetTextArray(carr) return nil }
func (self DocumentMutation) applyRichTextMutation(obj map[string]interface{}, mutation RichTextMutation, flags uint32) { if flags&CreateIDs == CreateIDs { if _, ok := obj["_id"]; !ok { obj["_id"] = uniqueId() } obj["_rev"] = self.AppliedAtRevision() } var text vec.Vector = obj["text"].([]interface{}) index := 0 inside := 0 for _, m := range mutation.TextArray() { switch { case IsDeleteMutation(m): count := toDeleteMutation(m).Count() for count > 0 { if str, ok := text[index].(string); ok { l := min(len(str)-inside, count) // inside += l // str = str[inside:] str = str[:inside] + str[inside+l:] if len(str) == 0 { text.Delete(index) inside = 0 } else if inside == len(str) { text[index] = str index++ inside = 0 } else { text[index] = str } count -= l } else { inside = 0 text.Delete(index) count-- } } // ** Ended up in the middle between two strings? -> Join them ** if inside == 0 && index < len(text) { if str1, ok := text[index-1].(string); ok { if str2, ok := text[index].(string); ok { text[index-1] = str1 + str2 text.Delete(index) index-- inside = len(str1) continue } } } else if index < len(text)-1 { if str1, ok := text[index].(string); inside == len(str1) && ok { if str2, ok := text[index+1].(string); ok { text[index] = str1 + str2 inside = len(str1) text.Delete(index + 1) continue } } } case IsSkipMutation(m): count := toSkipMutation(m).Count() for count > 0 { if str, ok := text[index].(string); ok { l := min(len(str)-inside, count) inside += l count -= count if inside == len(str) { index++ inside = 0 } } else { inside = 0 index++ count-- } } default: // *** A string? *** if s, ok := m.(string); ok { // Appending to a string? if inside == 0 && index > 0 { if str, ok := text[index-1].(string); ok { text[index-1] = str + s continue } } // End of string? if index == len(text) { text.Insert(index, s) index++ continue } // Prepending/Inserting to an existing string? if str, ok := text[index].(string); ok { // Insert into an existing string ? text[index] = str[0:inside] + s + str[inside:] inside += len(str) continue } // Insert in front of an object text.Insert(index, s) index++ continue } // *** Insert an object *** if index < len(text) && inside > 0 && inside == len(text[index].(string)) { // End of string? inside = 0 index++ } // Middle of a string -> split it if inside > 0 { str := text[index].(string) text.Insert(index+1, str[inside:]) text[index] = str[:inside] text.Insert(index+1, m) inside = 0 index += 2 } else { text.Insert(index, m) index++ } } } obj["text"] = []interface{}(text) }
func parse_forth(dat string, DataStack *vector.Vector) { L := DataStack.Len() switch strings.TrimSpace(string(dat)) { case "": case "<cr>": return case "t": //check the DataStack size using the popped value // if it passes, then the program continues minimum := int(DataStack.Pop().(float32)) if DataStack.Len() < minimum { log.Println("DataStack has not enough minerals (values)") } case ".": log.Println(DataStack.Pop()) case "0SP": DataStack.Cut(0, L) case ".S": log.Println(DataStack) case "2/": DataStack.Push(DataStack.Pop().(float32) / 2) case "2*": DataStack.Push(DataStack.Pop().(float32) * 2) case "2-": DataStack.Push(DataStack.Pop().(float32) - 2) case "2+": DataStack.Push(DataStack.Pop().(float32) + 2) case "1-": DataStack.Push(DataStack.Pop().(float32) - 1) case "1+": DataStack.Push(DataStack.Pop().(float32) + 1) case "DUP": DataStack.Push(DataStack.Last()) case "?DUP": if DataStack.Last().(float32) != 0 { DataStack.Push(DataStack.Last().(float32)) } case "PICK": number := int(DataStack.Pop().(float32)) if number < L { DataStack.Push(DataStack.At(L - 1 - number).(float32)) } else { log.Fatal("picking out of stack not allowed. Stack Length: " + string(L) + ". Selecting: " + string(number) + ".") return } case "TUCK": DataStack.Insert(L-2, int(DataStack.Last().(float32))) case "NIP": DataStack.Delete(L - 2) case "2DROP": DataStack.Pop() DataStack.Pop() case "2DUP": DataStack.Push(DataStack.At(L - 2)) DataStack.Push(DataStack.At(DataStack.Len() - 2)) case "DROP": DataStack.Pop() case "OVER": DataStack.Push(DataStack.At(L - 2)) case "SWAP": l := DataStack.Len() DataStack.Swap(l-2, l-1) case "*": num1 := DataStack.Pop().(float32) num2 := DataStack.Pop().(float32) DataStack.Push(num1 * num2) case "+": num1 := DataStack.Pop().(float32) num2 := DataStack.Pop().(float32) DataStack.Push(num1 + num2) case "-": num1 := DataStack.Pop().(float32) num2 := DataStack.Pop().(float32) DataStack.Push(num2 - num1) case "/": num1 := DataStack.Pop().(float32) num2 := DataStack.Pop().(float32) DataStack.Push(num2 / num1) case "-ROT": DataStack.Swap(L-1, L-2) DataStack.Swap(L-2, L-3) case "ROT": DataStack.Swap(L-3, L-2) DataStack.Swap(L-2, L-1) case "2OVER": DataStack.Push(DataStack.At(L - 4)) DataStack.Push(DataStack.At(DataStack.Len() - 4)) case "2SWAP": DataStack.Swap(L-4, L-2) DataStack.Swap(L-3, L-1) case "EMIT": log.Println(string([]byte{uint8(DataStack.Last().(float32))})) default: val, ok := strconv.Atof32(dat) if ok == nil { DataStack.Push(val) } else { log.Println(ok) log.Fatalln("error, unknown token \"" + dat + "\"") } } }
func (m *Map) Overlay(n *Map, mergeFaces func(interface{}, interface{}) (interface{}, os.Error)) (*Map, os.Error) { o := NewMap() CopiedEdges := new(vector.Vector) m.Edges.Do(func(l interface{}) { e := l.(*Edge) if e.start.Point.Less(e.end.Point) { f, g := NewEdgePair(NewVertex(e.start.Copy()), NewVertex(e.end.Copy())) f.face = e.face g.face = e.twin.face f.Generation = e.Generation g.Generation = e.twin.Generation f.fromMap,g.fromMap = m,m CopiedEdges.Push(f) CopiedEdges.Push(g) } }) n.Edges.Do(func(l interface{}) { e := l.(*Edge) if e.start.Point.Less(e.end.Point) { f, g := NewEdgePair(NewVertex(e.start.Copy()), NewVertex(e.end.Copy())) f.face = e.face g.face = e.twin.face f.Generation = e.Generation g.Generation = e.twin.Generation f.fromMap,g.fromMap = n,n CopiedEdges.Push(f) CopiedEdges.Push(g) } }) Q := new(vector.Vector) T := new(sweepStatus) T.segments = new(vector.Vector) CopiedEdges.Do(func(l interface{}) { e, _ := l.(*Edge) if e.start.Point.Less(e.end.Point) { evt := new(sweepEvent) evt.point = e.start.Point evt.coincidentEdge = e Q.Push(evt) evt = new(sweepEvent) evt.point = e.end.Point evt.coincidentEdge = nil Q.Push(evt) } }) heap.Init(Q) for Q.Len() > 0 { evt, _ := heap.Pop(Q).(*sweepEvent) //fmt.Fprintf(os.Stderr,"event: %v\n",evt.point) L := new(vector.Vector) Lswp := new(sweepStatus) Lswp.segments = L Lswp.sweepLocation = evt.point if evt.coincidentEdge != nil { L.Push(evt.coincidentEdge) } for Q.Len() > 0 && evt.point.Equal(Q.At(0).(*sweepEvent).point) { evt, _ := heap.Pop(Q).(*sweepEvent) if evt.coincidentEdge != nil { L.Push(evt.coincidentEdge) } } sort.Sort(Lswp) for i := 0; i < L.Len()-1; { if L.At(i).(*Edge).Equal(L.At(i + 1).(*Edge)) { L.At(i).(*Edge).newFace = L.At(i + 1).(*Edge).face L.At(i).(*Edge).twin.newFace = L.At(i + 1).(*Edge).twin.face L.At(i).(*Edge).fromMap = nil //no longer from a unique map L.At(i).(*Edge).twin.fromMap = nil //no longer from a unique map L.Delete(i + 1) } else { i++ } } //fmt.Fprintf(os.Stderr,"L: %v\n",L) R := new(vector.Vector) for i := 0; i < T.segments.Len(); { e := T.segments.At(i).(*Edge) if e.end.Point.Equal(evt.point) { R.Push(e) T.segments.Delete(i) } else if e.Line().On(evt.point) { return nil, os.NewError("intersection not at an endpoint") } else { i++ } } // Fill in handle event. You won't need the whole damn thing because // Most of the time you just abort with non-terminal intersection T.sweepLocation = evt.point sort.Sort(T) //fmt.Fprintf(os.Stderr,"status: %v\n",T.segments) if L.Len() == 0 && R.Len() == 0 { return nil, os.NewError("event point with no edges terminal at it " + evt.point.String() + fmt.Sprintf("current status: %v", T.segments)) } else if L.Len() == 0 { above := sort.Search(T.Len(), func(i int) bool { return T.segments.At(i).(*Edge).Line().Below(evt.point) }) //fmt.Fprintf(os.Stderr,"Testing status point, no new edge. above: %v, Len: %v\n",above,T.Len()) if 0 < above && above < T.Len() { sa := T.segments.At(above).(*Edge) sb := T.segments.At(above - 1).(*Edge) cross, _, _ := sb.Line().IntersectAsFloats(sa.Line()) if cross && !sa.Coterminal(sb) { return nil, os.NewError("intersection not at an endpoint") } } } else { aboveL := sort.Search(T.Len(), func(i int) bool { return L.Last().(*Edge).Line().LessAt(T.segments.At(i).(*Edge).Line(), evt.point) }) belowL := aboveL - 1 //fmt.Fprintf(os.Stderr,"Testing status point, new edges. above: %v, Len: %v\n",aboveL,T.Len()) if 0 <= belowL && belowL < T.Len() { sa := L.At(0).(*Edge) sb := T.segments.At(belowL).(*Edge) cross, _, _ := sa.Line().IntersectAsFloats(sb.Line()) if cross && !sa.Coterminal(sb) { return nil, os.NewError("intersection not at an endpoint") } } if aboveL < T.Len() { sa := T.segments.At(aboveL).(*Edge) sb := L.Last().(*Edge) cross, _, _ := sa.Line().IntersectAsFloats(sb.Line()) if cross && !sa.Coterminal(sb) { return nil, os.NewError("intersection not at an endpoint") } } } // This is the barrier between preparing the new vertex (below) and determining if the new vertex is good // Setting up edges nv := NewVertex(evt.point.Copy()) R.Do(func(r interface{}) { nv.OutgoingEdges.Push(r.(*Edge).twin) r.(*Edge).end = nv r.(*Edge).twin.start = nv o.Edges.Push(r) o.Edges.Push(r.(*Edge).twin) }) L.Do(func(l interface{}) { l.(*Edge).start = nv l.(*Edge).twin.end = nv nv.OutgoingEdges.Push(l) }) sort.Sort(nv.OutgoingEdges) for i := 0; i < nv.OutgoingEdges.Len(); i++ { e := nv.OutgoingEdges.At(i).(*Edge) f := nv.OutgoingEdges.At((i + 1) % nv.OutgoingEdges.Len()).(*Edge) e.prev = f.twin f.twin.next = e } // Setting up nv's inFace. // A new vertex only has relevant inFace information when it comes exclusively from one map, we first determine that fromOneMap := true fromMap := nv.OutgoingEdges.At(0).(*Edge).fromMap nv.OutgoingEdges.Do(func(e interface{}) { fromOneMap = fromOneMap && e.(*Edge).fromMap == fromMap && e.(*Edge).fromMap != nil }) // we're from one map, got to find the elements in T from the other map above and below us if fromOneMap { //fmt.Fprintf(os.Stderr,"from one map, finding face of other\n") TfromOtherMap := new(sweepStatus) TfromOtherMap.sweepLocation = evt.point TfromOtherMap.segments = new(vector.Vector) T.segments.Do(func(e interface{}) { if e.(*Edge).fromMap != fromMap { TfromOtherMap.segments.Push(e) } }) sort.Sort(TfromOtherMap) above := sort.Search(TfromOtherMap.Len(), func(i int) bool { return TfromOtherMap.segments.At(i).(*Edge).Line().Below(evt.point) }) if 0 < above && above < TfromOtherMap.Len() { //fmt.Fprintf(os.Stderr,"Testing status point, looking for vertex in face. above: %v, Len: %v\n",above,TfromOtherMap.Len()) sb := TfromOtherMap.segments.At(above - 1).(*Edge) if sb.fromMap == nil { if sb.face.fromMap == fromMap { nv.inFace = sb.newFace } else { nv.inFace = sb.face } } else { nv.inFace = sb.face } } else if TfromOtherMap.Len() == 0 { nv.inFace = nil // completely outside other map, not our problem } else if above == 0 { sa := TfromOtherMap.segments.At(above).(*Edge) if sa.twin.fromMap == nil { if sa.twin.face.fromMap == fromMap { nv.inFace = sa.twin.newFace } else { nv.inFace = sa.twin.face } } else { nv.inFace = sa.twin.face } } else if above == TfromOtherMap.Len() { sb := TfromOtherMap.segments.At(above - 1).(*Edge) nv.inFace = sb.face if sb.fromMap == nil { if sb.face.fromMap == fromMap { nv.inFace = sb.newFace } else { nv.inFace = sb.face } } else { nv.inFace = sb.face } } } else { nv.inFace = nil //we're not from one map, this vertex happens at the overlay, edges have complete face information. } o.Verticies.Push(nv) // Vertex done, add any new edges to the sweep line. L.Do(func(l interface{}) { T.segments.Push(l) }) } var leFuck string for i := 0; i < o.Edges.Len(); i++ { e, _ := o.Edges.At(i).(*Edge) if e.visited { continue } //fmt.Fprintf(os.Stderr,"found a face containing: %v,",e.start) F := new(Face) F.boundary = e F.fromMap = o e.visited = true oldFaces := make(map[*Face]int) //fmt.Fprintf(os.Stderr,"%v: ",e.start) if e.face != nil { //fmt.Fprintf(os.Stderr,"f %v ",e.face.Value) oldFaces[e.face]++ } if e.newFace != nil { //fmt.Fprintf(os.Stderr,"nf %v ",e.newFace.Value) oldFaces[e.newFace]++ } if e.start.inFace != nil { //fmt.Fprintf(os.Stderr,"if %v ",e.start.inFace.Value) oldFaces[e.start.inFace]++ } if e.face == nil && e.newFace == nil { panic("the edge without a face\n") } e.face = F for f := e.Next(); f != e; f = f.Next() { //fmt.Fprintf(os.Stderr,"%v: ",f.start) f.visited = true if f.face != nil { //fmt.Fprintf(os.Stderr,"f %v ",f.face.Value) oldFaces[f.face]++ } if f.newFace != nil { //fmt.Fprintf(os.Stderr,"nf %v ",f.newFace.Value) oldFaces[f.newFace]++ } if f.start.inFace != nil { //fmt.Fprintf(os.Stderr,"if %v ",f.start.inFace.Value) oldFaces[f.start.inFace]++ } //fmt.Fprintf(os.Stderr,",") f.face = F } //os.Stderr.WriteString("\n") //fmt.Fprintf(os.Stderr,"%v old faces\n",len(oldFaces)) if len(oldFaces) > 2 { leFuck += fmt.Sprintf("%v faces overlapping a new face, input must have been malformed, maps m: %p n: %p\n", len(oldFaces), m, n) for f, _ := range oldFaces { leFuck = leFuck + fmt.Sprintf("face %p from: %p containing: %v\n", f, f.fromMap, f.Value) } //os.Stderr.WriteString(leFuck) } else if len(oldFaces) == 0 { panic(fmt.Sprintf("No old faces. e: %v, e.face: %+v, maps: m: %p n: %p o: %p\n", e, e.face, m, n, o)) } var mFace, nFace *Face for f, _ := range oldFaces { if f.fromMap == m { mFace = f } else { nFace = f } } if mFace != nil && nFace != nil { v, ok := mergeFaces(mFace.Value, nFace.Value) if ok != nil { return nil, ok } if mFace.Type != "" { F.Type = mFace.Type } else if nFace.Type != "" { F.Type = nFace.Type } F.Value = v } else if mFace != nil { F.Value = mFace.Value F.Type = mFace.Type } else if nFace != nil { F.Value = nFace.Value F.Type = nFace.Type } else { panic(fmt.Sprintf("face didn't come from an mFace or an nFace, pointers m: %v n: %v o: %v face: %v", m, n, o, e.face)) } o.Faces.Push(F) } if leFuck != "" { return o, os.NewError(leFuck) } o.Init() return o, nil }
// returns a topologically sorted vector of Node's func TopSort(dag vec.Vector, s byte) vec.Vector { sortDag := new(vec.Vector) tempDag := new(vec.Vector) destDag := new(vec.Vector) setVec := new(vec.Vector) for i := 0; i < dag.Len(); i++ { tempDag.Push((dag.At(i).(*par.Node)).Copy()) destDag.Push((dag.At(i).(*par.Node)).Copy()) } // t-level gets regular top sort if s == 't' { setVec.Push(tempDag.At(0)) destDag.Delete(0) for i := setVec.Len(); i > 0; i = setVec.Len() { n := (setVec.Pop().(*par.Node)).Copy() sortDag.Push(n) for j := 0; j < (n.Cl).Len(); j++ { c := ((n.Cl).At(j).(*par.Rel)).Id for k := 0; k < destDag.Len(); k++ { if (destDag.At(k).(*par.Node)).Id == c { for l := 0; l < (destDag.At(k).(*par.Node)).Pl.Len(); l++ { if (destDag.At(k).(*par.Node)).Pl.At(l).(*par.Rel).Id == n.Id { (destDag.At(k).(*par.Node)).Pl.Delete(l) break } } } } } for j := 0; j < destDag.Len(); j++ { if (destDag.At(j).(*par.Node)).Pl.Len() == 0 { c := (destDag.At(j).(*par.Node)).Id for k := 0; k < tempDag.Len(); k++ { if (tempDag.At(k).(*par.Node)).Id == c { setVec.Push(tempDag.At(k)) break } } destDag.Delete(j) j-- } } } // b-level gets reverse top sort } else if s == 'b' { setVec.Push(tempDag.At(tempDag.Len() - 1)) destDag.Delete(destDag.Len() - 1) for i := setVec.Len(); i > 0; i = setVec.Len() { n := (setVec.Pop().(*par.Node)).Copy() sortDag.Push(n) for j := 0; j < (n.Pl).Len(); j++ { c := ((n.Pl).At(j).(*par.Rel)).Id for k := 0; k < destDag.Len(); k++ { if (destDag.At(k).(*par.Node)).Id == c { for l := 0; l < (destDag.At(k).(*par.Node)).Cl.Len(); l++ { if (destDag.At(k).(*par.Node)).Cl.At(l).(*par.Rel).Id == n.Id { (destDag.At(k).(*par.Node)).Cl.Delete(l) break } } } } } for j := 0; j < destDag.Len(); j++ { if (destDag.At(j).(*par.Node)).Cl.Len() == 0 { c := (destDag.At(j).(*par.Node)).Id for k := 0; k < tempDag.Len(); k++ { if (tempDag.At(k).(*par.Node)).Id == c { setVec.Push(tempDag.At(k)) break } } destDag.Delete(j) j-- } } } } else { fmt.Printf("Error") } return sortDag.Copy() }