Генерирование линий заданной длины

0 голосов
спросил 18 Март, 10 от dravig (1,240 баллов) в категории Программные продукты Esri
    Народ. Помогите написать скрипт по следующему алгоритму:
Есть точечная тема с полем числовых значений и линия, их соединияющая. Нужно для каждой точки построить линии, перпендикулярные главной, причем длина их должна браться из атрибутов точечной темы.

Буду очень благодарен.

10 Ответы

0 голосов
ответил 18 Март, 10 от TDenis (42,620 баллов)
И что конкретно вызывает у вас затруднения?
0 голосов
ответил 19 Март, 10 от dravig (1,240 баллов)
    собсно, все описанное и вызывает затруднения...
0 голосов
ответил 19 Март, 10 от TDenis (42,620 баллов)
Это в институте такие задачки задают?

Без обид, но вряд ли тут подскажут.
Подсказывают, если алгоритм интересный (поиск перпендикуляров к отрезку, нормирование и умножение к таким не относятся), либо если у человека действительно что-то не получается (т.е. он хотя бы пробует сам), либо если задача типовая и скрипт уже готов.
А такое писать всем будет просто лень, хотя это и займёт 5-10 минут.
Хотя может вам и повезёт, не знаю.
Удачи!
0 голосов
ответил 20 Март, 10 от pooperec (10,820 баллов)
TDenis - правильно написал...
Я, например, подсказываю:
1. (без издёвок) если алгоритм интересный (с).
2. (с издёвками) если задача типовая и скрипт уже готов.
3. (с понимание, и иногда издёвками) если у человека действительно что-то не получается (т.е. он хотя бы пробует сам).

А такие формулировки, звучат как "решите за меня мою проблему", а то мне самому не досуг...
0 голосов
ответил 22 Март, 10 от Lord (3,920 баллов)
'BZPIP.Angle обязательно так назвать скрипт, он вызывается в следующем скрипте
'Внутренняя функция, возвращающая угол наклона линии в радианах
'заданной координатами (x1, y1) - (x2, y2) - 4 параметра
'или двумя точками p1-p2                   - 2 параметра
'или линией line                           - 1 параметр

if (Self.Count=4) then
p1= Self.Get(0)@Self.Get(1)
p2= Self.Get(2)@Self.Get(3)
elseif (Self.Count=2) then
p1= Self.Get(0)
p2= Self.Get(1)
elseif (Self.Count=1) then
p1= Self.Get(0).ReturnStart
p2= Self.Get(0).ReturnEnd
else Return 0
end
pi= Number.GetPi d= p2-p1 angle= (d.GetY/d.GetX).atan
if (d.GetX<0) then
angle= angle+pi
elseif (d.GetY<0) then   
angle= angle+pi+pi
end
Return angle '.AsDegrees

