Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Media";
Текущий архив: 2004.03.28;
Скачать: [xml.tar.bz2];

Вниз

Как вращать строку с центром посредине строки?   Найти похожие ветки 

 
DAndrew   (2003-11-19 08:56) [0]

Как вращать строку с центром вращения посредине строки, а не в верхне-левом углу?
Вариант - рисовать текст на битмапе, а затем его вращать на заданный угол приводит к резким искажениям шрифта. Применение алгоритма антиалиазинга к битмапу сглаживает прорисовку, но резко тормозит систему.
Пожалуйста, практический пример или ссылку на подобный алгоритм!
Заранее благодарен!
Андрей!


 
default ©   (2003-11-19 09:11) [1]

через уравнения концентрических окружностей?


 
DAndrew   (2003-11-19 09:34) [2]

А как конкретно?
Приведите, пожалуйста, практический пример или отправьте мне его по почте. Как удобно.
Спасибо!


 
nstur   (2003-11-19 10:00) [3]

Ребята, вопрос интереный, поделитесь для всех.


 
default ©   (2003-11-19 10:02) [4]

символы текста тоже должны вращаться?


 
default ©   (2003-11-19 10:03) [5]

всмысле вокруг своей оси, если за ось принять их центр


 
DAndrew   (2003-11-19 10:31) [6]

всмысле вокруг своей оси, если за ось принять их центр
Да, например, если за центр принять центральный (или приходящийся на него) символ строки (если только это не пробел). А вращать неободимо всю строку! Попеременно в разные стороны (принимая поочередно положительные и отрицательные значения угла поворота строки).
И все же может кто-либо привести практический пример, а не теорию?
Спасибо!


 
default ©   (2003-11-19 10:36) [7]

точно?то есть, например, в какой-то момент буква "ф" может стать перевёрнутой?


 
DAndrew   (2003-11-19 11:17) [8]

Да не совсем, ну вот, например возьмем строку:

Это строка для вращения

И в ней за центр поворота следует взять ее середину, например центр вращения где-то в сисмволе "д" (а символ это будет конкретно или нет - это уже дело случая!)
Теперь понятен смысл вопроса?
Спасибо!


 
default ©   (2003-11-19 11:21) [9]

DAndrew   (19.11.03 11:17) [8]
так и не ответил на вопрос, ну ладно


 
DAndrew   (2003-11-19 11:41) [10]

default - например, в какой-то момент буква "ф" может стать перевёрнутой?
Нет, угол поворота не должен превышать диапазона "-40" градусов и "40" градусов.
Теперь я ответил на Ваш вопрос?
Спасибо!


 
MBo ©   (2003-11-19 12:23) [11]

Делаешь шрифт под углом
var
  LogFont: TLogFont;

with MyCanvas do begin
  Font.Name := "Arial";
  Font.Size := 24;
  Font.Style := [fsBold];
  GetObject(Font.Handle, @LogFont, SizeOf(LogFont));
  with LogFont do begin
    lfOrientation := 450;  {set to 45 degrees}
    lfEscapement := lfOrientation end;
  Font.Handle := CreateFontIndirect(LogFont);

и выводишь строку в рассчитаную позицию


 
DAndrew   (2003-11-19 12:27) [12]

MBo
Да, это все понятно, но как это практически "...и выводишь строку в рассчитаную позицию"?
Можете привести полный пример кода?
По-моему Ваша мысль - это все же прорисовка строки на битмапе и уже поворот его, а не собстенно строки. Или нет?
Спасибо!


 
MBo ©   (2003-11-19 13:02) [13]

>Ваша мысль - это все же прорисовка строки на битмапе и уже
поворот его
нет. Это именно вывод строки штатными средствами GDI (с сохранением антиалиасинга)


procedure TForm1.Button6Click(Sender: TObject);
var
 LogFont: TLogFont;
 s:string;
 w,h,x,y:Integer;
begin
with Canvas do begin
 Font.Name := "Arial";
 Font.Size := 24;
 GetObject(Font.Handle, SizeOf(LogFont),@LogFont);
 with LogFont do begin
   lfOrientation := 300;
   lfEscapement := lfOrientation;
 end;
 Font.Handle := CreateFontIndirect(LogFont);
