/// <summary> /// 由点集计算平面法向量 /// </summary> /// <param name="pts">点集</param> /// <returns></returns> public static bool CalcNormalVector(sg_Vector3[] pts, out sg_Vector3 n) { n = null; int iCount = pts.Length; if (iCount < 3) { return(false); } sg_Vector3 pt1 = pts[0]; sg_Vector3 pt2 = null; for (int i = 1; i < iCount; i++) { pt2 = pts[i]; if (sg_math.isZero(pt2.DistTo(pt1))) { pt2 = null; } else { break; } } if (pt2 == null) { return(false); } sg_Vector3 v1 = pt2 - pt1; sg_Vector3 v2 = null; for (int i = 1; i < iCount; i++) { var pt3 = pts[i]; if (sg_math.isZero(pt3.DistTo(pt1)) || sg_math.isZero(pt3.DistTo(pt2))) { pt3 = null; continue; } v2 = pt3 - pt1; if (!v2.isParallel(v1)) { break; } v2 = null; } if (v2 == null) { return(false); } n = v1.crossMul(v2); // 如果与Z轴夹角大于90度 则反向 if (n.getInterAngle(new sg_Vector3(0, 0, 1)) > 90) { n.reverse(); } return(true); }
/// <summary> /// 像素坐标转成局部坐标 /// </summary> /// <param name="p">像素坐标</param> /// <returns></returns> private sg_Vector3 Trans_XSToJB(Point p) { double jBx = p.X * doc.recWidth / widthScreen; double jBy = (p.Y - toolbar.Size.Height) * doc.recHeight / heightScreen; sg_Vector3 jB = new sg_Vector3(jBx, jBy, 0); return(jB); }
private void buttonXSave_Click(object sender, EventArgs e) { try { ctrlPtsKW = new sg_Vector3(double.Parse(kwX.Text.ToString()), double.Parse(kwY.Text.ToString()), double.Parse(kwZ.Text.ToString())); this.DialogResult = DialogResult.OK; } catch { MessageBox.Show("数字格式不正确"); return; } }
/// <summary> /// 计算大地坐标系下的一个点,在当前开挖坐标系的中坐标 /// </summary> /// <param name="coor">开挖坐标系</param> /// <param name="p">大地坐标系下的一个点</param> /// <returns></returns> public static sg_Vector3 ConverToThisSys(sg_Vector3[] coor, sg_Vector3 p) { sg_Vector3 sysX = coor[1] - coor[0]; // 横坐标向量 sg_Vector3 sysY = coor[2] - coor[0]; //纵坐标向量 sg_Vector3 _p = p - coor[0]; double yDirection = sysX.x * sysY.y - sysY.x * sysX.y; double distance = Math.Sqrt(_p.x * _p.x + _p.y * _p.y); double fenMu = Math.Sqrt(sysX.x * sysX.x + sysX.y * sysX.y) * Math.Sqrt(_p.x * _p.x + _p.y * _p.y); double fenZi1 = sysX.x * _p.x + sysX.y * _p.y; double cosValue1 = fenZi1 / fenMu; double xValue = cosValue1 * distance;// 点的横坐标 double yValue; double sinValue1 = Math.Sqrt(1 - cosValue1 * cosValue1); if (cosValue1 >= 0) { // 坐标系中的y轴如果与x轴是逆时针旋转后的成90度,则计算出的该点y坐标要乘-1 if (sysX.x * _p.y - sysX.y * _p.x >= 0) { yValue = sinValue1 * distance; } else { yValue = -sinValue1 * distance; } } else { // 坐标系中的y轴如果与x轴是逆时针旋转后的成90度,则计算出的该点y坐标要乘-1 if (-sysX.x * _p.y - -sysX.y * _p.x <= 0) { yValue = sinValue1 * distance; } else { yValue = -sinValue1 * distance; } } double yDirction = sysX.x * sysY.y - sysY.x * sysX.y; if (yDirction < 0) { yValue = -1 * yValue; } return(new sg_Vector3(xValue, yValue, _p.z)); }
/// <summary> /// 得到数据来源的局部编录坐标系 (还未实现) /// </summary> /// <param name="id"></param> /// <param name="pts"></param> /// <returns></returns> public static bool get_JBBLZBPt3(string id, out sg_Vector3[] pts) { pts = new sg_Vector3[3]; DataTable dt = BLHTBLL.GetXDMXJDZB(id); if (dt.Rows.Count == 0) { return(false); } // 待实现 return(true); }
/// <summary> /// 构造函数 /// </summary> /// <param name="orgin">开挖坐标原点</param> /// <param name="H_Point">开挖坐标X(横)坐标轴上一点</param> /// <param name="V_Point">开挖坐标Y(纵)坐标轴正方向侧的任意点</param> public M1(sg_Vector3 orgin, sg_Vector3 H_Point, sg_Vector3 V_Point) { sg_Vector3 newZ = new sg_Vector3(0, 0, 1); sg_Vector3 newX = H_Point - orgin; sg_Vector3 YR1 = V_Point - orgin; sg_Vector3 newY = newZ.crossMul(newX); double angle = Math.Abs(YR1.getInterAngle(newY));// 两向量夹角 if (angle > 90) { newY.reverse(); } mTrans = new sg_Transformation(newZ, newX, newY, orgin); }
/// <summary> /// 构造函数 /// </summary> /// <param name="pt1">局部编录坐标控制点1</param> /// <param name="pt2">局部编录坐标控制点2</param> /// <param name="pt3">局部编录坐标控制点3</param> public M3(sg_Vector3 pt1, sg_Vector3 pt2, sg_Vector3 pt3, double xOffset = 0.0, double yOffset = 0.0) { ctrlPts = new sg_Vector3[3]; ctrlPts[0] = pt1; ctrlPts[1] = pt2; ctrlPts[2] = pt3; sg_Vector3 v12 = pt2 - pt1; sg_Vector3 v13 = pt3 - pt1; if (v12.isParallel(v13)) { } else { } sg_Vector3 newZ = new sg_Vector3(0, 0, 1); sg_Vector3 newX = pt2 - pt1; sg_Vector3 YR1 = pt3 - pt1; sg_Vector3 newY = newZ.crossMul(newX); double angle = Math.Abs(YR1.getInterAngle(newY)); // 两向量夹角 if (angle > 90) { newY.reverse(); } sg_Vector3 nLocalXoY = v12.crossMul(v13); // 局部编录面法向量 sg_Vector3 nGeodeticXoY = new sg_Vector3(0, 0, 1); // 大地坐标XoY面法向量 sg_Vector3 nx = nLocalXoY.isParallel(nGeodeticXoY) ? new sg_Vector3(1, 0, 0) : nLocalXoY.crossMul(nGeodeticXoY); sg_Vector3 ny = nLocalXoY.isParallel(nGeodeticXoY) ? new sg_Vector3(0, 1, 0) : nLocalXoY.crossMul(nx); sg_Vector3 nz = nx.crossMul(ny); sg_Vector3 origin = new sg_Vector3(pt1.x + xOffset, pt1.y + yOffset, pt1.z); this.mTrans = new sg_Transformation(nz, nx, ny, origin); IsValid = true; }
/// <summary> /// 判断点集是否共线 /// </summary> /// <param name="pts">点集</param> /// <returns></returns> public static bool IsPtsCollinear(sg_Vector3[] pts) { int iCount = pts.Length; // 若点集中的点数小于3个,判定共线 if (iCount < 3) { return(true); } // 获取第一个非零辅助向量 sg_Vector3 v1 = pts[1] - pts[0]; if (v1.isZero()) { for (int i = 2; i < iCount; ++i) { v1 = pts[i] - pts[0]; if (!v1.isZero()) { break; } } } // 获取第二个非零辅助向量 for (int j = 1; j < iCount; ++j) { var v2 = pts[j] - pts[0]; if (v2.isZero()) { continue; } // 若两个非零辅助向量不平行,则判定不共线 if (!v1.isParallel(v2)) { return(false); } } // 若两个非零辅助向量始终平行,则判定共线 return(true); }
/// <summary> /// 得到数据来源的局部编录坐标系 (还未实现) /// </summary> /// <param name="id"></param> /// <param name="pts"></param> /// <returns></returns> public static bool get_JBBLZBPt3(string id, IGPoint[] slopePts, out sg_Vector3[] pts) { //边坡的 3 个点 sg_Vector3[] slopeCtrl = new sg_Vector3[3]; sg_Vector3[] sysPts = new sg_Vector3[3]; pts = new sg_Vector3[3]; get_KWZBPt3(id, out sysPts); //获取 开挖坐标的三个点 //sg_Vector3 sysX = sysPts[1] - sysPts[0]; // 横坐标向量 //sg_Vector3 sysY = sysPts[2] - sysPts[0];//纵坐标向量 //判断 y 轴与 x 轴的相对位置 //double yDirection = sysX.x * sysY.y - sysY.x * sysX.y; for (int i = 0; i < 3; i++) { slopeCtrl[i] = new sg_Vector3(slopePts[i].X, slopePts[i].Y, slopePts[i].Z); pts[i] = ConverToThisSys(sysPts, slopeCtrl[i]); } return(true); }
private void buttonXSave_Click(object sender, EventArgs e) { if (chooseCtrlPts.Text == "控制点1") { ctrlPtsKW = new sg_Vector3(pKWInThis[0].x, pKWInThis[0].y, pKWInThis[0].z); DialogResult = DialogResult.OK; } else if (chooseCtrlPts.Text == "控制点2") { ctrlPtsKW = new sg_Vector3(pKWInThis[1].x, pKWInThis[1].y, pKWInThis[1].z); DialogResult = DialogResult.OK; } else if (chooseCtrlPts.Text == "控制点3") { ctrlPtsKW = new sg_Vector3(pKWInThis[2].x, pKWInThis[2].y, pKWInThis[2].z); DialogResult = DialogResult.OK; } else { MessageBox.Show("请选择控制点"); return; } }
/// <summary> /// 得到数据来源的开挖坐标系 /// </summary> /// <param name="id">数据来源ID</param> /// <param name="pts"></param> /// <returns></returns> public static bool get_KWZBPt3(string id, out sg_Vector3[] pts) { // 坐标系ID pts = new sg_Vector3[3]; string zbxtid = ColumnType.ConvertStringNotDBNull(BaseBll.GetSingleValue( $"SELECT ZBXTID FROM SJLYK WHERE ID='{id}'")); if (string.IsNullOrEmpty(zbxtid)) { //没有坐标系不计算 return(false); } //获取坐标系的控制控制点坐标 //cl 2016/09/21 这里应是获取开挖坐标系 DataSet ds = GCKWZBXTKBLL.GetKZDZBByZTXTID(zbxtid); if (ds.Tables[GCKWZBXTKModel.TableName].Rows.Count == 0) { //没有坐标系不计算 return(false); } string ydid = ds.Tables[GCKWZBXTKModel.TableName].Rows[0][GCKWZBXTKModel.YDID].ToString(); //if (!string.IsNullOrEmpty(ydid)) //{ if (string.IsNullOrEmpty(ydid))//修改 xyb,为什么是有值还不计算? { //没有原点坐标,不计算 return(false); } string hzbid = ds.Tables[GCKWZBXTKModel.TableName].Rows[0][GCKWZBXTKModel.HZBID].ToString(); if (string.IsNullOrEmpty(hzbid)) { //没有x方向坐标,不计算 return(false); } string zzbid = ds.Tables[GCKWZBXTKModel.TableName].Rows[0][GCKWZBXTKModel.ZZBID].ToString(); if (string.IsNullOrEmpty(zzbid)) { //没有y方向坐标,不计算 return(false); } //开挖坐标系原点坐标 DataRow drYD = ds.Tables[GCKZDZBKModel.TableName].Rows.Find(ydid); double x = double.Parse(drYD["X"].ToString()); double y = double.Parse(drYD["Y"].ToString()); double z = double.Parse(drYD["Z"].ToString()); pts[0] = new sg_Vector3(x, y, z); //开挖坐标系X坐标 DataRow hdr = ds.Tables[GCKZDZBKModel.TableName].Rows.Find(hzbid); x = double.Parse(hdr["X"].ToString()); y = double.Parse(hdr["Y"].ToString()); z = double.Parse(hdr["Z"].ToString()); pts[1] = new sg_Vector3(x, y, z); //开挖坐标系Y坐标 DataRow zdr = ds.Tables[GCKZDZBKModel.TableName].Rows.Find(zzbid); x = double.Parse(zdr["X"].ToString()); y = double.Parse(zdr["Y"].ToString()); z = double.Parse(zdr["Z"].ToString()); pts[2] = new sg_Vector3(x, y, z); return(true); }
/// <summary> /// 由点集计算平面法向量 //??? /// </summary> /// <returns></returns> private bool CalcNormalVector(sg_Vector3[] pts) { NormalVector = new sg_Vector3(0, 0, 0); return(true); }
/// <summary> /// 设定初始数据 /// </summary> private void Init() { // 获取地质对象的三个控制点,若找不到控制点,则退出 sg_Vector3[] ptsForM1; if (!CoordSys.CoordHelp.get_KWZBPt3(SJLYID, out ptsForM1)) { return; } // 根据三个控制点,建立M1 if (ptsForM1.Count() > 2) { m1 = new CoordSys.M1(ptsForM1); } string DXID = string.Empty; string OperateID = GUIDGenerator.NewGUID; EditDataSet = GLDXMDXKBLL.GetEditDataSet(SJLYID, OperateID, DXID, string.Empty); // ? sg_Vector3[] ptsForM3; // 用于求M3的控制点 dt = BLHTBLL.GetXDMXJDZB(SJLYID); // 用于求M3(可能重构进入CoordHelp相关函数中) if (!CoordHelp.get_JBBLZBPt3(SJLYID, out ptsForM3)) { return; } // 根据三个控制点,建立M3 if (!CoordHelp.IsPtsCollinear(ptsForM3)) { this.m3Raw = new M3(ptsForM3); } if (!this.m3Raw.IsValid) { throw new Exception("M3创建失败,请检查控制点坐标。"); } // 大地控制点在M3下的坐标 sg_Vector3 pts1InM3 = this.m3Raw.getLocCoord(ptsForM3[0]); sg_Vector3 pts2InM3 = this.m3Raw.getLocCoord(ptsForM3[1]); sg_Vector3 pts3InM3 = this.m3Raw.getLocCoord(ptsForM3[2]); // 获取新的原点 double xNewO = Math.Min(Math.Min(pts1InM3.x, pts2InM3.x), pts3InM3.x); double yNewO = Math.Min(Math.Min(pts1InM3.y, pts2InM3.y), pts3InM3.y); // 获取新原点下的坐标偏移值 double xOffset = xNewO - pts1InM3.x; // 减控制点1的横纵坐标什么意思??? double yOffset = yNewO - pts1InM3.y; // 建立M3Screen (M3与M3Screen) this.m3Screen = new M3(ptsForM3, xOffset, yOffset); // 确定矩形参数 //矩形的四个顶点作为屏幕坐标的基准点 recWidth = Math.Max(Math.Max(pts1InM3.x, pts2InM3.x), pts3InM3.x) - Math.Min(Math.Min(pts1InM3.x, pts2InM3.x), pts3InM3.x); recHeight = Math.Max(Math.Max(pts1InM3.y, pts2InM3.y), pts3InM3.y) - Math.Min(Math.Min(pts1InM3.y, pts2InM3.y), pts3InM3.y); sg_Vector3 recLeftLow = new sg_Vector3(0, 0); sg_Vector3 recLeftHigh = new sg_Vector3(0, recHeight); sg_Vector3 recRightLow = new sg_Vector3(recWidth, 0); sg_Vector3 recRightHigh = new sg_Vector3(recWidth, recHeight); widthHeightRito = recWidth / recHeight; // 绘制矩形 }
/// <summary> /// 由局部编录坐标计算大地坐标 /// </summary> /// <param name="pt">以局部编录坐标表示的点</param> /// <returns></returns> public sg_Vector3 getWorldCoord(sg_Vector3 pt) { return(mTrans.apply(pt)); }
/// <summary> /// 由大地坐标计算局部编录坐标 /// </summary> /// <param name="pt">以大地坐标表示的点</param> /// <returns></returns> public sg_Vector3 getLocCoord(sg_Vector3 pt) { return(mTrans.inverse(pt)); }