следующий скрипт повесить на панель инструментов вида
условия: активная тема линейная и включена на редактирование
в теме выделен один отрезок линии (линия между 2-мя точками
выбрать этот инструмент
щелкнуть мышкой ВОЗЛЕ точки отрезка с той стороны, в какую сторону провести перпендикуляр
В линейной теме появится перпендикуляр заданной длины
если нарисовался в другую сторону, этот перпенд удалить и щелкнуть с другой сороны.
подработав этот скрипт можно решить и вашу ситуацию
пока

'bzpip.PerpendicularForLine
'построение перпендикуляра к линии к точке в конце линии
    theView = av.getactivedoc
    theTheme=theView.GetActiveThemes.Get(0)
    if (theTheme.GetFtab.IsEditable.not) then
      MsgBox.Error("Тема"++theTheme.GetSrcName.GetName++"не включена на редактирование",
                  "Перпендикуляр")
      exit
    end
        theFtab=theTheme.GetFtab
        theClass=theFtab.GetShapeClass.GetClassName
           if ( theClass<>"PolyLine") then
               MsgBox.Error("Тема<"++theTheme.GetSrcName.GetName++"> не линейная",
                            "Перпендикуляр")
               exit
           end
aDisp=theView.GetDisplay
aSel=theFtab.GetSelection
pi=180.AsRadians
z=vector.Make(0,0,1)
aCount=aSel.Count
if (aCount=0) then
    MsgBox.Error("Нет выделенных объектов. Обработка не проводится",
               "Перпендикуляр")
    exit
end

if (aCount>1) then
    MsgBox.Error("Выделено более одного объекта. Обработка не проводится",
               "Перпендикуляр")
    exit
end
aPoint=theView.GetDisplay.ReturnUserPoint
'rectLine=rect.Make(312993@626515,10@40)
PointList={} PointNew={}
aPosition=aSel.GetNextSet(-1)
theShape=theFtab.FindField("shape")
anObj=theFtab.ReturnValue(theShape,aPosition)
LineList=anObj.explode
dist=1000
for each rec in LineList
    for each rec1 in rec.AsList
      for each rec2 in 0..(rec1.AsList.Count-2)
        aLine=Line.Make(rec1.Get(rec2),rec1.Get(rec2+1))
        dTemp=aPoint.Distance(aLine)
        if (dist>dTemp) then dist=dTemp end
      end
    end
end
for each rec in LineList
    for each rec1 in rec.AsList
      for each rec2 in 0..(rec1.AsList.Count-2)
        aLine=Line.Make(rec1.Get(rec2),rec1.Get(rec2+1))
        dTemp=aPoint.Distance(aLine)
        if (dist=dTemp) then
          MyLine=aLine
        end
      end
    end
end
sPoint=MyLine.returnStart
ePoint=MyLine.returnEnd
dist1=sPoint.Distance(aPoint)
dist2=ePoint.Distance(aPoint)

if (dist1<dist2) then
MyPoint=sPoint st=1
else
MyPoint=ePoint st=2
end

ugMyLine=av.Run("BZPIP.Angle",{0@0,ePoint-sPoint}).AsDegrees
ugMyPoint=av.Run("BZPIP.Angle",{0@0,aPoint-sPoint}).AsDegrees

if (st=1) then
        aVec=vector.Make(sPoint.GetX-ePoint.GetX,sPoint.GetY-ePoint.GetY,0)
      if (ugMyLine>ugMyPoint) then
        aVec90=aVec.Rotate(90,z)
      else
        aVec90=aVec.Rotate(270,z)
      end
elseif (st=2) then
    aVec=vector.Make(ePoint.GetX-sPoint.GetX,ePoint.GetY-sPoint.GetY,0)
if (ugMyLine<ugMyPoint) then
    aVec90=aVec.Rotate(90,z)
else
    aVec90=aVec.Rotate(270,z)
end
end
intensityValue=msgbox.Input("Введите длину перпендикуляра","Построение перпендикуляра","100")
if (intensityValue=Nil) then exit end
intensityValue=intensityValue.Translate(",",".").AsNumber
aVec90.SetIntensity (intensityValue)

theFtab.BeginTransaction
new=theFtab.addrecord
if (st=1) then
theFtab.SetValue(theShape,new,PolyLine.Make({{sPoint,(aVec90.AsPoint+sPoint)}}))
else
theFtab.SetValue(theShape,new,PolyLine.Make({{ePoint,(aVec90.AsPoint+ePoint)}}))
end

theFtab.EndTransaction
theTheme.invalidate(true)
theView.Invalidate
0 голосов
ответил 22 Март, 10 от dravig (1,240 баллов)
Lord, спасибо огромное...
0 голосов
ответил 22 Март, 10 от dravig (1,240 баллов)
  "Это в институте такие задачки задают? "
  и далее ответ на сообщение pooperec

Задача, к сожалению, производственная.  Поскольку в программировании не силен, максимум что могу сделать - это подогнать скрипт с похожей задачей (перелопатив при этом кучу интернет-ресурсов) под свою...

   "А такие формулировки, звучат как "решите за меня мою проблему", а то мне самому не досуг..."

Возможно, это так и звучит... но все мы падки на "халяву"....
0 голосов
ответил 22 Март, 10 от TDenis (42,620 баллов)
dravig, значит вам повезло.

Lord,
Ого, радианы, повороты, арктангенсы. Надеюсь вы не писали это специально для данного случая, и это просто универсальное типовое решение, для поворотов на любые углы.

В нашем случае, если начальная точка отрезка (совпадающая с точкой слоя, из которой будут исходить перпендикуляры) имеет координаты (X0, Y0), а конечная точка отрезка имеет координаты (X1, Y1), то координаты вторых вершин перпендикуляров считаются:
(X0 - Dy, Y0 + Dx)
(X0 + Dy, Y0 - Dx)
где Dx = X1 - X0,
Dy = Y1 - Y0.
После чего нормируем перпендикуляры и домножаем на необходимую длину. Можно оптимизировать, посчитать один перпендикуляр, для него рассчитать нормированные Dx', Dy'. Второй перпендикуляр рассчитать можно будет суммированием, без умножения и корней.
0 голосов
ответил 23 Март, 10 от Lord (3,920 баллов)
Ребята, не стреляйте в пианиста, играет, как умеет.
Скрипты моей молодости
0 голосов
ответил 23 Март, 10 от TDenis (42,620 баллов)
Скрипты моей молодости

А, ну раз это уже готовые скрипты, тогда понятно. Извините)
Добро пожаловать на сайт Вопросов и Ответов, где вы можете задавать вопросы по GIS тематике и получать ответы от других членов сообщества.
...