QGIS에서 섹터 라이트를 작성 하시겠습니까?


24

QGIS 2.18을 사용하고 있습니다. 내비게이션 목적으로지도에서 섹터 라이트를 만들어야합니다.

500 개가 넘는 부표, 비콘 및 등대가있는 셰이프 파일에 becon_id, 시작 각도, 끝 각도 및 색상을 제공하는 필드로 라이트 섹터 데이터가 있습니다. 각 비콘마다 하나의 광 섹터 (예 : 흰색 섹터)를 나타내는 많은 행이있을 수 있습니다.

최종 결과는 다음과 같습니다. 색상 필드 (RGW)에 문자로 색상이 표시되고 부표 / 비콘 / 등대에서 100m에서 1000m까지 점선으로 표시되는 올바른 색상의 광 섹터.

이것은 아마도 규칙 기반 심볼로 생성되어야하지만 파이썬이 필요합니까?

여기에 이미지 설명을 입력하십시오

다음은 114와 154도 사이의 녹색 섹터, 154와 168도 사이의 흰색 섹터, 168과 237도 사이의 빨간색 섹터, 녹색이있는 등대 (불행히도 위의 것이 아님)에 대한 쉐이프 파일 데이터의 예입니다. 237 ~ 314도 사이의 섹터, 314 ~ 320도 사이의 흰색 섹터, 320 ~ 337 도의 빨간색 섹터 (어떤 이유로 0은 북쪽이 아니라 남쪽) :

shapefile 테이블 예



2
예상 한 결과가 정확히 무엇인지 설명하여 샘플 데이터 세트를 업로드하고 질문을 편집 할 수 있습니까? 첨부 된 이미지에서 나는 기호와 색상의 우주만을 볼 수 있습니다.
mgri

1
예제 데이터가 여기에 도움이 될 것입니다. 섹터 라이트 당 하나의 기능 또는 부표 당 하나의 기능이 있습니까? Wedge Buffer 플러그인이 여기에 도움이 될 수 있지만 이것이 얼마나 쉬운지는 데이터 설정 방법에 달려 있습니다.
Steven Kay

안녕 @ mgri와 Steven, 나는 예제 데이터를 추가하고 질문을 더 명확하게 만들려고 노력했습니다 :), 감사합니다!
Benjamin Donner

1
@ mgri 선은 변수가 아니지만 이미지와 같이 광 섹터 사이에서 900m 긴 선으로 정적으로 표시되어야하는 선입니다. 예상 기준 시스템.
Benjamin Donner

답변:


50

편집 특정 상황 (특정 각도 값으로 인해)을 관리하고 둥근 각도가 정의 될 때 점선을 표시하지 않도록 답변을 편집했습니다.


나는 규칙 기반의 상징과 라벨링에만 반복해서 해결책을 제안한다.

시작하기 전에 원하는 결과를 재현하기 위해 수행해야 할 최소한의 설명에주의를 기울일 것이라고 강조하고 싶습니다. 이는 다른 작은 매개 변수 (예 : 크기, 너비 등)를 쉽게 조정할 수 있음을 의미합니다. 당신의 요구를 더 잘 맞추기 위해.

또한, 경우이 솔루션은 작동 당신이 생각 0정도가 아니라 남한의 북한 (경우이다 0남쪽, 대신, 그것은 합산 충분하다 180각도로하는 계약 식에 '90'을 표시 할 때마다 값을, 예를 들어이 cos(radians(90))될 것입니다 cos(radians(180 + 90))). 더 일반적인 솔루션을 제공하기 위해이 작업을 선호했습니다.


스타일링

점을 a로 렌더링하고 Single symbol1 Simple Marker~ 3 개의 Geometry generator심볼 레이어 로 반복합니다 .

여기에 이미지 설명을 입력하십시오

추가 설명에서 위의 이미지에서 동일한 순서의 기호를 따릅니다.

1) 단순 마커

크기가 3mm이고 너비가 0.4mm 인 검은 별의 기본 기호 (이 자습서에서는 더 쉬운 부분)를 선택했습니다.

2) 지오메트리 생성기 1 번

새 심볼 레이어를 추가하고 Geometry generator유형을 선택하십시오 .

여기에 이미지 설명을 입력하십시오

이 표현식을 Expression필드 에 삽입하십시오 .

CASE
WHEN abs( "ALKUKULMA" - "LOPPUKULMA") < 360
THEN
make_line(
 $geometry,
 make_point(
  $x + 1000*cos(radians(90 - "ALKUKULMA")),
  $y + 1000*sin(radians(90 - "ALKUKULMA"))
  )
)
END

우리는 광 섹터가 시작되는 지점을 가리키는 첫 번째 라인을 정의했습니다. 이 선의 길이는 1000m이며, 섹터 라이트의 개방 각도가 둥근 각도가 아닌 경우에만 생성됩니다 (선이 전체 원을 깰 수 있음을 방지하기 위해 발생 함).

3) 지오메트리 생성기 2 번

위와 동일하지만이 단계에서는 다음 표현식을 사용해야합니다.

CASE
WHEN abs( "ALKUKULMA" - "LOPPUKULMA") < 360
THEN
make_line(
 $geometry,
 make_point(
  $x + 1000*cos(radians(90 - "LOPPUKULMA")),
  $y + 1000*sin(radians(90 - "LOPPUKULMA"))
  )
)
END

