//min, max 값 적용 private void buttonApply_Click(object sender, RoutedEventArgs e) { float min, max; NumericTreeViewItem parent = (treeView.SelectedItem as NumericTreeViewItem).owner; if (float.TryParse(textBoxMin.Text, out min) && float.TryParse(textBoxMax.Text, out max)) { if (min > max) { MessageBox.Show("최소값이 최대값보다 큽니다."); } else if ((parent != null) && (min < parent.min || max > parent.max)) { MessageBox.Show("상위 노드의 범위를 벗어납니다."); } else { //적용 (treeView.SelectedItem as NumericTreeViewItem).UpdateInfo(min, max, (bool)checkBoxMin.IsChecked, (bool)checkBoxMax.IsChecked); checkRange(); //적용 후에 범위 에러 체크 } } else { MessageBox.Show("잘못된 값을 입력하셨습니다."); } }
private void LoadNode(XmlNode parent, ItemCollection items, NumericTreeViewItem parentItem) { foreach (XmlNode child in parent) { if (child.NodeType == XmlNodeType.Element && child.Name == "node") { string tmp = child.Attributes["range"].Value; bool withMin = tmp.Substring(0, 1) == "["; bool withMax = tmp.Substring(tmp.Length - 1, 1) == "]"; string tmp2 = tmp.Substring(1, tmp.Length - 2); int tmpIndex = tmp2.IndexOf('-'); float min, max; float.TryParse(tmp2.Substring(0, tmpIndex), out min); float.TryParse(tmp2.Substring(tmpIndex + 1), out max); NumericTreeViewItem c = new NumericTreeViewItem(0, 0, parentItem); c.UpdateInfo(min, max, withMin, withMax); items.Add(c); if (child.HasChildNodes) { LoadNode(child, c.Items, c); } } } }
//데이터 값에 따른 절반 나누기 recursive private void staticAdd(int height, NumericTreeViewItem root, bool isHybrid, bool isFloat = false) { float midValue = isFloat ? (root.min + root.max) / 2 : (int)((root.min + root.max) / 2); if (root.min != midValue) { root.Items.Add(new NumericTreeViewItem(0, 0, root) { IsExpanded = true }); root.Items.Add(new NumericTreeViewItem(0, 0, root) { IsExpanded = true }); (root.Items[0] as NumericTreeViewItem).UpdateInfo(root.min, midValue, root.includeMin, false); (root.Items[1] as NumericTreeViewItem).UpdateInfo(midValue, root.max, true, root.includeMax); root.IsExpanded = true; //확장 bool hasChild = true; //hybrid method에서, 자식이 있는지 삭제되었는지 if (isHybrid) { //준식별자의 경우: 범위 내 값이 k개 미만인 값이 존재한다면 하위 노드 필요 없음 bool caseA = (dm.GetAttrList()[index] as Attr).type == Attr.attrType.qi && (root.Items[0] as NumericTreeViewItem).count < dm.k; bool caseB = (dm.GetAttrList()[index] as Attr).type == Attr.attrType.qi && (root.Items[1] as NumericTreeViewItem).count < dm.k; //범위 내 값이 0개인 값이 존재한다면 하위 노드 필요 없음 bool caseC = (root.Items[0] as NumericTreeViewItem).count == 0; bool caseD = (root.Items[1] as NumericTreeViewItem).count == 0; if (caseA || caseB || caseC || caseD) { root.Items.RemoveAt(1); root.Items.RemoveAt(0); hasChild = false; } } if (hasChild && height > 0) { staticAdd(height - 1, root.Items[0] as NumericTreeViewItem, isHybrid); staticAdd(height - 1, root.Items[1] as NumericTreeViewItem, isHybrid); } } else { maxDepth = maxDepth > height ? maxDepth : height; //perfect binary를 벗어나는 height를 저장 } }
//하위 노드 생성 private void buttonAdd_Click(object sender, RoutedEventArgs e) { NumericTreeViewItem parent = (treeView.SelectedItem as NumericTreeViewItem); parent.Items.Add(new NumericTreeViewItem(parent.min, parent.max, parent) { IsExpanded = true }); parent.IsExpanded = true; //확장 checkRange(); //확장 후에 범위 에러 체크 }
//선택 노드 삭제 private void buttonDelete_Click(object sender, RoutedEventArgs e) { if ((treeView.SelectedItem as NumericTreeViewItem).Items.Count == 0) { NumericTreeViewItem parent = (treeView.SelectedItem as NumericTreeViewItem).owner; parent.Items.Remove(treeView.SelectedItem); parent.IsSelected = true; //삭제 후에 부모 노드 선택 checkRange(); //삭제 후에 범위 에러 체크 } else { MessageBox.Show("먼저 모든 하위노드를 삭제 해야합니다."); } }
//루트 라운딩 private void roundRoot() { bool minIsZero = list.Min() == 0; bool maxIsZero = list.Max() == 0; int minDigit = minIsZero ? 1 : (int)Math.Floor(Math.Log10(Math.Abs(list.Min()))) + 1; //최소값의 자리수 int maxDigit = maxIsZero ? 1 : (int)Math.Floor(Math.Log10(Math.Abs(list.Max()))) + 1; //최대값의 자리수 NumericTreeViewItem root = treeView.Items[0] as NumericTreeViewItem; float tmpRootMin = minIsZero ? 0 : (float)Math.Pow(10, minDigit - 1); int tmpMaxcoef = (int)(Math.Abs(list.Max()) / Math.Pow(10, maxDigit - 1)) + 1; float tmpRootMax = maxIsZero ? 0 : (float)(tmpMaxcoef * Math.Pow(10, maxDigit - 1)); root.UpdateInfo(tmpRootMin, tmpRootMax, true, false); //루트노드 업데이트 //노드의 min, max 로드 textBoxMin.Text = root.min.ToString(); textBoxMax.Text = root.max.ToString(); }
//데이터 값에 따르고 분포를 고려하는 절반 나누기 recursive private void heuristicAdd(int height, NumericTreeViewItem root, bool isFloat = false) { float midValue = isFloat ? (root.min + root.max) / 2 : (int)((root.min + root.max) / 2); if (root.min != midValue) { root.Items.Add(new NumericTreeViewItem(0, 0, root) { IsExpanded = true }); root.Items.Add(new NumericTreeViewItem(0, 0, root) { IsExpanded = true }); (root.Items[0] as NumericTreeViewItem).UpdateInfo(root.min, midValue, root.includeMin, false); (root.Items[1] as NumericTreeViewItem).UpdateInfo(midValue, root.max, true, root.includeMax); //데이터 분포 체크 float dif = ((float)(root.Items[0] as NumericTreeViewItem).count - (root.Items[1] as NumericTreeViewItem).count) / root.count; if (dif > 0.3) { int coef = dif > 0.7 ? (dif > 0.8 ? 8 : 5) : (dif > 0.5 ? 4 : 3); midValue = isFloat ? root.min + (root.max - root.min) / coef : (int)(root.min + (root.max - root.min) / coef); (root.Items[0] as NumericTreeViewItem).UpdateInfo(root.min, midValue, root.includeMin, false); (root.Items[1] as NumericTreeViewItem).UpdateInfo(midValue, root.max, true, root.includeMax); } else if (dif < -0.3) { int coef = dif < -0.7 ? (dif < -0.8 ? 8 : 5) : (dif < -0.5 ? 4 : 3); midValue = isFloat ? root.max - (root.max - root.min) / coef : (int)(root.max - (root.max - root.min) / coef); (root.Items[0] as NumericTreeViewItem).UpdateInfo(root.min, midValue, root.includeMin, false); (root.Items[1] as NumericTreeViewItem).UpdateInfo(midValue, root.max, true, root.includeMax); } root.IsExpanded = true; //확장 //준식별자의 경우: 범위 내 값이 k개 미만인 값이 존재한다면 하위 노드 필요 없음 bool caseA = (dm.GetAttrList()[index] as Attr).type == Attr.attrType.qi && (root.Items[0] as NumericTreeViewItem).count < dm.k; bool caseB = (dm.GetAttrList()[index] as Attr).type == Attr.attrType.qi && (root.Items[1] as NumericTreeViewItem).count < dm.k; //범위 내 값이 0개인 값이 존재한다면 하위 노드 필요 없음 bool caseC = (root.Items[0] as NumericTreeViewItem).count == 0; bool caseD = (root.Items[1] as NumericTreeViewItem).count == 0; if (caseA || caseB || caseC || caseD) { root.Items.RemoveAt(1); root.Items.RemoveAt(0); } else if (height > 0) { heuristicAdd(height - 1, root.Items[0] as NumericTreeViewItem); heuristicAdd(height - 1, root.Items[1] as NumericTreeViewItem); } } }
//데이터 분포에 따른 절반 나누기 recursive private void dynamicAdd(int height, NumericTreeViewItem root, int firstIndex, int lastIndex) { root.Items.Add(new NumericTreeViewItem(0, 0, root) { IsExpanded = true }); root.Items.Add(new NumericTreeViewItem(0, 0, root) { IsExpanded = true }); int midIndex = (firstIndex + lastIndex) / 2; //중간 인덱스 //최소와 중간이 같은 경우, 중간 인덱스를 뒤로 옮긴다. if (root.min == list[midIndex]) { for (int i = midIndex; i < lastIndex; ++i) { if (list[i] > list[midIndex]) { midIndex = i; break; } } } //최대와 중간이 같은 경우, 중간 인덱스를 뒤로 옮긴다. else if (root.max == list[midIndex]) { for (int i = midIndex; i > firstIndex; --i) { if (list[i] < list[midIndex]) { midIndex = i; break; } } } (root.Items[0] as NumericTreeViewItem).UpdateInfo(root.min, list[midIndex], root.includeMin, false); (root.Items[1] as NumericTreeViewItem).UpdateInfo(list[midIndex], root.max, true, root.includeMax); root.IsExpanded = true; //확장 //준식별자의 경우: 범위 내 값이 k개 미만인 값이 존재한다면 하위 노드 필요 없음 bool caseA = (dm.GetAttrList()[index] as Attr).type == Attr.attrType.qi && (root.Items[0] as NumericTreeViewItem).count < dm.k; bool caseB = (dm.GetAttrList()[index] as Attr).type == Attr.attrType.qi && (root.Items[1] as NumericTreeViewItem).count < dm.k; //범위 내 값이 0개인 값이 존재한다면 하위 노드 필요 없음 bool caseC = (root.Items[0] as NumericTreeViewItem).count == 0; bool caseD = (root.Items[1] as NumericTreeViewItem).count == 0; if (caseA || caseB || caseC || caseD) { root.Items.RemoveAt(1); root.Items.RemoveAt(0); } else if (height > 0) { dynamicAdd(height - 1, root.Items[0] as NumericTreeViewItem, firstIndex, midIndex); dynamicAdd(height - 1, root.Items[1] as NumericTreeViewItem, midIndex, lastIndex); } }
public string range; //xml 기록용 public NumericTreeViewItem(float min = 0, float max = 0, NumericTreeViewItem owner = null) { UpdateInfo(min, max, true, true); IsSelected = true; this.owner = owner; }