/// <summary> Смасштабировать и повернуть изображение профиля по опорным точкам </summary> private void UpdateProfileImageByControlPoints() { #region Обрезание var image = ProgramCore.Project.ProfileImage; var leftX = (int)(profileControlPoints.Min(x => x.ValueMirrored.X) * image.Width); var topY = (int)(profileControlPoints.Min(x => x.ValueMirrored.Y) * image.Height); var bottomY = (int)(profileControlPoints.Max(x => x.ValueMirrored.Y) * image.Height); leftX = leftX - 100 < 0 ? 0 : leftX - 100; // ширину хз как определять, ой-вей topY = topY - 10 < 0 ? 0 : topY - 10; bottomY = bottomY + 10 > image.Height ? image.Height : bottomY + 10; var height = bottomY - topY; var faceRectangle = new Rectangle(leftX, topY, image.Width - leftX, height); var croppedImage = ImageEx.Crop(image, faceRectangle); for (var i = 0; i < profileControlPoints.Count; i++) // смещаем все точки, чтобы учесть обрезанное { var point = profileControlPoints[i]; var pointK = new Vector2(point.ValueMirrored.X * image.Width, point.ValueMirrored.Y * image.Height); // по старой ширине-высоте pointK.X -= leftX; pointK.Y -= topY; profileControlPoints[i] = new MirroredHeadPoint(point.Value, new Vector2(pointK.X / (croppedImage.Width * 1f), pointK.Y / (croppedImage.Height * 1f)), false); // и в новые } #endregion #region Поворот var xVector = new Vector2(1, 0); var vectorLeft = profileControlPoints[2].ValueMirrored - profileControlPoints[1].ValueMirrored; // из глаза рот vectorLeft = new Vector2(vectorLeft.X * croppedImage.Width, vectorLeft.Y * croppedImage.Height); vectorLeft.Normalize(); var xDiff = xVector.X - vectorLeft.X; var yDiff = xVector.Y - vectorLeft.Y; var angleLeft = Math.Atan2(yDiff, xDiff); var vectorRight = profileControlPoints[2].Value - profileControlPoints[1].Value; vectorRight.Normalize(); xDiff = xVector.X - vectorRight.X; yDiff = xVector.Y - vectorRight.Y; var angleRight = -Math.Atan2(yDiff, xDiff); var angleDiffRad = angleRight - angleLeft; var angleDiff = angleDiffRad * 180.0 / Math.PI; using (var ii = ImageEx.RotateImage(croppedImage, (float)angleDiff)) { ProgramCore.Project.ProfileImage = new Bitmap(ii); SetTemplateImage(ProgramCore.Project.ProfileImage, false); } var center = new Vector2(ProgramCore.Project.ProfileImage.Width * 0.5f, ProgramCore.Project.ProfileImage.Height * 0.5f); var cosAngle = Math.Cos(angleDiffRad); var sinAngle = Math.Sin(angleDiffRad); for (var i = 0; i < profileControlPoints.Count; i++) // смещаем все точки, чтобы учесть обрезанное { var point = profileControlPoints[i]; var pointAbsolute = new Vector2(point.ValueMirrored.X * ProgramCore.Project.ProfileImage.Width, point.ValueMirrored.Y * ProgramCore.Project.ProfileImage.Height); // по старой ширине-высоте var newPoint = pointAbsolute - center; newPoint = new Vector2((float)(newPoint.X * cosAngle - newPoint.Y * sinAngle), (float)(newPoint.Y * cosAngle + newPoint.X * sinAngle)); newPoint += center; profileControlPoints[i] = new MirroredHeadPoint(point.Value, new Vector2(newPoint.X / (ProgramCore.Project.ProfileImage.Width * 1f), newPoint.Y / (ProgramCore.Project.ProfileImage.Height * 1f)), false); // и в новые } ProgramCore.MainForm.ctrlRenderControl.InitializeProfileCamera(ModelAdaptParamProfile); #endregion var projectPath = Path.Combine(ProgramCore.Project.ProjectPath, "ProfileImage.jpg"); ProgramCore.Project.ProfileImage.Save(projectPath); ControlPointsMode = ProfileControlPointsMode.UpdateRightLeft; }
public void pictureTemplate_MouseUp(object sender, MouseEventArgs e) { startMousePoint = Vector2.Zero; if (e.Button == MouseButtons.Left) { headLastPoint = Vector2.Zero; switch (ProgramCore.MainForm.ctrlRenderControl.ScaleMode) { case ScaleMode.Zoom: tempOffsetPoint = Vector2.Zero; break; case ScaleMode.None: #region Обычные режимы switch (ProgramCore.MainForm.ctrlRenderControl.Mode) { case Mode.HeadAutodotsFirstTime: case Mode.HeadAutodots: { if (ProgramCore.Project.ShapeFlip != FlipType.None) return; if (!startMove && !dblClick) { if (!shiftKeyPressed) ProgramCore.MainForm.ctrlRenderControl.headController.AutoDots.ClearSelection(); if (e.X >= MouthTransformed.X - HalfPointRectSize && e.X <= MouthTransformed.X + HalfPointRectSize && e.Y >= MouthTransformed.Y - HalfPointRectSize && e.Y <= MouthTransformed.Y + HalfPointRectSize) // рот ProgramCore.MainForm.ctrlRenderControl.headController.SelectAutdotsMouth(); else if (e.X >= LeftEyeTransformed.X - HalfPointRectSize && e.X <= LeftEyeTransformed.X + HalfPointRectSize && e.Y >= LeftEyeTransformed.Y - HalfPointRectSize && e.Y <= LeftEyeTransformed.Y + HalfPointRectSize) // левый глаз ProgramCore.MainForm.ctrlRenderControl.headController.SelectAutodotsLeftEye(); else if (e.X >= RightEyeTransformed.X - HalfPointRectSize && e.X <= RightEyeTransformed.X + HalfPointRectSize && e.Y >= RightEyeTransformed.Y - HalfPointRectSize && e.Y <= RightEyeTransformed.Y + HalfPointRectSize) // правый глаз ProgramCore.MainForm.ctrlRenderControl.headController.SelectAutodotsRightEye(); else if (e.X >= NoseTransformed.X - HalfPointRectSize && e.X <= NoseTransformed.X + HalfPointRectSize && e.Y >= NoseTransformed.Y - HalfPointRectSize && e.Y <= NoseTransformed.Y + HalfPointRectSize) // нос ProgramCore.MainForm.ctrlRenderControl.headController.SelectAutodotsNose(); else if (e.X >= CentralFacePoint.X - HalfPointRectSize && e.X <= CentralFacePoint.X + HalfPointRectSize && e.Y >= CentralFacePoint.Y - HalfPointRectSize && e.Y <= CentralFacePoint.Y + HalfPointRectSize) // прямоугольник и выделение всех точек { if (RectTransformMode) { RectTransformMode = false; ProgramCore.MainForm.ctrlRenderControl.headController.AutoDots.ClearSelection(); } else { RectTransformMode = true; UpdateUserCenterPositions(true, true); ProgramCore.MainForm.ctrlRenderControl.headController.SelectAutodotsFaceEllipse(); } } else ProgramCore.MainForm.ctrlRenderControl.headController.UpdateAutodotsPointSelection(e.X, e.Y, true); } else { RecalcEyeMouthRect(); if (ProgramCore.MainForm.ctrlRenderControl.Mode == Mode.HeadAutodots) { ProgramCore.MainForm.ctrlRenderControl.CalcReflectedBitmaps(); ProgramCore.MainForm.ctrlRenderControl.headController.EndAutodots(false); ProgramCore.MainForm.ctrlRenderControl.ApplySmoothedTextures(); for (var i = 0; i < ProgramCore.MainForm.ctrlRenderControl.headController.AutoDots.Count; i++) // после слияние с ShapeDots. Проверить! { var p = ProgramCore.MainForm.ctrlRenderControl.headController.AutoDots[i]; if (p.Selected) ProgramCore.MainForm.ctrlRenderControl.autodotsShapeHelper.Transform(p.Value, i); // точка в мировых координатах } } } } break; /* case Mode.HeadShapedots: if (ProgramCore.Project.ShapeFlip != FlipType.None) return; if (!startMove && !dblClick) { if (!shiftKeyPressed) ProgramCore.MainForm.ctrlRenderControl.headController.ShapeDots.ClearSelection(); if (e.X >= MouthTransformed.X - HalfPointRectSize && e.X <= MouthTransformed.X + HalfPointRectSize && e.Y >= MouthTransformed.Y - HalfPointRectSize && e.Y <= MouthTransformed.Y + HalfPointRectSize) // рот ProgramCore.MainForm.ctrlRenderControl.headController.SelectShapedotsMouth(); else if (e.X >= LeftEyeTransformed.X - HalfPointRectSize && e.X <= LeftEyeTransformed.X + HalfPointRectSize && e.Y >= LeftEyeTransformed.Y - HalfPointRectSize && e.Y <= LeftEyeTransformed.Y + HalfPointRectSize) // левый глаз ProgramCore.MainForm.ctrlRenderControl.headController.SelectShapedotsLeftEye(); else if (e.X >= RightEyeTransformed.X - HalfPointRectSize && e.X <= RightEyeTransformed.X + HalfPointRectSize && e.Y >= RightEyeTransformed.Y - HalfPointRectSize && e.Y <= RightEyeTransformed.Y + HalfPointRectSize) // правый глаз ProgramCore.MainForm.ctrlRenderControl.headController.SelectShapedotsRightEye(); else if (e.X >= NoseTransformed.X - HalfPointRectSize && e.X <= NoseTransformed.X + HalfPointRectSize && e.Y >= NoseTransformed.Y - HalfPointRectSize && e.Y <= NoseTransformed.Y + HalfPointRectSize) // нос ProgramCore.MainForm.ctrlRenderControl.headController.SelectShapedotsNose(); else if (e.X >= CentralFacePoint.X - HalfPointRectSize && e.X <= CentralFacePoint.X + HalfPointRectSize && e.Y >= CentralFacePoint.Y - HalfPointRectSize && e.Y <= CentralFacePoint.Y + HalfPointRectSize) // прямоугольник и выделение всех точек { if (RectTransformMode) { RectTransformMode = false; ProgramCore.MainForm.ctrlRenderControl.headController.ShapeDots.ClearSelection(); } else { RectTransformMode = true; UpdateUserCenterPositions(true, true); ProgramCore.MainForm.ctrlRenderControl.headController.SelectShapedotsFaceEllipse(); } } else ProgramCore.MainForm.ctrlRenderControl.headController.UpdateShapedotsPointSelection(e.X, e.Y, true); } else { for (var i = 0; i < ProgramCore.MainForm.ctrlRenderControl.headController.ShapeDots.Count; i++) { var p = ProgramCore.MainForm.ctrlRenderControl.headController.ShapeDots[i]; if (p.Selected) ProgramCore.MainForm.ctrlRenderControl.autodotsShapeHelper.Transform(p.Value, i); // точка в мировых координатах } } break;*/ case Mode.HeadAutodotsLassoStart: headAutodotsLassoPoints.Add(new Vector2(e.X, e.Y)); break; /* case Mode.HeadShapedotsLassoStart: headShapedotsLassoPoints.Add(new Vector2(e.X, e.Y)); break;*/ case Mode.HeadLine: { if (ProgramCore.Project.ShapeFlip != FlipType.None) return; if (ProgramCore.MainForm.HeadFront) { #region вид спереди if (!startMove && !dblClick) { #region Проверяем, начали ли что-то обводить линиями var firstTime = false; if (e.X >= MouthTransformed.X - 2.5 && e.X <= MouthTransformed.X + 2.5 && e.Y >= MouthTransformed.Y - 2.5 && e.Y <= MouthTransformed.Y + 2.5) // рот { if (ProgramCore.MainForm.ctrlRenderControl.HeadLineMode != MeshPartType.Lip) { firstTime = true; ProgramCore.MainForm.ctrlRenderControl.HeadLineMode = MeshPartType.Lip; } } else if (e.X >= LeftEyeTransformed.X - 2.5 && e.X <= LeftEyeTransformed.X + 2.5 && e.Y >= LeftEyeTransformed.Y - 2.5 && e.Y <= LeftEyeTransformed.Y + 2.5) // левый глаз { firstTime = true; ProgramCore.MainForm.ctrlRenderControl.HeadLineMode = MeshPartType.LEye; } else if (e.X >= RightEyeTransformed.X - 2.5 && e.X <= RightEyeTransformed.X + 2.5 && e.Y >= RightEyeTransformed.Y - 2.5 && e.Y <= RightEyeTransformed.Y + 2.5) // правый глаз { firstTime = true; ProgramCore.MainForm.ctrlRenderControl.HeadLineMode = MeshPartType.REye; } else if (e.X >= NoseTransformed.X - 2.5 && e.X <= NoseTransformed.X + 2.5 && e.Y >= NoseTransformed.Y - 2.5 && e.Y <= NoseTransformed.Y + 2.5) // нос { firstTime = true; ProgramCore.MainForm.ctrlRenderControl.HeadLineMode = MeshPartType.Nose; } else if (e.X >= CentralFacePoint.X - 2.5 && e.X <= CentralFacePoint.X + 2.5 && e.Y >= CentralFacePoint.Y - 2.5 && e.Y <= CentralFacePoint.Y + 2.5) { firstTime = true; ProgramCore.MainForm.ctrlRenderControl.HeadLineMode = MeshPartType.Head; } #endregion if (firstTime) // выбираем режим линии { ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Clear(); ProgramCore.MainForm.ctrlRenderControl.autodotsShapeHelper.ResetPoints(ProgramCore.MainForm.ctrlRenderControl.HeadLineMode); } else if (ProgramCore.MainForm.ctrlRenderControl.HeadLineMode != MeshPartType.None) // добавляем новые точки { var point = new MirroredHeadPoint(headLastPointRelative, headLastPointRelative, false); point.UpdateWorldPoint(); #region Проверка на количество линий и режим выделения if (ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Count > 1) { var condition = false; switch (ProgramCore.MainForm.ctrlRenderControl.HeadLineMode) { case MeshPartType.Lip: if (ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Count > 2) condition = true; break; default: if (ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Count > 1) condition = true; break; } if (condition) // если ничего не выделили - начинаем рисовать новую линию. иначе уходим в режим выделения и таскания точек { if (!shiftKeyPressed) ProgramCore.MainForm.ctrlRenderControl.headController.ClearPointsSelection(); if (ProgramCore.MainForm.ctrlRenderControl.headController.UpdatePointSelection(point.Value.X, point.Value.Y)) LineSelectionMode = true; else { if (LineSelectionMode) { LineSelectionMode = false; ProgramCore.MainForm.ctrlRenderControl.headController.ClearPointsSelection(); break; } else ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Clear(); } } } #endregion if (!LineSelectionMode) { #region Добавляем новые точки линии if (ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Count == 0) { var line = new HeadLine(); line.Add(point); ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Add(line); } else { var currentLine = ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Last(); var hasIntersections = false; if (currentLine.Count > 1) // проверка на пересечения линий { var lastPoint = currentLine.Last(); float ua, ub; for (var i = currentLine.Count - 2; i >= 0; i--) { var pointA = currentLine[i]; var pointB = currentLine[i + 1]; if (AutodotsShapeHelper.GetUaUb(ref lastPoint.Value, ref point.Value, ref pointA.Value, ref pointB.Value, out ua, out ub)) { if (ua > 0 && ua < 1 && ub > 0 && ub < 1) { hasIntersections = true; break; } } } } var inAnotherPoint = false; if (ProgramCore.MainForm.ctrlRenderControl.HeadLineMode == MeshPartType.Lip && ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Count == 2) { // ЭТо вторая линия губ foreach (var lPoint in ProgramCore.MainForm.ctrlRenderControl.headController.Lines.First()) if (point.Value.X >= lPoint.Value.X - 0.25 && point.Value.X <= lPoint.Value.X + 0.25 && point.Value.Y >= lPoint.Value.Y - 0.25 && point.Value.Y <= lPoint.Value.Y + 0.25 && !currentLine.Contains(lPoint)) { if (currentLine.Count == 0) currentLine.Add(lPoint); else { currentLine.Add(lPoint); ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Add(new HeadLine()); } inAnotherPoint = true; break; } if (currentLine.Count == 0) //первую точку добавляем всегда в пересечении с другой точкой. inAnotherPoint = true; } // прочие случаи if (!hasIntersections && !inAnotherPoint) { var firstPoint = currentLine.First(); if (point.Value.X >= firstPoint.Value.X - 0.25 && point.Value.X <= firstPoint.Value.X + 0.25 && point.Value.Y >= firstPoint.Value.Y - 0.25 && point.Value.Y <= firstPoint.Value.Y + 0.25) { currentLine.Add(firstPoint); ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Add(new HeadLine()); } else currentLine.Add(point); } } #endregion } } } #endregion } else { #region Вид сбоку if (isProfileSmoothing) return; if (!startMove && !dblClick) { var point = new MirroredHeadPoint(headLastPointRelative, headLastPointRelative, false); point.UpdateWorldPoint(); #region Проверка на количество линий и режим выделения if (ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Count > 1) // если ничего не выделили - начинаем рисовать новую линию. иначе уходим в режим выделения и таскания точек { if (!shiftKeyPressed) ProgramCore.MainForm.ctrlRenderControl.headController.ClearPointsSelection(); if (ProgramCore.MainForm.ctrlRenderControl.headController.UpdatePointSelection(point.Value.X, point.Value.Y)) LineSelectionMode = true; else { if (LineSelectionMode) { LineSelectionMode = false; ProgramCore.MainForm.ctrlRenderControl.headController.ClearPointsSelection(); break; } } } #endregion if (!LineSelectionMode) { #region Добавляем новые точки линии if (ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Count == 0) { var line = new HeadLine(); line.Add(point); ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Add(line); } else { var currentLine = ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Last(); var hasIntersections = false; if (currentLine.Count > 1) // проверка на пересечения линий { var lastPoint = currentLine.Last(); float ua, ub; for (var i = currentLine.Count - 2; i >= 0; i--) { var pointA = currentLine[i]; var pointB = currentLine[i + 1]; if (AutodotsShapeHelper.GetUaUb(ref lastPoint.Value, ref point.Value, ref pointA.Value, ref pointB.Value, out ua, out ub)) { if (ua > 0 && ua < 1 && ub > 0 && ub < 1) { hasIntersections = true; break; } } } } // прочие случаи if (!hasIntersections) currentLine.Add(point); } #endregion } } #endregion } } break; case Mode.None: { if (ProgramCore.MainForm.HeadProfile) { switch (ControlPointsMode) { case ProfileControlPointsMode.SetControlPoints: // в профиле. расставляем опорные точки { if (headLastPointRelative != Vector2.Zero) { profileControlPoints[profileControlPointIndex].ValueMirrored = headLastPointRelative; ++profileControlPointIndex; if (profileControlPointIndex == 4) { ControlPointsMode = ProfileControlPointsMode.MoveControlPoints; profileControlPointIndex = 0; } } } break; case ProfileControlPointsMode.MoveControlPoints: // выделяем и двигаем опорные точки { if (!startMove && !dblClick) { if (!shiftKeyPressed) foreach (var point in profileControlPoints) point.Selected = false; foreach (var point in profileControlPoints) { var pointK = new Vector2(point.ValueMirrored.X * ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateWidth + ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateOffsetX, point.ValueMirrored.Y * ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateHeight + ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateOffsetY); if (e.X >= pointK.X - 5 && e.X <= pointK.X + 5 && e.Y >= pointK.Y - 5 && e.Y <= pointK.Y + 5) { point.Selected = true; break; } } } } break; case ProfileControlPointsMode.UpdateRightLeft: // выделяем и двигаем опорные точки { if (!startMove && !dblClick) { if (!shiftKeyPressed) foreach (var point in profileControlPoints) point.Selected = false; for (var i = 0; i < profileControlPoints.Count; i += 3) { var point = profileControlPoints[i]; var pointK = new Vector2(point.ValueMirrored.X * ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateWidth + ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateOffsetX, point.ValueMirrored.Y * ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateHeight + ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateOffsetY); if (e.X >= pointK.X - 5 && e.X <= pointK.X + 5 && e.Y >= pointK.Y - 5 && e.Y <= pointK.Y + 5) { point.Selected = true; break; } } } else if (startMove) { UpdateProfileRectangle(); } } break; } } } break; } #endregion break; } } moveRectIndex = -1; startMove = false; leftMousePressed = false; dblClick = false; headLastPointRelative = Vector2.Zero; headTempPoints.Clear(); Cursor = Cursors.Arrow; }
private void ctrlTemplateImage_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) { if (e.KeyData == (Keys.A)) ProgramCore.MainForm.ctrlRenderControl.headController.SelectAll(); else if (e.KeyData == (Keys.D)) ProgramCore.MainForm.ctrlRenderControl.headController.ClearPointsSelection(); else if (e.KeyData == (Keys.ShiftKey | Keys.Shift)) shiftKeyPressed = true; else if (e.KeyData == Keys.Enter) { switch (ProgramCore.MainForm.ctrlRenderControl.Mode) { case Mode.HeadLine: if (ProgramCore.MainForm.HeadProfile) { if (isProfileSmoothing) { isProfileSmoothing = false; ProgramCore.MainForm.panelFront.UpdateProfileSmoothing(isProfileSmoothing); } else if (ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Count == 2) { if (ProgramCore.MainForm.ctrlRenderControl.headController.AllPoints.Count > 3) { foreach (var point in ProgramCore.MainForm.ctrlRenderControl.headController.AllPoints) point.UpdateWorldPoint(); #region История (undo) Dictionary<Guid, MeshUndoInfo> undoInfo; ProgramCore.MainForm.ctrlRenderControl.headMeshesController.GetUndoInfo(out undoInfo); var isProfile = ProgramCore.MainForm.HeadProfile; var teInfo = isProfile ? ProgramCore.MainForm.ctrlRenderControl.autodotsShapeHelper.ShapeProfileInfo : ProgramCore.MainForm.ctrlRenderControl.autodotsShapeHelper.ShapeInfo; var historyElem = new HistoryHeadShapeLines(undoInfo, null, teInfo, isProfile); ProgramCore.MainForm.ctrlRenderControl.historyController.Add(historyElem); #endregion var userPoints = ProgramCore.MainForm.ctrlRenderControl.headController.AllPoints.Select(x => x.ValueMirrored).ToList(); List<Vector2> pointsTop = new List<Vector2>(); List<Vector2> pointsBottom = null; var lipsY = ProgramCore.MainForm.ctrlRenderControl.autodotsShapeHelper.GetLipsTopY(); var prevPoint = Vector2.Zero; for (int i = 0; i < userPoints.Count; ++i) { var p = userPoints[i]; var x = p.X * ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateWidth + ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateOffsetX; var y = p.Y * ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateHeight + ProgramCore.MainForm.ctrlTemplateImage.ImageTemplateOffsetY; var point = ProgramCore.MainForm.ctrlRenderControl.camera.GetWorldPoint((int)x, (int)y, ProgramCore.MainForm.ctrlRenderControl.Width, ProgramCore.MainForm.ctrlRenderControl.Height, 1.0f).Zy; if (point.Y < lipsY && i > 0) { if (pointsBottom == null) { var tempPoint = point - prevPoint; var d = (point.Y - prevPoint.Y) / (prevPoint.Y - lipsY); var center = prevPoint + tempPoint * d; pointsTop.Add(center); pointsBottom = new List<Vector2>(); pointsBottom.Add(center); } pointsBottom.Add(point); } else { prevPoint = point; pointsTop.Add(point); } } ProgramCore.MainForm.ctrlRenderControl.autodotsShapeHelper.Transform(MeshPartType.ProfileTop, pointsTop, Vector2.Zero); ProgramCore.MainForm.ctrlRenderControl.autodotsShapeHelper.Transform(MeshPartType.ProfileBottom, pointsBottom, Vector2.Zero); var th = new Thread(() => { Thread.CurrentThread.IsBackground = true; ProgramCore.MainForm.ctrlRenderControl.headMeshesController.Smooth(); }); th.Start(); while (th.IsAlive) ProgramCore.Progress("Please wait"); ProfileSmoothing = new ProfileSmoothing(ProgramCore.MainForm.ctrlRenderControl.headMeshesController.RenderMesh, undoInfo); } foreach (var p in ProgramCore.MainForm.ctrlRenderControl.headMeshesController.RenderMesh.Parts) p.UpdateNormals(); ProgramCore.MainForm.ctrlRenderControl.headController.Lines.Clear(); //ProgramCore.MainForm.ctrlRenderControl.HeadLineMode = ProgramCore.MainForm.ctrlRenderControl.HeadLineMode == MeshPartType.ProfileTop ? MeshPartType.ProfileBottom : MeshPartType.ProfileTop; ProgramCore.MainForm.ctrlRenderControl.UpdateProfileRectangle(); isProfileSmoothing = true; ProgramCore.MainForm.panelFront.UpdateProfileSmoothing(isProfileSmoothing); } else FinishLine(); } else FinishLine(); break; case Mode.None: if (ProgramCore.MainForm.HeadProfile) switch (ControlPointsMode) { case ProfileControlPointsMode.MoveControlPoints: UpdateProfileImageByControlPoints(); UpdateProfileRectangle(); ProgramCore.MainForm.ctrlRenderControl.UpdateProfileRectangle(); ControlPointsMode = ProfileControlPointsMode.UpdateRightLeft; break; case ProfileControlPointsMode.UpdateRightLeft: UpdateProfileRectangle(); foreach (var point in profileControlPoints) point.Selected = false; ControlPointsMode = ProfileControlPointsMode.None; break; } break; } } }