우리는 라이트 섹터가 끝나는 지점을 향한 첫 번째 라인을 정의했습니다. 이 선의 길이는 1000m이며, 섹터 라이트의 개방 각도가 둥근 각도가 아닌 경우에만 생성됩니다 (선이 전체 원을 깰 수 있음을 방지하기 위해 발생 함).

4) 지오메트리 생성기 3 번

이 표현식을 Expression필드 에 삽입하십시오 .

CASE

WHEN abs("ALKUKULMA" - "LOPPUKULMA") <= 180 AND "ALKUKULMA" >= "LOPPUKULMA"
THEN
difference(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x + 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y + 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") <= 180 AND "ALKUKULMA" <= "LOPPUKULMA"
THEN
intersection(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x + 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y + 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") > 180 AND "ALKUKULMA" >= "LOPPUKULMA"
THEN
intersection(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x - 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y - 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") > 180 AND "ALKUKULMA" <= "LOPPUKULMA"
THEN
difference(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x - 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y - 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)


END

우리는 방금 빛의 시작점과 끝점 사이의 호를 정의했습니다 ( 반지름 900m의 원의 경계와 교차 2000하는 다각형 을 만들려고하기 때문에 임의의 값입니다 ).

또한 "VARIS"현장에 저장되는 색상을 설정해야 합니다. 이를 위해서는 사용자 정의 표현식으로 지정해야합니다. 아래 이미지의 화살표를 따르십시오.

여기에 이미지 설명을 입력하십시오

그런 다음 Edit...버튼 을 클릭 한 후이 표현식을 입력하십시오 .

CASE
WHEN  "VARIS" = 'vi' THEN color_rgb(51,160,44)
WHEN "VARIS" = 'v' THEN color_rgb(255,255,255)
WHEN "VARIS" = 'p' THEN color_rgb(227,26,28)
END

이 심볼 레이어의 경우 두 줄을 만들었습니다. 위 줄은 사용할 색상을 정의하고 (실제로이 사용자 정의 표현식을 설정합니다) 아래쪽 줄은 검은 색 테두리를 정의하는 데 유용합니다 ( 상단 라인 중 하나보다 큰 너비). 설정 또한 기억 Flat으로 Cap style중복 색상을 피하기위한 두 라인.


라벨링

1) 라벨 설정

Layer Properties>로 이동하여 Labels평소와 같이 빨간색 화살표를 따릅니다.

여기에 이미지 설명을 입력하십시오

다음 식을 입력하십시오.

CASE
WHEN "VARIS" = 'vi' THEN 'G'
WHEN "VARIS" = 'v' THEN 'W'
WHEN "VARIS" = 'p' THEN 'R'
END

"VARIS"필드에 저장된 값을 사용하여 색상 규칙을 정의했습니다 .

2) 라벨 배치 설정

메뉴에서 Placement옵션을 Labels선택하고을 선택하십시오 Offset from point.

그런 다음 아래 이미지를 참조하십시오.

여기에 이미지 설명을 입력하십시오

빨간색 화살표를 따라이 표현식을 입력하십시오.

CASE
WHEN "ALKUKULMA" > "LOPPUKULMA"
THEN
concat(
 -1000*cos(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2)),
  ',',
  1000*sin(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2))
)
WHEN "ALKUKULMA" <= "LOPPUKULMA"
THEN
concat(
 1000*cos(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2)),
  ',',
  -1000*sin(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2))
)
END

그런 다음 녹색 화살표를 따라 다음 표현식을 입력하십시오.

CASE
WHEN "ALKUKULMA" >= "LOPPUKULMA"
THEN
180-(("ALKUKULMA" + "LOPPUKULMA")/2)
WHEN "ALKUKULMA" < "LOPPUKULMA"
THEN
- (("ALKUKULMA" + "LOPPUKULMA")/2)
END

최종 결과

이전 작업을 올바르게 수행 한 경우 다음 결과를 얻을 수 있습니다.

여기에 이미지 설명을 입력하십시오

보너스

마이너 매개 변수가이 답변에서 완전히 다루기에는 너무 많으므로 여기 에 스타일을 첨부했습니다 . 텍스트 편집기에서이 코드를 열고 QGIS 레이어 스타일 파일 (예 : .qml확장명) 로 저장할 수 있습니다.

위의 스타일은 QGIS 2.18.4를 사용하여 작성되었습니다 (사용 중인 쉐이프 파일의 이름이 같아야 함).


3
멋지게 보입니다. 지오메트리 생성기의 힘을 보여줍니다. 렌더링 속도가 느립니까?
HeikkiVesanto

2
@Vesanto 나는 6 개의 특징 (6 개의 섹터 라이트)을 가진 한 지점에서 테스트했고 즉시 렌더링했습니다. 프로 바이더 나 비슷한 것을 호출 할 필요는 없지만 Well Know Text와 같은 몇 가지 수학 연산과 도형 만 있기 때문에 수백 가지 기능을 처리 할 때도 빠르다고 생각합니다.
mgri

2
이와 같은 질문 / 답변은 실제로 다양한 QGIS가 가능한 방법을 보여줍니다!
Joseph

1
@ mgri 당신은 훌륭하고 훌륭한 솔루션이며 많은 작업과 관련된 훌륭한 설명 인 The Master입니다. 감사합니다!
Benjamin Donner

1
@mgri이 지역의 산은 당신의 이름을 should어야합니다. 조금 테스트했지만 추가 솔루션에 아무런 문제가 없습니다. :)!
Benjamin Donner
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.