Skip to content

Commit

Permalink
path view sorting algorithm with iterations tested and validated -- u…
Browse files Browse the repository at this point in the history
…ncrosses wires.. use style class to match so you can really validate all the different types of paths in a complex network
  • Loading branch information
rcoreilly committed Aug 28, 2024
1 parent db5942c commit 2e7f412
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 27 deletions.
2 changes: 1 addition & 1 deletion netview/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func (sw *Scene) WidgetTooltip(pos image.Point) (string, image.Point) {
pt := sw.PathAtPoint(lpos)
if pt != nil {
pe := pt.AsEmer()
tt := "[Click to edit] " + pe.Name + " " + pt.TypeName()
tt := "[Click to edit] " + pe.Name + " " + pt.StyleClass()
if pe.Doc != "" {
tt += ": " + pe.Doc
}
Expand Down
8 changes: 5 additions & 3 deletions netview/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@ type Options struct { //types:add
// whether to display the pathways between layers as arrows
Paths bool

// path type name(s) to display (space separated),
// for path arrows, and when there are multiple pathways from the same layer.
// path type name(s) to display (space separated), for path arrows,
// and when there are multiple pathways from the same layer.
// For arrows, uses the style class names to match, which includes type name
// and other factors.
// Uses case insensitive contains logic for each name.
PathType string

// width of the path arrows, in normalized units
PathWidth float32 `default:"0.002"`
PathWidth float32 `min:"0.0001" max:".05" step:"0.001" default:"0.002"`

// raster plot parameters
Raster RasterOptions `display:"inline"`
Expand Down
99 changes: 76 additions & 23 deletions netview/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
package netview

import (
"cmp"
"fmt"
"math"
"slices"
"strings"

"cogentcore.org/core/base/errors"
Expand Down Expand Up @@ -230,7 +232,7 @@ func (nv *NetView) UpdatePaths() {
npt := sl.NumSendPaths()
for pi := range npt {
pt := sl.SendPath(pi)
if !nv.pathTypeNameMatch(pt.TypeName()) {
if !nv.pathTypeNameMatch(pt.StyleClass()) {
continue
}
rb := pt.RecvLayer().AsEmer()
Expand All @@ -256,23 +258,38 @@ func (nv *NetView) UpdatePaths() {
}
}
i := pdIdx(minData.sSide, minData.cat)
minData.sIdx = len(slayData.paths[i])
slayData.paths[i] = append(slayData.paths[i], minData)
for _, pd := range slayData.paths[i] {
pd.sN = len(slayData.paths[i])
}
rlayData := &layPaths[rb.Index]
i = pdIdx(minData.rSide, minData.cat)
minData.rIdx = len(rlayData.paths[i])
rlayData.paths[i] = append(rlayData.paths[i], minData)
for _, pd := range rlayData.paths[i] {
pd.rN = len(rlayData.paths[i])
}
}
for li := range nlay {
ly := nv.Net.EmerLayer(li)
lb := ly.AsEmer()
layData := &layPaths[lb.Index]
for side := range 4 {
for cat := range 3 {
pidx := pdIdx(side, cat)
pths := layData.paths[pidx]
npt := len(pths)
if npt == 0 {
continue
}
for pi, pd := range pths {
if pd.path.RecvLayer() == ly {
pd.rIdx = pi
pd.rN = npt
} else {
pd.sIdx = pi
pd.sN = npt
}
}
}
}
}
// now we have the full set of data, sort positions
// orderChanged := false
for range 1 {
for range 10 { // 10 seems to get as much as 100 on complex networks
for li := range nlay {
ly := nv.Net.EmerLayer(li)
lb := ly.AsEmer()
Expand All @@ -286,17 +303,52 @@ func (nv *NetView) UpdatePaths() {
continue
}
for _, pd := range pths {
if pd.path.RecvLayer() != ly {
continue
if pd.path.RecvLayer() == ly {
setPathPos(pd)
}
}
}
}
}
orderChanged := false
for li := range nlay {
ly := nv.Net.EmerLayer(li)
lb := ly.AsEmer()
layData := &layPaths[lb.Index]
for side := range 4 {
for cat := range 3 {
pidx := pdIdx(side, cat)
pths := layData.paths[pidx]
npt := len(pths)
if npt == 0 {
continue
}
slices.SortStableFunc(pths, func(a, b *pathData) int {
if a.path.RecvLayer() == ly {
return -cmp.Compare(a.sPos.Dim(sideDims[a.rSide]), b.sPos.Dim(sideDims[b.rSide]))
} else {
return -cmp.Compare(a.rPos.Dim(sideDims[a.sSide]), b.rPos.Dim(sideDims[b.sSide]))
}
})
for pi, pd := range pths {
if pd.path.RecvLayer() == ly {
if pi != pd.rIdx {
orderChanged = true
pd.rIdx = pi
}
} else {
if pi != pd.sIdx {
orderChanged = true
pd.sIdx = pi
}
}
setPathPos(pd)
}
// slices.SortStableFunc(pths, func(a, b *pathData) int {
// return -cmp.Compare(a.spos.Dim(sideDims[rSide]), b.spos.Dim(sideDims[rSide]))
// })
}
}
}
if !orderChanged {
break
}
}

// final render
Expand Down Expand Up @@ -350,21 +402,22 @@ func (nv *NetView) UpdatePaths() {
sfgp.SetName(pb.Name)
sfp := xyz.NewSolid(sfgp).SetMesh(spm).SetColor(clr)
sfp.SetName(pb.Name)
sfp.Pose.Pos = laySidePos(lb, selfSide, 1, pi, npt, 0.2)
sfp.Pose.Pos = laySidePos(lb, selfSide, 1, pi, npt, 0)
}
}
}

func (nv *NetView) pathTypeNameMatch(ptyp string) bool {
func (nv *NetView) pathTypeNameMatch(pcls string) bool {
if len(nv.Options.PathType) == 0 {
return true
}
ptyp = strings.ToLower(ptyp)
fs := strings.Fields(nv.Options.PathType)
cls := strings.Fields(strings.ToLower(pcls))
fs := strings.Fields(strings.ToLower(nv.Options.PathType))
for _, pt := range fs {
pt = strings.ToLower(pt)
if strings.Contains(ptyp, pt) {
return true
for _, cl := range cls {
if strings.Contains(cl, pt) {
return true
}
}
}
return false
Expand Down

0 comments on commit 2e7f412

Please sign in to comment.