end;
s:="0123456789----9876543210";
Canvas.Ellipse(195,195,205,205);
w:=Canvas.TextWidth(s);
h:=Canvas.TextHeight(s);
X:=200-Round(cos(Pi/6)*w+h*sin(Pi/6)) div 2;
Y:=200-Round(-sin(Pi/6)*w+h*cos(Pi/6)) div 2;
Canvas.TextOut(X,Y,s);
Canvas.Ellipse(200-5,200-5,200+5,200+5);
end;


 
_Zergey   (2003-11-19 13:35) [14]

function AngleTextRect(DC:HDC;const AText:string;Left,Top:integer;
Angle:single;Alignment:TAlignment):TRect;
var
i,mw:integer;
Sz:TSize;
ARect:TRect;
Pt:array of TPoint;
begin
if Length(AText)=0 then Result:=Bounds(Left,Top,0,0) else
with TStringList.Create do
try
 Text:=AText;
 SetLength(Pt,(Count shl 2)+1);
 mw:=0;
 Int64(Pt[0]):=0;
 for i:=0 to Count-1 do
 begin
  GetTextExtentPoint(DC,PChar(Strings[i]),Length(Strings[i]),Sz);
  mw:=Max(mw,Sz.cx);
  Pt[i+1].x:=Sz.cx;
  Pt[i+1].y:=Pt[i].y+Sz.cy
 end;
 Objects[0]:=TObject(Pt[Count].y shr 1);
 for i:=Count downto 1 do
 with Sz do
 begin
  ARect.Left:=0;
  ARect.Top:=Pt[i-1].y;
  ARect.BottomRight:=Pt[i];
  case Alignment of
   taCenter:OffsetRect(ARect,((mw-WidthOf(ARect)) shr 1)+Left,Top);
   taRightJustify:OffsetRect(ARect,mw-WidthOf(ARect)+Left,Top)
   else OffsetRect(ARect,Left,Top)
  end;
  cy:=i shl 2;
  with ARect do
  begin
   Pt[cy]:=BottomRight;
   Dec(cy);
   Pt[cy]:=Point(Left,Bottom);
   Dec(cy);
   Pt[cy]:=Point(Right,Top);
   Dec(cy);
   Pt[cy]:=TopLeft
  end
 end;
 Pt[0]:=Point((mw shr 1)+Left,Integer(Objects[0])+Top);
 RotatePt(Pt,Angle);
 Result:=PolygonRect(Pt)
finally
 Free
end
end;

procedure DrawRotatedText(DC:HDC;const Text:string;const ARect:TRect;
Angle:single;Alignment:TAlignment;Layout:TTextLayout);
begin
with AngleTextRect(DC,Text,ARect.Left,ARect.Top,-Angle,Alignment) do
begin
 case Alignment of
  taCenter:Left:=(WidthOf(ARect) shr 1)+ARect.Left;
  taRightJustify:Left:=ARect.Right-((Right-Left) shr 1)
  else Left:=((Right-Left) shr 1)+ARect.Left
 end;
 case Layout of
  tlCenter:Top:=(HeightOf(ARect) shr 1)+ARect.Top;
  tlBottom:Top:=ARect.Bottom-((Bottom-Top) shr 1)
  else Top:=((Bottom-Top) shr 1)+ARect.Top
 end;
 AngledTextOut(DC,Text,Left,Top,-Angle,Alignment)
end
end;


 
DAndrew   (2003-11-19 13:43) [15]

MBo!
Спасибо, но это все же не то...
Опять таки поворот строки происходит с центром от первого символа строки ("неподвижная точка"), а мне необходимо, чтобы (по Вашему коду) левая и правая части строки (от Вашего эллипса в центре 0123456789----о-----9876543210) вращались в противоположные стороны при задаваемых значениях угла от "-45" до "45" градусов! А центром вращения ("неподвижной точкой") оставалась точка, которую Вы обозначили, как эллипс послредине строки.
Я несколько дополнил Ваш код, посмотрите, может так Вам станет понятнее проблема. Кликая на кнопке строка должна "вертеться", подобно "детским качелям":

...................................
var
 Form1: TForm1;
 FAngle: Integer;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 FAngle:= 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
     var LogFont: TLogFont;
         s: string;
         w, h, x, y:Integer;
begin
 inc(FAngle, 200);
 with Image1.Canvas do begin
      Font.Name := "Arial";
      Font.Size := 24;
      GetObject(Font.Handle, SizeOf(LogFont), @LogFont);

      with LogFont do begin
           lfOrientation := FAngle;
           lfEscapement := lfOrientation; end;

      Font.Handle := CreateFontIndirect(LogFont);
 end;

 s:="0123456789----9876543210";
 Image1.Canvas.Ellipse(195, 195, 205, 205);
 w:= Image1.Canvas.TextWidth (s);
 h:= Image1.Canvas.TextHeight(s);
 X:= 200 - Round( cos(Pi/6)*w + h*sin(Pi/6)) div 2;
 Y:= 200 - Round(-sin(Pi/6)*w + h*cos(Pi/6)) div 2;
 Image1.Canvas.TextOut(X, Y, s);
 Image1.Canvas.Ellipse(200 - 5, 200 - 5, 200 + 5, 200 + 5);
end;

end.

Спасибо!

Андрей!


 
DAndrew   (2003-11-19 13:45) [16]

_Zergey

Спасибо - проверю и напишу, что получилось!

Андрей!


 
DAndrew   (2003-11-19 14:00) [17]

_Zergey!

Коды не компилируются, компилятор выдает следующие ошибки (возможно их больше):

[Error] Unit1.pas(78): Undeclared identifier: "RotatePt"
[Error] Unit1.pas(79): Undeclared identifier: "PolygonRect"
[Error] Unit1.pas(100): Undeclared identifier: "AngledTextOut"
[Fatal Error] Project1.dpr(5): Could not compile used unit "Unit1.pas"


Функция WidthOf из библиотеки RXLib? А можно обойти эту библиотеку, у меня строки с символами юникодов?
Как и какими другими функциями можно заменить некоторые из примененных в Вашем коде.
Вы можете привести полные коды, если Вам удобно отошлите мне их на мой email! И еще вопрос могут ли данные коды поворота строки работать с юникодными символами, это очень важно для меня. Так как строка у меня содержит символы юникодов.

Спасибо!

Андрей!


 
MBo ©   (2003-11-19 14:11) [18]

>Спасибо, но это все же не то...
Это именно то, что требовалось, просто кое-кто не обдумал приведенный код.
Pi/6  - это не случайная абстракция, а 30 градусов (соответствует 300 в LogFont).


 
default ©   (2003-11-19 14:22) [19]

DAndrew   (19.11.03 13:43) [15]
inc(FAngle, 200);
этим ты меняешь точку относительно которой под заданным углом выводится строка...
см MBo ©   (19.11.03 14:11) [18]


 
default ©   (2003-11-19 14:24) [20]

MBo ©   (19.11.03 13:02) [13]
"Font.Handle := CreateFontIndirect(LogFont);"
а ресурс здесь не теряется?Font.Handle не надо сохранять?


 
DAndrew   (2003-11-19 14:37) [21]

И все же, Мастера!
Как решить практически проблему?

Есть еще мнения?

Можно по email.

Андрей!


 
default ©   (2003-11-19 14:43) [22]

DAndrew   (19.11.03 14:37) [21]
млин, FAngle ты даже нигде не используешь, а хочешь чтобы что-то менялось...
"Как решить практически проблему?"
MBo тебе всё написал, осталось только обобщить, непонял код?нарисуй на бумажке - поймёшь


 
MBo ©   (2003-11-19 14:54) [23]

>default ©   (19.11.03 14:24) [20]
>а ресурс здесь не теряется?Font.Handle не надо сохранять?
Насколько я помню, при назначении нового дескриптора граф. объекту (TFont.SetHandle) старый освобождается с пом. FreeResource.
Можно оттрассировать.


 
default ©   (2003-11-19 15:08) [24]

MBo ©   (19.11.03 14:54) [23]
да действительно


 
DAndrew   (2003-11-19 15:46) [25]

MBo!

Извините, сразу не понял Вашего кода.
Против часовой стрелки у меня получилось, подскажите, что необходимо скорректировать в Вашем коде (MBo © (19.11.03 13:02) [13]), чтобы вращение строки было по часовой стрелке.

Спасибо!

Андрей!


 
default ©   (2003-11-19 15:51) [26]

DAndrew   (19.11.03 15:46) [25]
а говоришь понял...угол в обратном направлении менять


 
DAndrew   (2003-11-19 16:11) [27]

Пробовал задать переменную FAngle с отрицательным значением - неполучается.
Что-то еще необходимо изменить?

Андрей.


 
default ©   (2003-11-19 16:13) [28]

код покажи


 
default ©   (2003-11-19 16:21) [29]

сделай себе класс...с таймером, через определённый интервал времени у тебя будет надпись вертеться, скорость тем самым сможешь задавать(вращения), крутить по часовой, против часовой, угловой размер одного поворота надписи...


 
DAndrew   (2003-11-19 16:37) [30]

Ниже код (пробую вращать строку по часовой стрелке - не получается):

procedure TForm1.Button1Click(Sender: TObject);
     var LogFont: TLogFont;
         s: string;
         w, h, X, Y:Integer;
         FGrad: Extended;
begin
 Inc(FAngle, 20);
 FAngle:= -FAngle;

 s:= "My name Andrew";

 with Image1.Canvas do begin
      Font.Name := "Times New Roman";
      Font.Size := 36;
      Font.Style:= [fsBold];

      GetObject(Font.Handle, SizeOf(LogFont), @LogFont);

      with LogFont do begin
           lfOrientation := FAngle*10;
           lfEscapement := lfOrientation; end;

      Font.Handle:= CreateFontIndirect(LogFont);

      Ellipse(195, 195, 205, 205);
      w:= TextWidth (s);
      h:= TextHeight(s);

      Brush.Color:= clInfoBk; //clWhite;
      FillRect(ClientRect);
      Brush.Style:= bsClear;

      FGrad:= DegToRad(FAngle);
      X:= 200 - Round( cos(FGrad)*w + h*sin(FGrad)) div 2;
      Y:= 200 - Round(-sin(FGrad)*w + h*cos(FGrad)) div 2;

      TextOut(X, Y, s);
      Ellipse(200 - 5, 200 - 5, 200 + 5, 200 + 5); end;

 Image1.Invalidate;
end;

Что не так?

Андрей!


 
DAndrew   (2003-11-19 16:38) [31]

Ниже код (пробую вращать строку по часовой стрелке - не получается):

procedure TForm1.Button1Click(Sender: TObject);
     var LogFont: TLogFont;
         s: string;
         w, h, X, Y:Integer;
         FGrad: Extended;
begin
 Inc(FAngle, 20);
 FAngle:= -FAngle;

 s:= "My name Andrew";

 with Image1.Canvas do begin
      Font.Name := "Times New Roman";
      Font.Size := 36;
      Font.Style:= [fsBold];

      GetObject(Font.Handle, SizeOf(LogFont), @LogFont);

      with LogFont do begin
           lfOrientation := FAngle*10;
           lfEscapement := lfOrientation; end;

      Font.Handle:= CreateFontIndirect(LogFont);

      Ellipse(195, 195, 205, 205);
      w:= TextWidth (s);
      h:= TextHeight(s);

      Brush.Color:= clInfoBk; //clWhite;
      FillRect(ClientRect);
      Brush.Style:= bsClear;

      FGrad:= DegToRad(FAngle);
      X:= 200 - Round( cos(FGrad)*w + h*sin(FGrad)) div 2;
      Y:= 200 - Round(-sin(FGrad)*w + h*cos(FGrad)) div 2;

      TextOut(X, Y, s);
      Ellipse(200 - 5, 200 - 5, 200 + 5, 200 + 5); end;

 Image1.Invalidate;
end;

Что не так?

Андрей!


 
default ©   (2003-11-19 18:41) [32]

" Inc(FAngle, 20);
FAngle:= -FAngle;" --> Dec(FAngle, 20)


 
DAndrew   (2003-11-19 19:40) [33]

default, MBo!

Спасибо!
Всем спасибо за общение!

Андрей!


 
_Zergey   (2003-11-22 10:48) [34]

Не обратил внимания исправляюсь :)
На основе того чем делюсь был мной написан компонент на основе TLabel с возможностью вращения текста на любой угол с работающим при етом AutoSize!

procedure AngledTextOut(DC:HDC;const Text:string;cx,cy:integer;Angle:single;
Alignment:TAlignment);
var
Pt:array of TPoint;
ps:PChar;
psa:TList;
i:integer;
s:string;
begin
SetString(s,PChar(Text),Length(Text));
psa:=TList.Create;
try
 TextToStrArr(psa,PChar(s));
 SetLength(Pt,psa.Count+1);
 Int64(Pt[0]):=0;
 for i:=1 to psa.Count do
 begin
  ps:=psa[i-1];
  GetTextExtentPoint(DC,ps,StrLen(ps),TSize(Pt[i]));
  with Pt[0] do
  begin
   x:=Max(x,Pt[i].x);
   ps:=Pointer(Pt[i].y);
   Pt[i].y:=y;
   Inc(y,Integer(ps))
  end
 end;
 for i:=1 to psa.Count do
 with Pt[i] do
 case Alignment of
  taCenter:x:=(Pt[0].x-x) shr 1;
  taRightJustify:x:=Pt[0].x-x
  else x:=0
 end;
 with Pt[0] do
 begin
  x:=x shr 1;
  y:=y shr 1
 end;
 RotatePt(Pt,Angle);
 with Pt[0] do OffsetPt(Pt,cx-x,cy-y);
 for i:=1 to psa.Count do
 begin
  ps:=psa[i-1];
  with Pt[i] do TextOut(DC,x,y,ps,StrLen(ps))
 end
finally
 psa.Free
end
end;

procedure RotatePt(var Pt:array of TPoint;Angle:single);
var
i,x0,y0,xb:integer;
s,c:extended;
begin
if Length(Pt)>0 then
begin
 x0:=Pt[0].x;
 y0:=Pt[0].y;
 SinCos(Angle,s,c);
 for i:=1 to High(Pt) do
 with Pt[i] do
 begin
  Dec(x,x0);
  Dec(y,y0);
  xb:=x;
  x:=Round((xb*c)-(y*s))+x0;
  y:=Round((y*c)+(xb*s))+y0
 end
end
end;

function PolygonRect(const Pt:array of TPoint):TRect;
var
i:integer;
begin
Result.TopLeft:=Pt[0];
Result.BottomRight:=Pt[0];
if High(Pt)>0 then
for i:=1 to High(Pt) do
with Result,Pt[i] do
begin
 if x<Left then Left:=x else
 if x>Right then Right:=x;
 if y<Top then Top:=y else
 if y>Bottom then Bottom:=y
end
end;


 
_Zergey   (2003-11-22 10:52) [35]

и есче :)...

procedure TextToStrArr(List:TList;Text:PChar);
var
p:PChar;
begin
List.Clear;
p:=Text;
while p^<>#0 do
if p^=#13 then
begin
 p^:=#0;
 List.Add(Text);
 Inc(p);
 Inc(p);
 Text:=p
end
else Inc(p);
List.Add(Text)
end;


 
_Zergey   (2003-11-22 11:00) [36]

воощет я полагал почемута, что названия процедур грят сами за себя и написать их код, как 2б обнулить!



Страницы: 1 вся ветка

Форум: "Media";
Текущий архив: 2004.03.28;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.035 c
14-1077808466
Mentov
2004-02-26 18:14
2004.03.28
Формат передачи логина/пароля в прокси HTTP


6-1073907626
Anatolik
2004-01-12 14:40
2004.03.28
kak c помошью компанента WebBrowser можно соединится через


4-1073209698
LexaTyukha
2004-01-04 12:48
2004.03.28
Обработка остановки сервиса.


1-1078840598
bn2
2004-03-09 16:56
2004.03.28
непонятное поведение компилятора


1-1078909467
RatLion
2004-03-10 12:04
2004.03.28
Как показать код исполняемый во время выполнения?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский